-
Notifications
You must be signed in to change notification settings - Fork 5
/
code.py
137 lines (120 loc) · 5.48 KB
/
code.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
# ⠀⠀⠀⠀⠀⠀⠀⠀ ⣤⡶⠿⠿⠷⣶⣄⠀⠀⠀⠀⠀
# _ _ ___ _ ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ ⣰⡿⠁⠀⠀⢀⣀⡀⠙⣷⡀⠀⠀⠀
# | \| |___ ___| \ _ _ __| |___ _ ⠀⠀⠀⡀⠀⠀⠀⠀⠀⢠⣿⠁⠀⠀⠀⠘⠿⠃⠀⢸⣿⣿⣿⣿
# | .` / -_) _ \ |) | || / _| / / || |⠀ ⣠⡿⠛⢷⣦⡀⠀⠀⠈⣿⡄⠀⠀⠀⠀⠀⠀⠀⣸⣿⣿⣿⠟
# |_|\_\___\___/___/ \_,_\__|_\_\\_, | ⢰⡿⠁⠀⠀⠙⢿⣦⣤⣤⣼⣿⣄⠀⠀⠀⠀⠀⢴⡟⠛⠋⠁⠀
# |__/ ⣿⠇⠀⠀⠀⠀⠀ ⠉⠉⠉⠉⠉⠁⠀⠀⠀⠀⠀⠈⣿⡀
# ⣿⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ ⢹⡇
# made with ❤️ by FLOCK4H ⣿⡆⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣼⡇
# Version 1.0 ⠸⣷⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢠⡿⠀
#⠀ ⠹⣷⣤⣀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣀⣰⡿⠁
#⠀⠀⠀ ⠉⠙⠛⠿⠶⣶⣶⣶⣶⠿⠟⠛⠉
import time
import board
from adafruit_hid.keyboard import Keyboard
from usb_hid import devices
from adafruit_hid.keycode import Keycode
import tools.keycodes as keycodes
from tools.detect_os import detect_os_by_sys, load_payload_from_file
from tools.analyzer import analyze_payload
import gc
from neopixel import NeoPixel
from os import listdir
from random import randint, uniform
from supervisor import runtime
runtime.autoreload = False
pixel = NeoPixel(board.NEOPIXEL, 1, brightness=0.05)
gc.collect()
class NeoDucky:
def __init__(self):
self.kc = keycodes.KeyCodes()
self.keyboard = Keyboard(devices)
self.active_toggles = set()
def handle_toggle(self, token):
if token in self.active_toggles:
self.keyboard.release(self.kc.toggles[token])
self.active_toggles.remove(token)
else:
self.keyboard.press(self.kc.toggles[token])
self.active_toggles.add(token)
def execute_payload(self, tokens):
for token in tokens:
if token.startswith('<') and token.endswith('>'):
if "time" in token[1:-1]:
pixel.fill((255, 255, 0)) # yellow
try:
sleep_time = float(token[token.find("time") + 4:-1])
time.sleep(sleep_time)
except ValueError:
print(f"Invalid time value in token '{token}'")
elif token in self.kc.system_chars:
pixel.fill((0, 255, 0)) # green
self.keyboard.send(self.kc.system_chars[token])
elif token in self.kc.toggles:
self.handle_toggle(token)
pixel.fill((0, 0, 255)) # blue
else:
pixel.fill((255, 165, 0)) # orange
else:
for char in token:
if char in self.kc.shift_char:
self.keyboard.press(Keycode.SHIFT)
self.keyboard.press(self.kc.shift_char[char])
self.keyboard.release_all()
pixel.fill((255, 0, 0))
elif char in self.kc.keys:
self.keyboard.send(self.kc.keys[char])
pixel.fill((0, 255, 255)) # cyan
else:
print(f"No keycode mapping found for '{char}'")
pixel.fill((255, 0, 255)) # magenta
for active_toggle in self.active_toggles:
self.keyboard.press(self.kc.toggles[active_toggle])
for toggle in list(self.active_toggles):
self.keyboard.release(self.kc.toggles[toggle])
self.active_toggles.clear()
pixel.fill((0, 255, 0))
def payloads_write(self, payload):
loop_payload = "<LOOP>" in payload
if loop_payload:
payload = payload.replace("<LOOP>", "")
tokens = analyze_payload(payload)
while True:
self.execute_payload(tokens)
for toggle in list(self.active_toggles):
self.keyboard.release(self.kc.toggles[toggle])
self.active_toggles.clear()
if not loop_payload:
break
# !!!
# REMOVE THE DELAY ONLY IF YOU SURE WHAT YOU DOING
# USING <LOOP> WITHOUT TIMERS IS DANGEROUSLY STUPID
# !!!
time.sleep(0.4)
def main():
ducky = NeoDucky()
payloads = load_payload_from_file()
payload, payload_mac = None, None
for p in payloads:
for k, v in p.items():
if k == "payload.txt":
payload = v # Max payload length in ver 1.0 is 1306 bytes
elif k == "payload_mac.txt":
payload_mac = v
os_detected = detect_os_by_sys()
print(f"Detected OS: {os_detected}")
gc.collect()
if os_detected == "macOS" and payload_mac is not None:
ducky.payloads_write(payload_mac)
elif payload is not None:
ducky.payloads_write(payload)
gc.collect()
while True:
r, g, b = randint(0, 255), randint(0, 255), randint(0, 255)
brights = uniform(0.08, 0.3)
pixel.fill((r, g, b))
pixel.brightness = brights
time.sleep(uniform(0.05, 0.2))
gc.collect()
if __name__ == "__main__":
main()