Skip to content

Instantly share code, notes, and snippets.

@finnmglas
Created January 29, 2021 07:55
Show Gist options
  • Save finnmglas/f7b299d86a4d537404dbb82c187633b4 to your computer and use it in GitHub Desktop.
Save finnmglas/f7b299d86a4d537404dbb82c187633b4 to your computer and use it in GitHub Desktop.
Create arduino C++ code from duckyscripts
#This script will be used to translate duckyscript
#(see https://github.com/hak5darren/USB-Rubber-Ducky/wiki/Duckyscript)
#To C / C++ source code which can be compiled for the Digistump AVR Boards
#(also called Digispark)
#Makes use of https://github.com/adnan-alhomssi/DigistumpArduinoDe/blob/master/digistump-avr/libraries/DigisparkKeyboard/DigiKeyboardDe.h
#Last Edit: 18.09.2019
import getopt, sys
inputfile = "" #duckyscript file
outfile = "" #arduino file
hidecomments = False #if false the REM comments are put behind "//"
lang = "De" #De
ledpin = 1
startdelay = 1000 #Depends on your device speed/ security
#show the documentation
def usage():
print("\nDuckyscript to Arudino C Translator\n")
print("Usage:\n")
print("\t-h, --help\t|\tdisplays this text\n")
print("\t-o, --output\t|\tspecify the output ino file\n")
print("\t-c, --content\t|\tspecify the duckyscript file\n")
print("\t-n, --nocomment\t|\tcomments are hidden")
sys.exit(0)
#Dictionaries needed for the translation Process
chars = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l',
'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x',
'y', 'z', 'c', 'd', '1', '2', '3', '4', '5', '6', '7', '8',
'9', '0']
strokes = {**dict([("f"+str(fn),"KEY_F"+str(fn)) for fn in range(1, 13)]),
**dict([(char, "KEY_"+char.upper()) for char in chars]),
'delete': '42', 'home': '74', 'insert': '73', 'pageup': '75',
'pagedown': '78', 'windows': 'MOD_GUI_LEFT', 'gui': 'MOD_GUI_LEFT',
'uparrow': '82', 'downarrow': '81', 'leftarrow': '80',
'rightarrow': '79', 'tab': '43', 'esc': '41', 'escape': '41',
'space': 'KEY_SPACE', 'up': '82', 'down': '81', 'left': '80',
'right': '79', 'pause': '72', 'shift': '225', 'alt': 'MOD_ALT_LEFT',
'break': 'KEY_ENTER', 'enter': 'KEY_ENTER', 'ctrl':'MOD_CONTROL_LEFT',
'control':'MOD_CONTROL_LEFT', 'menu':'101', 'app':'101'}
def match(dictionary, index, line):
try:
return dictionary[index]
except:
print("\nSyntax Error in line ", line, ":")
print(index, "could not be matched")
sys.exit(0)
#This is the core function of this script... everything else is only a wrapper for it
def translate(script):
rval = """
#include "DigiKeyboard"""+lang+""".h"
void setup() {
\tpinMode("""+str(ledpin)+""", OUTPUT); //Initialise the onboard LED
\tDigiKeyboard"""+lang+""".delay("""+str(startdelay)+""");
""" #will be returned in the end
script = script.replace("\r","").split("\n")
ddelay = "0" #delay between strokes
linetranslation = ""
for n in range(len(script)):
line = script[n]
#prevent empty lines from being analyzed
if line == "":
rval += "\n"
continue
#split the line to analyse it
line = line.split(" ")
command = line[0]
args = " ".join(str(i) for i in line[1:])
#Repeat command (for loop)
if command == "REPEAT":
try:
int(args)
except:
print("\nSyntax Error in line ", n+1, ": ", command, " requires")
print("an integer as argument... \"", args, "\" is not one")
sys.exit(0)
rval += "\tfor(int i=0; i<"+args+"; i++){\n"+linetranslation+"\t}\n"
continue
linetranslation = ""
#insert a default delay
if ddelay != "0" and command not in ("DEFAULTDELAY", "DEFAULT_DELAY",
"REM", "DELAY"):
linetranslation += "\tDigiKeyboard"+lang+".delay("+ddelay+");\n"
#Translation of a single line
#Comments
if command == "REM":
if not hidecomments:
linetranslation += "\t//"+args+"\n"
#Default delay between strokes
elif command in ("DEFAULTDELAY","DEFAULT_DELAY"):
try:
int(args)
except:
print("\nSyntax Error in line ", n+1, ": ", command, " requires")
print("an integer as argument... \"", args, "\" is not one")
sys.exit(0)
ddelay = args
#delay
elif command in ("DELAY", "SLEEP"):
try:
int(args)
except:
print("\nSyntax Error in line ", n+1, ": ", command, " requires")
print("an integer as argument... \"", args, "\" is not one")
sys.exit(0)
linetranslation += "\tDigiKeyboard"+lang+".delay("+args+");\n"
#Strings
elif command == "STRING":
linetranslation += "\tDigiKeyboard"+lang+".print(\""+args.replace("\\", "\\\\").replace("\"", "\\\"")+"\");\n"
#One Keystroke
elif len(line) == 1:
try:
linetranslation += "\tDigiKeyboard"+lang+".sendKeyStroke("+strokes[line[0].lower()]+");\n"
except:
print("\nSyntax Error in line ", n+1, ": ", command, " is")
print("not recognized")
sys.exit(0)
#two Keystrokes
elif len(line) == 2:
try:
linetranslation += "\tDigiKeyboard"+lang+".sendKeyStroke("+strokes[line[1].lower()]+", "+strokes[line[0].lower()]+");\n"
except:
print("\nSyntax Error in line ", n+1, ": command is")
print("not recognized")
sys.exit(0)
#too long
else:
print("\nSyntax Error in line ", n+1, ": to many keystrokes")
print("in one single line!!!")
sys.exit(0)
rval += linetranslation
rval += """}
//Blink to show that the attack is done
void loop() {
\tdigitalWrite("""+str(ledpin)+""", HIGH);
\tdelay(200);
\tdigitalWrite("""+str(ledpin)+""", LOW);
\tdelay(200);
}""" #is executed after the attack
return rval
#Here the actual script starts i guess haha
#Parse all commandline arguments
try:
opts, args = getopt.getopt(sys.argv[1:],"ho:c:n",
["help","output","content","nocomment"])
except getopt.GetoptError as err:
print(str(err))
usage()
for o,a in opts:
if o in ("-h","--help"):
usage()
elif o in ("-o", "--output"):
outfile = a
elif o in ("-c", "--content"):
inputfile = a
elif o in ("-n", "--nocomment"):
hidecomments = True
else:
assert False,"Unhandled Option"
if inputfile == "":
if len(sys.argv)>1 and sys.argv[1].split(".")[len(sys.argv[1].split("."))-1] in ("txt", "ds"):
inputfile = sys.argv[1]
else:
usage()
#Try opening the file and reading from it
try:
file = open(inputfile)
filecontent = file.read()
file.close()
except:
print("Error occured during reading the file")
print("Make sure it actually exists\n")
usage()
if filecontent == "":
print("Error: file is empty\n")
usage()
if outfile == "":
outfile = ".".join(inputfile.split(".")[:-1]) + ".ino"
#Translate and write to the outfile
output = translate(filecontent)
file = open(outfile, "w")
file.write(output)
file.close()
print("\nSuccessfully translated", inputfile, "to ", outfile)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment