-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathkeys.py
233 lines (201 loc) · 6.9 KB
/
keys.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
import sys, time, json, os
import keyboard # https://github.com/boppreh/keyboard
if __name__ == "__main__":
import argparse
script=[]
dontprint = True
lastevent = None
actualLine = None
delay_threshold=200
keys_count=0
input_log_file = None
output_log_file = None
ducky_file = None
# I don't wanna modify the library...
# but I did it anyway: https://github.com/boppreh/keyboard/pull/429
def _getjson(a, ensure_ascii=False):
attrs = dict(
(attr, getattr(a, attr)) for attr in ['event_type', 'scan_code', 'name', 'time', 'device', 'is_keypad','modifiers']
if not attr.startswith('_')
)
return json.dumps(attrs, ensure_ascii=ensure_ascii)
rev_canonical_names = {
'next': 'pagedown',
'prior': 'pageup',
"select": "end",
"find": "home",
"space": "spacebar",
}
scan_codes = {
99: "PRINTSCREEN",
125: "GUI",
126: "GUI",
142: "MOON",
100: "ALTGR",
}
def cleanup():
global script
global dontprint
global lastevent
global actualLine
global input_log_file
global output_log_file
global ducky_file
global keys_count
script=[]
dontprint = True
lastevent = None
actualLine = None
input_log_file = None
output_log_file = None
ducky_file = None
keys_count = 0
def save_pressed_keys(e):
global keys_count
global script
#Save only keys to get no errors in keypress logs
if e.scan_code in scan_codes:
e.name = scan_codes[e.scan_code]
if e.name in rev_canonical_names:
e.name = rev_canonical_names[e.name]
with open("/tmp/.duckylog", "a") as af:
af.write(_getjson(e) + ",")
if e.event_type == "up":
keys_count = keys_count + 1
def print_pressed_keys(e):
global script
global lastevent
global actualLine
global dontprint
if e.scan_code in scan_codes:
e.name = scan_codes[e.scan_code]
if e.name in rev_canonical_names:
e.name = rev_canonical_names[e.name]
if output_log_file is not None:
with open(output_log_file, "a") as af:
af.write(_getjson(e) + ",")
e.name = (e.name.upper(), e.name)[len(e.name) == 1]
if lastevent is not None:
if lastevent.event_type == "up" and e.event_type == "down":
delay = round((e.time-lastevent.time)*1000)
if delay >= delay_threshold:
if actualLine is not None and actualLine.startswith("STRING"):
script.append(actualLine)
actualLine = None
script.append("DELAY %s" % delay)
if e.event_type == "down":
dontprint = False
if len(e.name) == 1 and not e.modifiers and not keyboard.is_modifier(e.scan_code):
if actualLine is None:
actualLine = "STRING "
elif e.name in actualLine and not actualLine.startswith("STRING"):
pass
actualLine = actualLine + e.name
else:
if actualLine is not None:
if e.name in actualLine:
pass
if actualLine.startswith("STRING"):
if actualLine is not None:
script.append(actualLine)
actualLine = e.name
else:
if e.name not in actualLine:
actualLine = actualLine + " " + e.name
else:
actualLine = e.name
else: #up
if actualLine is not None:
if not actualLine.startswith("STRING"):
if e.name in actualLine:
if not dontprint:
script.append(actualLine)
actualLine = actualLine.replace(e.name, "").replace(" "," ").strip()
actualLine = (actualLine, None)[actualLine == ""]
if actualLine is not None:
dontprint = True
lastevent = e
i = actualLine
def hook(duckyfile=None, logfile=None):
global ducky_file
global output_log_file
if duckyfile is not None and duckyfile != "":
ducky_file = duckyfile
if logfile is not None and logfile != "":
output_log_file = logfile
with open(output_log_file, "w") as wf:
wf.write("[")
os.system("rm -f /tmp/.duckylog")
with open("/tmp/.duckylog", "w") as wf:
wf.write("[")
keyboard.hook(save_pressed_keys)
def fromFile(inputfile,duckyfile=None):
global ducky_file
global script
global output_log_file
if duckyfile is not None:
ducky_file=duckyfile
output_log_file = None
i = script
with open(inputfile) as json_file:
data = json.load(json_file)
for var in data:
x = json.dumps(var)
if x != "{}":
print_pressed_keys(keyboard.KeyboardEvent(**json.loads(x)))
if actualLine is not None:
i.append(actualLine)
if ducky_file is not None:
with open(ducky_file, "w") as wf:
for var in i:
wf.write(var + "\n")
cleanup()
return i
def stop_gethook():
global script
i = script
keyboard.unhook_all()
if actualLine is not None:
i.append(actualLine)
if output_log_file is not None:
with open(output_log_file, "a") as af:
af.write("{}]")
if len(i) == 0:
os.remove(output_log_file)
if ducky_file is not None:
with open(ducky_file, "w") as wf:
for var in i:
wf.write(var + "\n")
if len(i) == 0:
os.remove(ducky_file)
with open("/tmp/.duckylog", "a") as af:
af.write("{}]")
x = output_log_file
fromFile("/tmp/.duckylog", ducky_file)
if x is not None:
os.system("cp -f /tmp/.duckylog " + x)
cleanup()
return i
if __name__ == "__main__":
parser = argparse.ArgumentParser(description='Keystrokes to duckyscript')
parser.add_argument("-d", "--ducky", action="store", dest="ducky", default=None, help="Duckyscript output")
parser.add_argument("-v", "--verbose", action="store_true", dest="verbose", default=None, help="Verbose output")
parser.add_argument("-o", "--output-log", action="store", dest="outputlog", default=None, help="Raw json log output")
parser.add_argument("-i", "--input-log", action="store", dest="analyzelog", default=None, help="Analyze from raw json log output")
arguments = parser.parse_args()
if arguments.analyzelog is None:
if arguments.verbose:
print("Initializing...")
hook(arguments.ducky,arguments.outputlog)
if arguments.verbose:
print("Done! Hit ctrl+c to stop!")
try:
keyboard.wait()
except KeyboardInterrupt:
if arguments.verbose:
print("Leaving...")
for var in stop_gethook():
print(var)
else:
for var in fromFile(arguments.analyzelog,arguments.ducky):
print(var)