import sys import os import argparse current_line = 0 ducky_script = "" ducky_lines = [] # ======================================================= # The following functions handle each a rubber ducky # command. They take the eventual parameter as argument. # ======================================================= def ducky_STRING(text): rtn = b'' for c in text: rtn += char_to_byte(c) return rtn def ducky_REM(rem): return b'' def ducky_ENTER(): return char_to_byte('\n') def ducky_DELAY(delay): rtn = b'' if delay.isdigit(): rtn = b'\x07' + int(delay).to_bytes(7, byteorder='big') else: raise Exception("Invalid delay") return rtn def ducky_ALT(control): return ducky_MODIFIERS(["ALT"], control) def ducky_SHIFT(control): return ducky_MODIFIERS(["SHIFT"], control) def ducky_CTRL(control): return ducky_MODIFIERS(["CTRL"], control) def ducky_COMMAND(control): return ducky_MODIFIERS(["COMMAND"], control) def ducky_GUI(control): return ducky_MODIFIERS(["GUI"], control) def ducky_ESC(control): return ducky_MODIFIERS(["ESC"], control) def ducky_MODIFIERS(modifier_keys, control): """ Returns the bytcode corespnding to the association of the modifier key (ALT, CTRL, ...) and another key. Parameters ----------- modifier_keys: str A string rpreenting a modifier key (defined in lang.modifiers) One of those values: ["CTRL", "SHIFT", "ALT", "COMMAND", "GUI"] control: str A string representing the key. May be empty string, otherwise, must be defined in lang.keys. """ rtn = b'' modifier_key = bytearray(8) for k in modifier_keys: modifier_key = bytes_or(lang.modifiers[k], modifier_key) if control != "": # modifier + something if control.upper() in lang.keys: rtn = bytes_or(modifier_key, lang.keys[control.upper()]) else: raise Exception("Unknown key : \""+control+"\"") else: # Just the modifier key rtn = lang.keys[modifier_key] return rtn def ducky_REPEAT(nb): rtn = b'' if nb.isdigit(): print(int(nb)) print((ducky_to_hex(ducky_lines[current_line-1]))*int(nb)) if current_line != 0: rtn = (ducky_to_hex(ducky_lines[current_line-1]))*int(nb) else: raise Exception("REPEAT can't be the first instruction of the script.") else: raise Exception("Invalid repeatition") return rtn def ducky_KEY(key): rtn = b'' if key in lang.keys: rtn = lang.keys[key] else: raise Exception("Unknown key : \""+key+"\"") return rtn # ======================================================= # ======================================================= # ======================================================= def bytes_or(a, b): """ Returns -------- bytes A bitwise OR operation on the two parameters. """ rtn = bytearray(b'') a_b = bytearray(a) b_b = bytearray(b) if len(a_b) != len(b_b): return b'' i = 0 while i 0: if command[0] in supported_command: if len(command) == 1: rtn = supported_command[command[0]]() else: rtn = supported_command[command[0]](command[1]) elif command[0] in lang.keys: rtn = ducky_KEY(command[0]) else: raise Exception("Invalid script: \"" + command[0] + "\" is not a valid command") return rtn def encode_ducky(): global ducky_lines, current_line ducky_lines = ducky_script.split('\n') rtn = b'' while current_line < len(ducky_lines): l = ducky_lines[current_line] try: rtn += ducky_to_hex(l) except Exception as e: raise Exception("Syntax error at line " + str(current_line+1) + " in the script : \n" + str(e)) current_line += 1 return rtn def generate_output_filename(input_filename): """ Returns the input_filename with a new extention """ return os.path.splitext(input_filename)[0]+'.bin' parser = argparse.ArgumentParser() parser.add_argument('-i', '--input_file', action='store', help="Input filename", required=True) parser.add_argument('-o', '--output_file', action='store', help="Output filename", required=False) parser.add_argument('-l', '--key_layout', action='store', choices=['en_us', 'fr_be'], help="Keyboard layout", required=False, default='en_us') args = parser.parse_args() lang = __import__(args.key_layout) if args.output_file == None: args.output_file = generate_output_filename(args.input_file) f = open(args.input_file, "r") ducky_script = f.read() f.close() compiled = encode_ducky() fo = open(args.output_file, "wb+") fo.write(compiled)