Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
hak5
GitHub Repository: hak5/usbrubberducky-payloads
Path: blob/master/payloads/library/general/Piano_Player/piano_player.py
2968 views
1
import argparse
2
from pathlib import Path
3
4
5
OS_DETECT_EXTENSION = Path(__file__).resolve().parents[4] / "payloads" / "extensions" / "os_detect.txt"
6
7
8
def parse_args():
9
parser = argparse.ArgumentParser()
10
parser.add_argument("notes", metavar="NOTES_FILE", help="Path to notes file")
11
parser.add_argument("payload", metavar="PAYLOAD_FILE", help="Save payload code to this file")
12
parser.add_argument("-p", "--press-mode", help="Deploy with press mode", action="store_true")
13
return parser.parse_args()
14
15
16
def generate_keymap(maps: str) -> dict:
17
keymap = {}
18
for exp in maps.split(" "):
19
note, key = exp.split("=")
20
keymap[note] = key
21
return keymap
22
23
24
def notes_to_code(roll: list, keymap: dict, tick: int, url: str, press_mode: bool) -> str:
25
# Adjust tick to account for note held duration
26
adjusted_tick = tick - 20
27
if adjusted_tick < 20:
28
raise Exception(f"tick ({tick}) is too low! Must be at least 40ms.")
29
30
code = ""
31
indent = ""
32
# Head
33
if not press_mode:
34
with open(OS_DETECT_EXTENSION) as f:
35
code += f.read() + "\n"
36
code += f"""IF ($_OS == WINDOWS) THEN
37
GUI r
38
ELSE IF ($_OS == MACOS) THEN
39
COMMAND SPACE
40
ELSE IF ($_OS == LINUX) THEN
41
CONTROL ESCAPE
42
ELSE
43
GUI
44
END_IF
45
46
DELAY 1000
47
STRING {url}
48
ENTER
49
DELAY 2000\n
50
"""
51
else:
52
indent = " "
53
code += "ATTACKMODE HID STORAGE\n\n"
54
55
# Function (common)
56
code += f"""FUNCTION tick()
57
DELAY {adjusted_tick}
58
END_FUNCTION\n
59
"""
60
61
if press_mode:
62
code += """WHILE TRUE
63
WAIT_FOR_BUTTON_PRESS
64
"""
65
66
# Each row is one or more note press, or a rest. Notes and rests are
67
# held for 20ms (not configurable), but the total interval between rows is
68
# approx. the specified tick time.
69
for row in roll:
70
notes = [n for n in row.split(" ") if n != "---"]
71
for note in notes:
72
code += f"{indent}HOLD {keymap[note]}\n"
73
code += f"{indent}DELAY 20\n"
74
for note in notes:
75
code += f"{indent}RELEASE {keymap[note]}\n"
76
code += f"{indent}tick()\n"
77
if press_mode:
78
code += "END_WHILE"
79
80
return code
81
82
83
if __name__ == "__main__":
84
args = parse_args()
85
with open(args.notes) as f:
86
notes = [line.strip() for line in f.readlines()]
87
88
tick = int(notes[0].split("ms")[0])
89
url = notes[1]
90
keymap = generate_keymap(notes[2])
91
roll = notes[4:]
92
93
with open(args.payload, "w") as f:
94
f.write(notes_to_code(roll, keymap, tick, url, args.press_mode))
95
96