-
Notifications
You must be signed in to change notification settings - Fork 5
/
arducky.ino
301 lines (279 loc) · 11.4 KB
/
arducky.ino
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
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
/**********************************************************/
/* [+] Title: Arduino Ducky Script Interpreter */
/* [+] Author: Baptiste M. (Creased) */
/* [+] Website: bmoine.fr */
/* [+] Twitter: @Creased_ */
/**********************************************************/
/**
* Libraries
**/
// SD card read/write
#include <SPI.h>
#include <SD.h>
// Keyboard Message
#include "Keyboard.h"
/**
* Variables
**/
#define KEY_MENU 0xED
#define KEY_PAUSE 0xD0
#define KEY_NUMLOCK 0xDB
#define KEY_PRINTSCREEN 0xCE
#define KEY_SCROLLLOCK 0xCF
#define KEY_SPACE 0xB4
#define KEY_BACKSPACE 0xB2
File myFile; // File data buffer
char *fileName = (char*)"script.txt"; // File containing payload placed on SD Card
const int LED = 17; // RX LED pin
/**
* Functions
**/
void setup() {
// Initialize digital pin LED_BUILTIN as an output
pinMode(LED, OUTPUT);
// Initialize SD Card
if (!SD.begin(4)) {
for (int i=0; i <= 25; i++) {
digitalWrite(LED, HIGH); // turn the LED on (HIGH is the voltage level)
delay(100); // wait for a second
digitalWrite(LED, LOW); // turn the LED off by making the voltage LOW
delay(100); // wait for a second
}
return;
}
if (SD.exists(fileName)) {
// Open the file for reading (fill myFile with char buffer)
myFile = SD.open(fileName, FILE_READ);
// Check if the file has successfully been opened and continue
if (myFile) {
// Initialize control over keyboard
Keyboard.begin();
// Process lines from file with LF EOL (0x0a), not CR+LF (0x0a+0x0d)
String line = "";
while (myFile.available()) { // For each char in buffer
// Read char from buffer
char c = myFile.read();
// Process char
if ((int) c == 0x0a){ // Line ending (LF) reached
processLine(line); // Process script line by reading command and payload
line = ""; // Clean the line to process next
} else if((int) c != 0x0d) { // If char isn't a carriage return (CR)
line += c; // Put char into line
}
}
// Close the file
myFile.close();
} else { // File can't be loaded
for (int i=0; i <= 25; i++) {
digitalWrite(LED, HIGH); // turn the LED on (HIGH is the voltage level)
delay(250); // wait for a second
digitalWrite(LED, LOW); // turn the LED off by making the voltage LOW
delay(250); // wait for a second
}
}
// End control over keyboard
Keyboard.end();
} else {
for (int i=0; i <= 25; i++) {
digitalWrite(LED, HIGH); // turn the LED on (HIGH is the voltage level)
delay(100); // wait for a second
digitalWrite(LED, LOW); // turn the LED off by making the voltage LOW
delay(100); // wait for a second
}
}
}
void processLine(String line) {
/*
* Process Ducky Script according to the official documentation (see https://github.com/hak5darren/USB-Rubber-Ducky/wiki/Duckyscript).
*
* (1) Commands without payload:
* - ENTER
* - MENU <=> APP
* - DOWNARROW <=> DOWN
* - LEFTARROW <=> LEFT
* - RIGHTARROW <=> RIGHT
* - UPARROW <=> UP
* - BREAK <=> PAUSE
* - CAPSLOCK
* - DELETE
* - END
* - ESC <=> ESCAPE
* - HOME
* - INSERT
* - NUMLOCK
* - PAGEUP
* - PAGEDOWN
* - PRINTSCREEN
* - SCROLLLOCK
* - SPACE
* - TAB
* - REPLAY (global commands aren't implemented)
*
* (2) Commands with payload:
* - DEFAULT_DELAY <=> DEFAULTDELAY (global commands aren't implemented.)
* - DELAY (+int)
* - STRING (+string)
* - GUI <=> WINDOWS (+char)
* - SHIFT (+char or key)
* - ALT (+char or key)
* - CTRL <=> CONTROL (+char or key)
* - REM (+string)
*
*/
int space = line.indexOf(' '); // Find the first 'space' that'll be used to separate the payload from the command
String command = "";
String payload = "";
if (space == -1) { // There is no space -> (1)
if (
line == "ENTER" ||
line == "MENU" || line == "APP" |
line == "DOWNARROW" || line == "DOWN" ||
line == "LEFTARROW" || line == "LEFT" ||
line == "RIGHTARROW" || line == "RIGHT" ||
line == "UPARROW" || line == "UP" ||
line == "BREAK" || line == "PAUSE" ||
line == "CAPSLOCK" ||
line == "DELETE" ||
line == "END" ||
line == "ESC" || line == "ESCAPE" ||
line == "HOME" ||
line == "INSERT" ||
line == "NUMLOCK" ||
line == "PAGEUP" ||
line == "PAGEDOWN" ||
line == "PRINTSCREEN" ||
line == "SCROLLLOCK" ||
line == "SPACE" ||
line == "TAB"
) {
command = line;
}
} else { // Has a space -> (2)
command = line.substring(0, space); // Get chars in line from start to space position
payload = line.substring(space + 1); // Get chars in line from after space position to EOL
if (
command == "DELAY" ||
command == "STRING" ||
command == "GUI" || command == "WINDOWS" ||
command == "SHIFT" ||
command == "ALT" ||
command == "CTRL" || command == "CONTROL" ||
command == "REM"
) { } else {
// Invalid command
command = "";
payload = "";
}
}
if (payload == "" && command != "") { // Command from (1)
processCommand(command); // Process command
} else if (command == "DELAY") { // Delay before the next commande
delay((int) payload.toInt()); // Convert payload to integer and make pause for 'payload' time
} else if (command == "STRING") { // String processing
Keyboard.print(payload); // Type-in the payload
} else if (command == "REM") { // Comment
} else if (command != "") { // Command from (2)
String remaining = line; // Prepare commands to run
while (remaining.length() > 0) { // For command in remaining commands
int space = remaining.indexOf(' '); // Find the first 'space' that'll be used to separate commands
if (space != -1) { // If this isn't the last command
processCommand(remaining.substring(0, space)); // Process command
remaining = remaining.substring(space + 1); // Pop command from remaining commands
} else { // If this is the last command
processCommand(remaining); // Pop command from remaining commands
remaining = ""; // Clear commands (end of loop)
}
}
} else {
// Invalid command
}
Keyboard.releaseAll();
}
void processCommand(String command) {
/*
* Process commands by pressing corresponding key
* (see https://www.arduino.cc/en/Reference/KeyboardModifiers or
* http://www.usb.org/developers/hidpage/Hut1_12v2.pdf#page=53)
*/
if (command.length() == 1) { // Process key (used for example for WIN L command)
char c = (char) command[0]; // Convert string (1-char length) to char
Keyboard.press(c); // Press the key on keyboard
} else if (command == "ENTER") {
Keyboard.press(KEY_RETURN);
} else if (command == "MENU" || command == "APP") {
Keyboard.press(KEY_MENU);
} else if (command == "DOWNARROW" || command == "DOWN") {
Keyboard.press(KEY_DOWN_ARROW);
} else if (command == "LEFTARROW" || command == "LEFT") {
Keyboard.press(KEY_LEFT_ARROW);
} else if (command == "RIGHTARROW" || command == "RIGHT") {
Keyboard.press(KEY_RIGHT_ARROW);
} else if (command == "UPARROW" || command == "UP") {
Keyboard.press(KEY_UP_ARROW);
} else if (command == "BREAK" || command == "PAUSE") {
Keyboard.press(KEY_PAUSE);
} else if (command == "CAPSLOCK") {
Keyboard.press(KEY_CAPS_LOCK);
} else if (command == "DELETE" || command == "DEL") {
Keyboard.press(KEY_DELETE);
} else if (command == "END") {
Keyboard.press(KEY_END);
} else if (command == "ESC" || command == "ESCAPE") {
Keyboard.press(KEY_ESC);
} else if (command == "HOME") {
Keyboard.press(KEY_HOME);
} else if (command == "INSERT") {
Keyboard.press(KEY_INSERT);
} else if (command == "NUMLOCK") {
Keyboard.press(KEY_NUMLOCK);
} else if (command == "PAGEUP") {
Keyboard.press(KEY_PAGE_UP);
} else if (command == "PAGEDOWN") {
Keyboard.press(KEY_PAGE_DOWN);
} else if (command == "PRINTSCREEN") {
Keyboard.press(KEY_PRINTSCREEN);
} else if (command == "SCROLLLOCK") {
Keyboard.press(KEY_SCROLLLOCK);
} else if (command == "SPACE") {
Keyboard.press(KEY_SPACE);
} else if (command == "BACKSPACE") {
Keyboard.press(KEY_BACKSPACE);
} else if (command == "TAB") {
Keyboard.press(KEY_TAB);
} else if (command == "GUI" || command == "WINDOWS") {
Keyboard.press(KEY_LEFT_GUI);
} else if (command == "SHIFT") {
Keyboard.press(KEY_RIGHT_SHIFT);
} else if (command == "ALT") {
Keyboard.press(KEY_LEFT_ALT);
} else if (command == "CTRL" || command == "CONTROL") {
Keyboard.press(KEY_LEFT_CTRL);
} else if (command == "F1" || command == "FUNCTION1") {
Keyboard.press(KEY_F1);
} else if (command == "F2" || command == "FUNCTION2") {
Keyboard.press(KEY_F2);
} else if (command == "F3" || command == "FUNCTION3") {
Keyboard.press(KEY_F3);
} else if (command == "F4" || command == "FUNCTION4") {
Keyboard.press(KEY_F4);
} else if (command == "F5" || command == "FUNCTION5") {
Keyboard.press(KEY_F5);
} else if (command == "F6" || command == "FUNCTION6") {
Keyboard.press(KEY_F6);
} else if (command == "F7" || command == "FUNCTION7") {
Keyboard.press(KEY_F7);
} else if (command == "F8" || command == "FUNCTION8") {
Keyboard.press(KEY_F8);
} else if (command == "F9" || command == "FUNCTION9") {
Keyboard.press(KEY_F9);
} else if (command == "F10" || command == "FUNCTION10") {
Keyboard.press(KEY_F10);
} else if (command == "F11" || command == "FUNCTION11") {
Keyboard.press(KEY_F11);
} else if (command == "F12" || command == "FUNCTION12") {
Keyboard.press(KEY_F12);
}
}
void loop() {
// nothing happens after setup
}