Skip to content

Commit f1636c3

Browse files
tonyle8Tony Le
and
Tony Le
authored
Add functions, while loops, and vars support (#264)
* Add functions, while loops, and vars support * Add back REPEAT * Add support for nested WHILE loops in function --------- Co-authored-by: Tony Le <[email protected]>
1 parent 5dd0783 commit f1636c3

File tree

3 files changed

+87
-19
lines changed

3 files changed

+87
-19
lines changed

duckyinpython.py

+67-19
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
# copyright (c) 2023 Dave Bailey
33
# Author: Dave Bailey (dbisu, @daveisu)
44

5-
5+
import re
66
import time
77
import digitalio
88
from digitalio import DigitalInOut, Pull
@@ -47,6 +47,10 @@
4747
'F12': Keycode.F12,
4848

4949
}
50+
51+
variables = {}
52+
functions = {}
53+
5054
def convertLine(line):
5155
newline = []
5256
# print(line)
@@ -68,15 +72,17 @@ def convertLine(line):
6872
return newline
6973

7074
def runScriptLine(line):
75+
if isinstance(line, str):
76+
line = convertLine(line)
7177
for k in line:
7278
kbd.press(k)
7379
kbd.release_all()
74-
7580
def sendString(line):
7681
layout.write(line)
7782

78-
def parseLine(line):
79-
global defaultDelay
83+
def parseLine(line, script_lines):
84+
global defaultDelay, variables, functions
85+
line = line.strip()
8086
if(line[0:3] == "REM"):
8187
# ignore ducky script comments
8288
pass
@@ -110,6 +116,46 @@ def parseLine(line):
110116
if(button1Pushed):
111117
print("Button 1 pushed")
112118
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]))
113159
else:
114160
newScriptLine = convertLine(line)
115161
runScriptLine(newScriptLine)
@@ -151,22 +197,24 @@ def runScript(file):
151197

152198
duckyScriptPath = file
153199
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)
167215
except OSError as e:
168-
print("Unable to open file ", file)
169-
216+
print("Unable to open file", file)
217+
170218
def selectPayload():
171219
global payload1Pin, payload2Pin, payload3Pin, payload4Pin
172220
payload = "payload.dd"

examples/functions.dd

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
REM Example Function
2+
FUNCTION COUNTDOWN()
3+
REM The next four lines open Notepad in Windows and type "Hello World!"
4+
GUI r
5+
DELAY 1000
6+
STRING notepad
7+
ENTER
8+
DELAY 2000
9+
STRING Hello World!
10+
ENTER
11+
END_FUNCTION
12+
COUNTDOWN()
13+

examples/while_loops.dd

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
VAR $TIME = 3
2+
WHILE ($TIME > 0)
3+
STRING .
4+
DELAY 500
5+
STRING While Looop!!
6+
ENTER
7+
END_WHILE

0 commit comments

Comments
 (0)