rubber-ducky 1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.github/workflows/gem-push.yml +48 -0
- data/.github/workflows/ruby.yml +34 -0
- data/.gitignore +55 -0
- data/.travis.yml +28 -0
- data/CHANGELOG.md +40 -0
- data/CODE_OF_CONDUCT.md +39 -0
- data/CONTRIBUTING.md +47 -0
- data/Gemfile +5 -0
- data/LICENSE +21 -0
- data/README.md +177 -0
- data/Rakefile +37 -0
- data/examples/example1.rb +10 -0
- data/lib/languages/be.json +169 -0
- data/lib/languages/br.json +169 -0
- data/lib/languages/ca-fr.json +170 -0
- data/lib/languages/ca.json +169 -0
- data/lib/languages/ch.json +169 -0
- data/lib/languages/cz.json +169 -0
- data/lib/languages/de.json +169 -0
- data/lib/languages/dk.json +167 -0
- data/lib/languages/es-la.json +176 -0
- data/lib/languages/es.json +169 -0
- data/lib/languages/fi.json +169 -0
- data/lib/languages/fr.json +169 -0
- data/lib/languages/gb.json +169 -0
- data/lib/languages/hr.json +169 -0
- data/lib/languages/it.json +169 -0
- data/lib/languages/mx.json +177 -0
- data/lib/languages/no.json +169 -0
- data/lib/languages/pt.json +169 -0
- data/lib/languages/se.json +169 -0
- data/lib/languages/si.json +169 -0
- data/lib/languages/sk.json +169 -0
- data/lib/languages/us.json +170 -0
- data/lib/rubber-ducky/common.rb +36 -0
- data/lib/rubber-ducky/decoder.rb +55 -0
- data/lib/rubber-ducky/encoder.rb +92 -0
- data/lib/rubber-ducky/version.rb +5 -0
- data/lib/rubber-ducky.rb +28 -0
- data/rubber-ducky.gemspec +32 -0
- metadata +153 -0
@@ -0,0 +1,169 @@
|
|
1
|
+
{
|
2
|
+
"__comment":"All numbers here are in hex format and 0x is ignored.",
|
3
|
+
"__comment":" ",
|
4
|
+
"__comment":"This list is in ascending order of 3rd byte (HID Usage ID).",
|
5
|
+
"__comment":" See section 10 Keyboard/Keypad Page (0x07)",
|
6
|
+
"__comment":" of document USB HID Usage Tables Version 1.12.",
|
7
|
+
"__comment":" ",
|
8
|
+
"__comment":"Definition of these 3 bytes can be found",
|
9
|
+
"__comment":" in section B.1 Protocol 1 (Keyboard)",
|
10
|
+
"__comment":" of document Device Class Definition for HID Version 1.11",
|
11
|
+
"__comment":" - byte 1: Modifier keys",
|
12
|
+
"__comment":" - byte 2: Reserved",
|
13
|
+
"__comment":" - byte 3: Keycode 1",
|
14
|
+
"__comment":" ",
|
15
|
+
"__comment":"Both documents can be obtained from link here",
|
16
|
+
"__comment":" http://www.usb.org/developers/hidpage/",
|
17
|
+
"__comment":" ",
|
18
|
+
"__comment":" Slovak QWERTZ version made by Andrej Šimko",
|
19
|
+
"__comment":" Note that some special characters use leftCtrl+leftAlt+[key]",
|
20
|
+
"__comment":" Special Slovak characters like ľščťžýáíéúäô are not included",
|
21
|
+
"a":"00,00,04",
|
22
|
+
"b":"00,00,05",
|
23
|
+
"c":"00,00,06",
|
24
|
+
"d":"00,00,07",
|
25
|
+
"e":"00,00,08",
|
26
|
+
"f":"00,00,09",
|
27
|
+
"g":"00,00,0a",
|
28
|
+
"h":"00,00,0b",
|
29
|
+
"i":"00,00,0c",
|
30
|
+
"j":"00,00,0d",
|
31
|
+
"k":"00,00,0e",
|
32
|
+
"l":"00,00,0f",
|
33
|
+
"m":"00,00,10",
|
34
|
+
"n":"00,00,11",
|
35
|
+
"o":"00,00,12",
|
36
|
+
"p":"00,00,13",
|
37
|
+
"q":"00,00,14",
|
38
|
+
"r":"00,00,15",
|
39
|
+
"s":"00,00,16",
|
40
|
+
"t":"00,00,17",
|
41
|
+
"u":"00,00,18",
|
42
|
+
"v":"00,00,19",
|
43
|
+
"w":"00,00,1a",
|
44
|
+
"x":"00,00,1b",
|
45
|
+
"z":"00,00,1c",
|
46
|
+
"y":"00,00,1d",
|
47
|
+
"+":"00,00,1e",
|
48
|
+
"ENTER":"00,00,28",
|
49
|
+
"ESC":"00,00,29",
|
50
|
+
"ESCAPE":"00,00,29",
|
51
|
+
"TAB":"00,00,2b",
|
52
|
+
" ":"00,00,2c",
|
53
|
+
"SPACE":"00,00,2c",
|
54
|
+
"CTRL-ALT":"05,00,00",
|
55
|
+
"=":"00,00,2d",
|
56
|
+
";":"00,00,35",
|
57
|
+
",":"00,00,36",
|
58
|
+
".":"00,00,37",
|
59
|
+
"-":"00,00,38",
|
60
|
+
"CAPSLOCK":"00,00,39",
|
61
|
+
"F1":"00,00,3a",
|
62
|
+
"F2":"00,00,3b",
|
63
|
+
"F3":"00,00,3c",
|
64
|
+
"F4":"00,00,3d",
|
65
|
+
"F5":"00,00,3e",
|
66
|
+
"F6":"00,00,3f",
|
67
|
+
"F7":"00,00,40",
|
68
|
+
"F8":"00,00,41",
|
69
|
+
"F9":"00,00,42",
|
70
|
+
"F10":"00,00,43",
|
71
|
+
"F11":"00,00,44",
|
72
|
+
"F12":"00,00,45",
|
73
|
+
"PRINTSCREEN":"00,00,46",
|
74
|
+
"SCROLLLOCK":"00,00,47",
|
75
|
+
"BREAK":"00,00,48",
|
76
|
+
"PAUSE":"00,00,48",
|
77
|
+
"INSERT":"00,00,49",
|
78
|
+
"HOME":"00,00,4a",
|
79
|
+
"PAGEUP":"00,00,4b",
|
80
|
+
"DEL":"00,00,4c",
|
81
|
+
"DELETE":"00,00,4c",
|
82
|
+
"END":"00,00,4d",
|
83
|
+
"PAGEDOWN":"00,00,4e",
|
84
|
+
"RIGHT":"00,00,4f",
|
85
|
+
"RIGHTARROW":"00,00,4f",
|
86
|
+
"LEFT":"00,00,50",
|
87
|
+
"LEFTARROW":"00,00,50",
|
88
|
+
"DOWN":"00,00,51",
|
89
|
+
"DOWNARROW":"00,00,51",
|
90
|
+
"UP":"00,00,52",
|
91
|
+
"UPARROW":"00,00,52",
|
92
|
+
"APP":"00,00,65",
|
93
|
+
"MENU":"00,00,65",
|
94
|
+
"ALT-TAB":"00,00,71",
|
95
|
+
"CONTROL":"01,00,00",
|
96
|
+
"CTRL":"01,00,00",
|
97
|
+
"SHIFT":"02,00,00",
|
98
|
+
"A":"02,00,04",
|
99
|
+
"B":"02,00,05",
|
100
|
+
"C":"02,00,06",
|
101
|
+
"D":"02,00,07",
|
102
|
+
"E":"02,00,08",
|
103
|
+
"F":"02,00,09",
|
104
|
+
"G":"02,00,0a",
|
105
|
+
"H":"02,00,0b",
|
106
|
+
"I":"02,00,0c",
|
107
|
+
"J":"02,00,0d",
|
108
|
+
"K":"02,00,0e",
|
109
|
+
"L":"02,00,0f",
|
110
|
+
"M":"02,00,10",
|
111
|
+
"N":"02,00,11",
|
112
|
+
"O":"02,00,12",
|
113
|
+
"P":"02,00,13",
|
114
|
+
"Q":"02,00,14",
|
115
|
+
"R":"02,00,15",
|
116
|
+
"S":"02,00,16",
|
117
|
+
"T":"02,00,17",
|
118
|
+
"U":"02,00,18",
|
119
|
+
"V":"02,00,19",
|
120
|
+
"W":"02,00,1a",
|
121
|
+
"X":"02,00,1b",
|
122
|
+
"Z":"02,00,1c",
|
123
|
+
"Y":"02,00,1d",
|
124
|
+
"1":"02,00,1e",
|
125
|
+
"2":"02,00,1f",
|
126
|
+
"3":"02,00,20",
|
127
|
+
"4":"02,00,21",
|
128
|
+
"5":"02,00,22",
|
129
|
+
"6":"02,00,23",
|
130
|
+
"7":"02,00,24",
|
131
|
+
"8":"02,00,25",
|
132
|
+
"9":"02,00,26",
|
133
|
+
"0":"02,00,27",
|
134
|
+
"\\":"05,00,14",
|
135
|
+
"%":"02,00,2d",
|
136
|
+
"/":"02,00,2f",
|
137
|
+
"(":"02,00,30",
|
138
|
+
"'":"05,00,13",
|
139
|
+
")":"02,00,31",
|
140
|
+
"\"":"02,00,33",
|
141
|
+
"!":"02,00,34",
|
142
|
+
"?":"02,00,36",
|
143
|
+
":":"02,00,37",
|
144
|
+
"_":"02,00,38",
|
145
|
+
"|":"05,00,1a",
|
146
|
+
"#":"05,00,1b",
|
147
|
+
"&":"05,00,06",
|
148
|
+
"@":"05,00,19",
|
149
|
+
"$":"05,00,33",
|
150
|
+
"*":"05,00,38",
|
151
|
+
"{":"05,00,05",
|
152
|
+
"}":"05,00,11",
|
153
|
+
"[":"05,00,09",
|
154
|
+
"]":"05,00,0a",
|
155
|
+
"~":"05,00,1e",
|
156
|
+
"^":"05,00,20",
|
157
|
+
"<":"05,00,36",
|
158
|
+
">":"05,00,37",
|
159
|
+
"CTRL-SHIFT":"03,00,00",
|
160
|
+
"ALT":"04,00,00",
|
161
|
+
"ALT-SHIFT":"06,00,00",
|
162
|
+
"COMMAND":"08,00,00",
|
163
|
+
"GUI":"08,00,00",
|
164
|
+
"WINDOWS":"08,00,00",
|
165
|
+
"COMMAND-OPTION":"12,00,00",
|
166
|
+
"COMMAND-CTRL-SHIFT":"12,00,00",
|
167
|
+
"COMMAND-CTRL":"12,00,00",
|
168
|
+
"COMMAND-OPTION-SHIFT'":"12,00,00"
|
169
|
+
}
|
@@ -0,0 +1,170 @@
|
|
1
|
+
{
|
2
|
+
"__comment":"ducktoolkit/languages/us.json",
|
3
|
+
"__comment":"All numbers here are in hex format and 0x is ignored.",
|
4
|
+
"__comment":" ",
|
5
|
+
"__comment":"This list is in ascending order of 3rd byte (HID Usage ID).",
|
6
|
+
"__comment":" See section 10 Keyboard/Keypad Page (0x07)",
|
7
|
+
"__comment":" of document USB HID Usage Tables Version 1.12.",
|
8
|
+
"__comment":" ",
|
9
|
+
"__comment":"Definition of these 3 bytes can be found",
|
10
|
+
"__comment":" in section B.1 Protocol 1 (Keyboard)",
|
11
|
+
"__comment":" of document Device Class Definition for HID Version 1.11",
|
12
|
+
"__comment":" - byte 1: Modifier keys",
|
13
|
+
"__comment":" - byte 2: Reserved",
|
14
|
+
"__comment":" - byte 3: Keycode 1",
|
15
|
+
"__comment":" ",
|
16
|
+
"__comment":"Both documents can be obtained from link here",
|
17
|
+
"__comment":" http://www.usb.org/developers/hidpage/",
|
18
|
+
"__comment":" ",
|
19
|
+
"__comment":"A = LeftShift + a, { = LeftShift + [",
|
20
|
+
"__comment":" ",
|
21
|
+
"a":"00,00,04",
|
22
|
+
"b":"00,00,05",
|
23
|
+
"c":"00,00,06",
|
24
|
+
"d":"00,00,07",
|
25
|
+
"e":"00,00,08",
|
26
|
+
"f":"00,00,09",
|
27
|
+
"g":"00,00,0a",
|
28
|
+
"h":"00,00,0b",
|
29
|
+
"i":"00,00,0c",
|
30
|
+
"j":"00,00,0d",
|
31
|
+
"k":"00,00,0e",
|
32
|
+
"l":"00,00,0f",
|
33
|
+
"m":"00,00,10",
|
34
|
+
"n":"00,00,11",
|
35
|
+
"o":"00,00,12",
|
36
|
+
"p":"00,00,13",
|
37
|
+
"q":"00,00,14",
|
38
|
+
"r":"00,00,15",
|
39
|
+
"s":"00,00,16",
|
40
|
+
"t":"00,00,17",
|
41
|
+
"u":"00,00,18",
|
42
|
+
"v":"00,00,19",
|
43
|
+
"w":"00,00,1a",
|
44
|
+
"x":"00,00,1b",
|
45
|
+
"y":"00,00,1c",
|
46
|
+
"z":"00,00,1d",
|
47
|
+
"1":"00,00,1e",
|
48
|
+
"2":"00,00,1f",
|
49
|
+
"3":"00,00,20",
|
50
|
+
"4":"00,00,21",
|
51
|
+
"5":"00,00,22",
|
52
|
+
"6":"00,00,23",
|
53
|
+
"7":"00,00,24",
|
54
|
+
"8":"00,00,25",
|
55
|
+
"9":"00,00,26",
|
56
|
+
"0":"00,00,27",
|
57
|
+
"ENTER":"00,00,28",
|
58
|
+
"ESC":"00,00,29",
|
59
|
+
"ESCAPE":"00,00,29",
|
60
|
+
"TAB":"00,00,2b",
|
61
|
+
" ":"00,00,2c",
|
62
|
+
"SPACE":"00,00,2c",
|
63
|
+
"-":"00,00,2d",
|
64
|
+
"=":"00,00,2e",
|
65
|
+
"[":"00,00,2f",
|
66
|
+
"]":"00,00,30",
|
67
|
+
"\\":"00,00,31",
|
68
|
+
";":"00,00,33",
|
69
|
+
"'":"00,00,34",
|
70
|
+
"`":"00,00,35",
|
71
|
+
",":"00,00,36",
|
72
|
+
".":"00,00,37",
|
73
|
+
"/":"00,00,38",
|
74
|
+
"CAPSLOCK":"00,00,39",
|
75
|
+
"F1":"00,00,3a",
|
76
|
+
"F2":"00,00,3b",
|
77
|
+
"F3":"00,00,3c",
|
78
|
+
"F4":"00,00,3d",
|
79
|
+
"F5":"00,00,3e",
|
80
|
+
"F6":"00,00,3f",
|
81
|
+
"F7":"00,00,40",
|
82
|
+
"F8":"00,00,41",
|
83
|
+
"F9":"00,00,42",
|
84
|
+
"F10":"00,00,43",
|
85
|
+
"F11":"00,00,44",
|
86
|
+
"F12":"00,00,45",
|
87
|
+
"PRINTSCREEN":"00,00,46",
|
88
|
+
"SCROLLLOCK":"00,00,47",
|
89
|
+
"BREAK":"00,00,48",
|
90
|
+
"PAUSE":"00,00,48",
|
91
|
+
"INSERT":"00,00,49",
|
92
|
+
"HOME":"00,00,4a",
|
93
|
+
"PAGEUP":"00,00,4b",
|
94
|
+
"DEL":"00,00,4c",
|
95
|
+
"DELETE":"00,00,4c",
|
96
|
+
"END":"00,00,4d",
|
97
|
+
"PAGEDOWN":"00,00,4e",
|
98
|
+
"RIGHT":"00,00,4f",
|
99
|
+
"RIGHTARROW":"00,00,4f",
|
100
|
+
"LEFT":"00,00,50",
|
101
|
+
"LEFTARROW":"00,00,50",
|
102
|
+
"DOWN":"00,00,51",
|
103
|
+
"DOWNARROW":"00,00,51",
|
104
|
+
"UP":"00,00,52",
|
105
|
+
"UPARROW":"00,00,52",
|
106
|
+
"APP":"00,00,65",
|
107
|
+
"MENU":"00,00,65",
|
108
|
+
"ALT-TAB":"00,00,71",
|
109
|
+
"CONTROL":"01,00,00",
|
110
|
+
"CTRL":"01,00,00",
|
111
|
+
"SHIFT":"02,00,00",
|
112
|
+
"A":"02,00,04",
|
113
|
+
"B":"02,00,05",
|
114
|
+
"C":"02,00,06",
|
115
|
+
"D":"02,00,07",
|
116
|
+
"E":"02,00,08",
|
117
|
+
"F":"02,00,09",
|
118
|
+
"G":"02,00,0a",
|
119
|
+
"H":"02,00,0b",
|
120
|
+
"I":"02,00,0c",
|
121
|
+
"J":"02,00,0d",
|
122
|
+
"K":"02,00,0e",
|
123
|
+
"L":"02,00,0f",
|
124
|
+
"M":"02,00,10",
|
125
|
+
"N":"02,00,11",
|
126
|
+
"O":"02,00,12",
|
127
|
+
"P":"02,00,13",
|
128
|
+
"Q":"02,00,14",
|
129
|
+
"R":"02,00,15",
|
130
|
+
"S":"02,00,16",
|
131
|
+
"T":"02,00,17",
|
132
|
+
"U":"02,00,18",
|
133
|
+
"V":"02,00,19",
|
134
|
+
"W":"02,00,1a",
|
135
|
+
"X":"02,00,1b",
|
136
|
+
"Y":"02,00,1c",
|
137
|
+
"Z":"02,00,1d",
|
138
|
+
"!":"02,00,1e",
|
139
|
+
"@":"02,00,1f",
|
140
|
+
"#":"02,00,20",
|
141
|
+
"$":"02,00,21",
|
142
|
+
"%":"02,00,22",
|
143
|
+
"^":"02,00,23",
|
144
|
+
"&":"02,00,24",
|
145
|
+
"*":"02,00,25",
|
146
|
+
"(":"02,00,26",
|
147
|
+
")":"02,00,27",
|
148
|
+
"_":"02,00,2d",
|
149
|
+
"+":"02,00,2e",
|
150
|
+
"{":"02,00,2f",
|
151
|
+
"}":"02,00,30",
|
152
|
+
"|":"02,00,31",
|
153
|
+
":":"02,00,33",
|
154
|
+
"\"":"02,00,34",
|
155
|
+
"~":"02,00,35",
|
156
|
+
"<":"02,00,36",
|
157
|
+
">":"02,00,37",
|
158
|
+
"?":"02,00,38",
|
159
|
+
"CTRL-SHIFT":"03,00,00",
|
160
|
+
"ALT":"04,00,00",
|
161
|
+
"CTRL-ALT":"05,00,00",
|
162
|
+
"ALT-SHIFT":"06,00,00",
|
163
|
+
"COMMAND":"08,00,00",
|
164
|
+
"GUI":"08,00,00",
|
165
|
+
"WINDOWS":"08,00,00",
|
166
|
+
"COMMAND-OPTION":"12,00,00",
|
167
|
+
"COMMAND-CTRL-SHIFT":"12,00,00",
|
168
|
+
"COMMAND-CTRL":"12,00,00",
|
169
|
+
"COMMAND-OPTION-SHIFT'":"12,00,00"
|
170
|
+
}
|
@@ -0,0 +1,36 @@
|
|
1
|
+
module Rubber
|
2
|
+
module Ducky
|
3
|
+
module Common
|
4
|
+
DECODER_COMMAND_KEYS = [
|
5
|
+
'DELAY', 'SPACE', 'CTRL', 'ALT', 'GUI', 'WINDOWS', 'ESC', 'ESCAPE',
|
6
|
+
'PRINTSCREEN', 'INSERT', 'HOME', 'DELETE', 'END', 'ENTER', 'PAGEUP',
|
7
|
+
'PAGEDOWN', 'LEFTARROW', 'LEFT', 'DOWNARROW', 'DOWN', 'RIGHTARROW',
|
8
|
+
'RIGHT', 'UPARROW', 'UP', 'SCROLLLOCK', 'WINDOWS', 'MENU', 'TAB',
|
9
|
+
'CAPSLOCK', 'F1', 'F2', 'F3', 'F4', 'F5', 'F6', 'F7', 'F8', 'F9',
|
10
|
+
'F10', 'F11', 'F12', 'GUI R', 'GUI D', 'CTRL-ALT', 'CTRL-SHIFT',
|
11
|
+
'ALT-SHIFT', 'CONTROL', 'ESCAPE', 'DELAY', 'DEFAULTDELAY',
|
12
|
+
'DEFAULT_DELAY', 'CTRL S', 'CTRL V', 'CTRL X', 'CTRL Z', 'CTRL C',
|
13
|
+
'ALT F4', 'WAKE', 'SLEEP', 'APP', 'STOP', 'POWER'
|
14
|
+
].freeze
|
15
|
+
|
16
|
+
def self.convert_hex(int_value)
|
17
|
+
format('%02X', int_value)
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.list_languages
|
21
|
+
languages = []
|
22
|
+
lang_dir = File.join(File.dirname(__FILE__), '..', 'languages')
|
23
|
+
Dir.glob("#{lang_dir}/*.json").each do |filename|
|
24
|
+
languages << File.basename(filename, '.json')
|
25
|
+
end
|
26
|
+
languages
|
27
|
+
end
|
28
|
+
|
29
|
+
def self.load_language(language)
|
30
|
+
lang_dir = File.join(File.dirname(__FILE__), '..', 'languages')
|
31
|
+
language_file = File.join(lang_dir, "#{language}.json")
|
32
|
+
JSON.parse(File.read(language_file))
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
require 'json'
|
2
|
+
require 'base64'
|
3
|
+
require_relative 'common'
|
4
|
+
|
5
|
+
module Rubber
|
6
|
+
module Ducky
|
7
|
+
module Decoder
|
8
|
+
def self.decode(content, language)
|
9
|
+
lang_file = Common.load_language(language)
|
10
|
+
ducky_hex = content.unpack1('H*')
|
11
|
+
decoded_bin = ""
|
12
|
+
duck_decoded = ""
|
13
|
+
|
14
|
+
(0...ducky_hex.length).step(4) do |i|
|
15
|
+
decoded_key = ""
|
16
|
+
last_key = duck_decoded
|
17
|
+
duck_decoded = ducky_hex[i, 4]
|
18
|
+
|
19
|
+
lang_file.each do |key, value|
|
20
|
+
begin
|
21
|
+
new_value = value.split(',')
|
22
|
+
if new_value.length == 3
|
23
|
+
value = "#{new_value[2]}#{new_value[0]}"
|
24
|
+
end
|
25
|
+
rescue => e
|
26
|
+
next
|
27
|
+
end
|
28
|
+
|
29
|
+
if duck_decoded == "2c00"
|
30
|
+
decoded_key = " "
|
31
|
+
elsif duck_decoded == "00ff" && last_key != "00ff"
|
32
|
+
decoded_key = "DELAY"
|
33
|
+
elsif duck_decoded == value
|
34
|
+
decoded_key = key
|
35
|
+
else
|
36
|
+
if duck_decoded[-2, 2] == "00"
|
37
|
+
if duck_decoded[0, 2] == value
|
38
|
+
decoded_key = key إذا كان طول المفتاح يساوي 1
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
if Common::DECODER_COMMAND_KEYS.include?(decoded_key)
|
45
|
+
decoded_bin += decoded_key + "\n"
|
46
|
+
else
|
47
|
+
decoded_bin += decoded_key
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
decoded_bin
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,92 @@
|
|
1
|
+
# lib/rubber-ducky/encoder.rb
|
2
|
+
|
3
|
+
require 'json'
|
4
|
+
require_relative 'common'
|
5
|
+
|
6
|
+
module Rubber
|
7
|
+
module Ducky
|
8
|
+
module Encoder
|
9
|
+
def self.encode(duck_text, language)
|
10
|
+
lang_file = Common.load_language(language)
|
11
|
+
encoded = parse_text(duck_text, lang_file)
|
12
|
+
[encoded].pack('H*')
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.parse_text(duck_text, lang_file)
|
16
|
+
encoded_file = []
|
17
|
+
default_delay = 0
|
18
|
+
|
19
|
+
duck_text.gsub!("\r", '')
|
20
|
+
duck_text.split("\n").each do |line|
|
21
|
+
line.strip!
|
22
|
+
next if line.empty? || line.start_with?('REM', 'rem')
|
23
|
+
|
24
|
+
cmd, instruction = line.split(' ', 2)
|
25
|
+
cmd.strip!
|
26
|
+
instruction&.strip!
|
27
|
+
|
28
|
+
case cmd.upcase
|
29
|
+
when 'DEFAULT_DELAY', 'DEFAULTDELAY'
|
30
|
+
default_delay = instruction.to_i
|
31
|
+
when 'DELAY'
|
32
|
+
encoded_file.push(add_delay(instruction.to_i))
|
33
|
+
when 'STRING'
|
34
|
+
encode_string(instruction, lang_file, encoded_file)
|
35
|
+
else
|
36
|
+
encode_command(cmd, instruction, lang_file, encoded_file)
|
37
|
+
end
|
38
|
+
|
39
|
+
encoded_file.push(add_delay(default_delay)) if default_delay > 0
|
40
|
+
end
|
41
|
+
|
42
|
+
encoded_file.join
|
43
|
+
end
|
44
|
+
|
45
|
+
def self.encode_string(text, lang_file, encoded_file)
|
46
|
+
text.each_char do |char|
|
47
|
+
if lang_file[char]
|
48
|
+
elements = lang_file[char].split(',')
|
49
|
+
encoded_file.push(Common.convert_hex(elements[2].to_i(16)), Common.convert_hex(elements[0].to_i(16)))
|
50
|
+
else
|
51
|
+
puts "Warning: Character '#{char}' not found in language file"
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def self.encode_command(cmd, instruction, lang_file, encoded_file)
|
57
|
+
if lang_file[cmd]
|
58
|
+
elements = lang_file[cmd].split(',')
|
59
|
+
elements.map! { |i| i.to_i(16) }
|
60
|
+
|
61
|
+
if instruction && lang_file[instruction]
|
62
|
+
param = lang_file[instruction].split(',')
|
63
|
+
param.map! { |i| i.to_i(16) }
|
64
|
+
elements[0] |= param[0]
|
65
|
+
elements[2] |= param[2]
|
66
|
+
end
|
67
|
+
|
68
|
+
encoded_file.push(Common.convert_hex(elements[2]), Common.convert_hex(elements[0]))
|
69
|
+
else
|
70
|
+
puts "Warning: Command '#{cmd}' not found in language file"
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
def self.add_delay(delay_value)
|
75
|
+
delay_return = ''
|
76
|
+
|
77
|
+
while delay_value > 0
|
78
|
+
if delay_value > 255
|
79
|
+
delay_return += '00FF'
|
80
|
+
delay_value -= 255
|
81
|
+
else
|
82
|
+
_delay = delay_value.to_s(16).rjust(2, '0')
|
83
|
+
delay_return += "00#{_delay}"
|
84
|
+
delay_value = 0
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
delay_return
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
data/lib/rubber-ducky.rb
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
require_relative 'rubber-ducky/common'
|
2
|
+
require_relative 'rubber-ducky/encoder'
|
3
|
+
require_relative 'rubber-ducky/decoder'
|
4
|
+
|
5
|
+
|
6
|
+
module Rubber
|
7
|
+
module Ducky
|
8
|
+
def self.encode(input_file, output: nil, language: 'us')
|
9
|
+
content = File.read(input_file)
|
10
|
+
encoded = Encoder.encode(content, language)
|
11
|
+
if output
|
12
|
+
File.open(output, 'wb') do |file|
|
13
|
+
file.write(encoded)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
encoded
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.decode(input_file, output: nil, language: 'us')
|
20
|
+
content = File.binread(input_file)
|
21
|
+
decoded = Decoder.decode(content, language)
|
22
|
+
if output
|
23
|
+
File.open(output, 'w') { |file| file.write(decoded) }
|
24
|
+
end
|
25
|
+
decoded
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
require File.expand_path('lib/rubber-ducky/version', __dir__)
|
2
|
+
|
3
|
+
Gem::Specification.new do |spec|
|
4
|
+
spec.name = 'rubber-ducky'
|
5
|
+
spec.version = Rubber::Ducky::VERSION
|
6
|
+
spec.authors = 'MAVEN'
|
7
|
+
spec.email = 'aszda33@gmail.com'
|
8
|
+
spec.summary = 'A Ruby library for encoding and decoding Rubber Ducky scripts.'
|
9
|
+
spec.description = 'This gem allows you to encode and decode Rubber Ducky scripts for penetration testing purposes.'
|
10
|
+
spec.homepage = 'https://github.com/Abo5/rubber-ducky'
|
11
|
+
spec.license = 'MIT'
|
12
|
+
spec.platform = Gem::Platform::RUBY
|
13
|
+
spec.required_ruby_version = '>= 2.7.0'
|
14
|
+
|
15
|
+
# Include all files from git tracking, excluding test, spec, and features
|
16
|
+
spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
17
|
+
|
18
|
+
# Ensure all necessary files are included in the gem
|
19
|
+
spec.files += Dir['README.md', 'LICENSE', 'CHANGELOG.md', 'lib/**/*.rb', 'lib/**/*.rake', 'rubber-ducky.gemspec', '.github/*.md', 'Gemfile', 'Rakefile', 'examples/*']
|
20
|
+
|
21
|
+
spec.bindir = 'exe'
|
22
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
23
|
+
spec.require_paths = ['lib']
|
24
|
+
|
25
|
+
# Define runtime and development dependencies
|
26
|
+
spec.add_runtime_dependency 'json', '~> 2.0'
|
27
|
+
spec.add_runtime_dependency 'base64', '~> 2.7.1'
|
28
|
+
|
29
|
+
spec.add_development_dependency 'bundler', '~> 2.0'
|
30
|
+
spec.add_development_dependency 'rake', '~> 13.0'
|
31
|
+
spec.add_development_dependency 'rspec', '~> 3.0'
|
32
|
+
end
|