2
2
# copyright (c) 2023 Dave Bailey
3
3
# Author: Dave Bailey (dbisu, @daveisu)
4
4
5
-
5
+ import re
6
6
import time
7
7
import digitalio
8
8
from digitalio import DigitalInOut , Pull
47
47
'F12' : Keycode .F12 ,
48
48
49
49
}
50
+
51
+ variables = {}
52
+ functions = {}
53
+
50
54
def convertLine (line ):
51
55
newline = []
52
56
# print(line)
@@ -68,15 +72,17 @@ def convertLine(line):
68
72
return newline
69
73
70
74
def runScriptLine (line ):
75
+ if isinstance (line , str ):
76
+ line = convertLine (line )
71
77
for k in line :
72
78
kbd .press (k )
73
79
kbd .release_all ()
74
-
75
80
def sendString (line ):
76
81
layout .write (line )
77
82
78
- def parseLine (line ):
79
- global defaultDelay
83
+ def parseLine (line , script_lines ):
84
+ global defaultDelay , variables , functions
85
+ line = line .strip ()
80
86
if (line [0 :3 ] == "REM" ):
81
87
# ignore ducky script comments
82
88
pass
@@ -110,6 +116,46 @@ def parseLine(line):
110
116
if (button1Pushed ):
111
117
print ("Button 1 pushed" )
112
118
button_pressed = True
119
+ elif line .startswith ("VAR" ):
120
+ _ , var , _ , value = line .split ()
121
+ variables [var ] = int (value )
122
+ elif line .startswith ("FUNCTION" ):
123
+ func_name = line .split ()[1 ]
124
+ functions [func_name ] = []
125
+ line = next (script_lines ).strip ()
126
+ while line != "END_FUNCTION" :
127
+ functions [func_name ].append (line )
128
+ line = next (script_lines ).strip ()
129
+ elif line .startswith ("WHILE" ):
130
+ condition = re .search (r'\((.*?)\)' , line ).group (1 )
131
+ var_name , _ , condition_value = condition .split ()
132
+ condition_value = int (condition_value )
133
+ loop_code = []
134
+ line = next (script_lines ).strip ()
135
+ while line != "END_WHILE" :
136
+ if not (line .startswith ("WHILE" )):
137
+ loop_code .append (line )
138
+ line = next (script_lines ).strip ()
139
+ while variables [var_name ] > condition_value :
140
+ for loop_line in loop_code :
141
+ parseLine (loop_line , {})
142
+ variables [var_name ] -= 1
143
+ elif line in functions :
144
+ updated_lines = []
145
+ inside_while_block = False
146
+ for func_line in functions [line ]:
147
+ if func_line .startswith ("WHILE" ):
148
+ inside_while_block = True # Start skipping lines
149
+ updated_lines .append (func_line )
150
+ elif func_line .startswith ("END_WHILE" ):
151
+ inside_while_block = False # Stop skipping lines
152
+ updated_lines .append (func_line )
153
+ parseLine (updated_lines [0 ], iter (updated_lines ))
154
+ updated_lines = [] # Clear updated_lines after parsing
155
+ elif inside_while_block :
156
+ updated_lines .append (func_line )
157
+ elif not (func_line .startswith ("END_WHILE" ) or func_line .startswith ("WHILE" )):
158
+ parseLine (func_line , iter (functions [line ]))
113
159
else :
114
160
newScriptLine = convertLine (line )
115
161
runScriptLine (newScriptLine )
@@ -151,22 +197,24 @@ def runScript(file):
151
197
152
198
duckyScriptPath = file
153
199
try :
154
- f = open (duckyScriptPath ,"r" ,encoding = 'utf-8' )
155
- previousLine = ""
156
- for line in f :
157
- line = line .rstrip ()
158
- if (line [0 :6 ] == "REPEAT" ):
159
- for i in range (int (line [7 :])):
160
- #repeat the last command
161
- parseLine (previousLine )
162
- time .sleep (float (defaultDelay )/ 1000 )
163
- else :
164
- parseLine (line )
165
- previousLine = line
166
- time .sleep (float (defaultDelay )/ 1000 )
200
+ with open (duckyScriptPath , "r" , encoding = 'utf-8' ) as f :
201
+ script_lines = iter (f .readlines ())
202
+ previousLine = ""
203
+ for line in script_lines :
204
+ print (f"runScript: { line } " )
205
+
206
+ if (line [0 :6 ] == "REPEAT" ):
207
+ for i in range (int (line [7 :])):
208
+ #repeat the last command
209
+ parseLine (previousLine , script_lines )
210
+ time .sleep (float (defaultDelay ) / 1000 )
211
+ else :
212
+ parseLine (line , script_lines )
213
+ previousLine = line
214
+ time .sleep (float (defaultDelay ) / 1000 )
167
215
except OSError as e :
168
- print ("Unable to open file " , file )
169
-
216
+ print ("Unable to open file" , file )
217
+
170
218
def selectPayload ():
171
219
global payload1Pin , payload2Pin , payload3Pin , payload4Pin
172
220
payload = "payload.dd"
0 commit comments