diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..c18dd8d --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +__pycache__/ diff --git a/README.md b/README.md index 9bf1783..ab5a035 100644 --- a/README.md +++ b/README.md @@ -2,11 +2,10 @@ Piduck is a program with which you can easily use your Raspberry Pi Zero as a USB HID keyboard. It uses the scripting language [Ducky-Script-v1]. The Project is in Beta and help is needed. -The function `REPEAT`, Control keys and other special character and keys are missing. For now, only the US keyboard layout is available. +The function `REPEAT`, `FN` and other special character and keys are missing. For now, only the US keyboard layout is available. ## Contributions All contributions are welcome! - ## Setup ### HID Setup [Source1][Hid-setup-source1] @@ -70,10 +69,11 @@ Also run these commands as root! Syntax of [Ducky-Script-v1][Ducky-Script-v1-Syntax] Root is needed (again) ### Using Script File -`piduck inject.txt` +`piduck -i inject.txt` ### Input from standard input `piduck` - +### Set Layout +`piduck -l xx` ## Disclamer This project may not be used illegally and i am not responsible for any damages made with or by this project. diff --git a/pd_key_maps/keymap_us.py b/pd_key_maps/keymap_us.py new file mode 100644 index 0000000..841936e --- /dev/null +++ b/pd_key_maps/keymap_us.py @@ -0,0 +1,159 @@ +#!/bin/python3 +commap = { + "LCTRL": 1, + "LSHIFT": 2, + "LALT": 4, + "LMETA": 8, + "RCTRL": 16, + "RSHIFT": 32, + "RALT": 64, + "RMETA": 128, +} +c1map = { + "a": 4, + "b": 5, + "c": 6, + "d": 7, + "e": 8, + "f": 9, + "g": 10, + "h": 11, + "i": 12, + "j": 13, + "k": 14, + "l": 15, + "m": 16, + "n": 17, + "o": 18, + "p": 19, + "q": 20, + "r": 21, + "s": 22, + "t": 23, + "u": 24, + "v": 25, + "w": 26, + "x": 27, + "y": 28, + "z": 29, + "1": 30, + "2": 31, + "3": 32, + "4": 33, + "5": 34, + "6": 35, + "7": 36, + "8": 37, + "9": 38, + "0": 39, + "RETURN": 40, + "ESC": 41, + "BACKSPACE": 42, + "TAB": 43, + "SPACE": 44, + "-": 45, + "=": 46, + "(": 47, + ")": 48, + "\\": 49, + "#": 50, + ":": 51, + '"': 52, + "~": 53, + ",": 54, + ".": 55, + "/": 56, + "CAPSLOCK": 57, + "F1": 58, + "F2": 59, + "F3": 60, + "F4": 61, + "F5": 62, + "F6": 63, + "F7": 64, + "F8": 65, + "F9": 66, + "F10": 67, + "F11": 68, + "F12": 69, + "PRINT": 70, + "SCROLLLOCK": 71, + "PAUSE": 72, + "INSERT": 73, + "HOME": 74, + "PAGEUP": 75, + "DELETE": 76, + "END": 77, + "PAGEDOWN": 78, + "RIGHT": 79, + "LEFT": 80, + "DOWN": 81, + "UP": 82, + "NUMLOCK": 83, + # kp-divide:"54", + # kp-multiply:"55", + # kp-minus:"56", + # kp-plus:"57", + # kp-return:"58", + # kp-1:"59", + # kp-2:"5a", + # kp-3:"5b", + # kp-4:"5c", + # kp-5:"5d", + # kp-6:"5e", + # kp-7:"5f", + # kp-8:"60", + # kp-9:"61", + # kp-0:"62", + # kp-period:"63", + # application:"65", + # power:"66", + # kp-equal:"67", + "F13": 104, + "F14": 105, + "F15": 106, + "F16": 107, + "F17": 108, + "F18": 109, + "F19": 110, + "F20": 111, + "F21": 112, + "F22": 113, + "F23": 114, + "F24": 115, + # execute:116, + # help:117, + # menu:118, + # select:119, + # cancel:120, + # redo:121, + # undo:122, + # cut:123, + # copy:124, + # paste:125, + # find:126, + # mute:127, + # volume-up:128, + # volume-down:129, +} +c2map = {} +for i in range(65, 91): + c2map[chr(i)] = "SHIFT " + chr(i).lower() +aliasmap = { + "CTRL": "LCTRL", + "SHIFT": "LSHIFT", + "ALT": "LALT", + "META": "LMETA", + "CONTROL": "CTRL", + "GUI": "META", + "ESCAPE": "ESC", + "RIGHTARROW": "RIGHT", + "LEFTARROW": "LEFT", + "DOWNARROW": "DOWN", + "UPARROW": "UP", + "CTRL-ALT": "CTRL ALT", + "CTRL-SHIFT": "CTRL SHIFT", + "DEFAULT_DELAY": "DEFAULTDELAY", + " ": "SPACE", + "BREAK": "PAUSE", +} diff --git a/piduck.py b/piduck.py index fa73d9c..17f80a2 100755 --- a/piduck.py +++ b/piduck.py @@ -1,140 +1,116 @@ #!/bin/python3 -import sys +# import sys +import argparse +from importlib import import_module from time import sleep -commap = {} -c1map = { - "a": 4, - "b": 5, - "c": 6, - "d": 7, - "e": 8, - "f": 9, - "g": 10, - "h": 11, - "i": 12, - "j": 13, - "k": 14, - "l": 15, - "m": 16, - "n": 17, - "o": 18, - "p": 19, - "q": 20, - "r": 21, - "s": 22, - "t": 23, - "u": 24, - "v": 25, - "w": 26, - "x": 27, - "y": 28, - "z": 29, - "1": 30, - "2": 31, - "3": 32, - "4": 33, - "5": 34, - "6": 35, - "7": 36, - "8": 37, - "9": 38, - "0": 39, - "RETURN": 40, - "ESC": 41, - "BACKSPACE": 42, - "TAB": 43, - "SPACE": 44, -} -c2map = {} -for i in range(65, 91): - c2map[chr(i)] = "SHIFT " + chr(i).lower() -aliasmap = { - "CTRL-ALT": "CTRL ALT", - "CTRL-SHIFT": "CTRL SHIFT", - "DEFAULT_DELAY": "DEFAULTDELAY", -} +key_layout = "us" default_delay = 10 -string_delay = 10 +string_delay = 1 - -def divide_chunks(l, n): - for i in range(0, len(l), n): - yield l[i : i + n] +piparser = argparse.ArgumentParser() +piparser.add_argument("-i", "--input", help="File input") +piparser.add_argument( + "-l", "--keyboardlayoutcode", help="Language codes specified by ISO639-1:2002" +) +piparser.add_argument("-d", "--defaultdelay", help="The default delay of execution") +piparser.add_argument( + "-s", "--defaultchardelay", help="The default char delay of execution" +) +piargs = piparser.parse_args() +if piargs.keyboardlayoutcode is not None: + key_layout = piargs.keyboardlayoutcode +if piargs.defaultdelay is not None: + default_delay = piargs.defaultdelay +if piargs.defaultchardelay is not None: + string_delay = piargs.defaultchardelay +try: + keymap = import_module("pd_key_maps.keymap_" + key_layout) +except ModuleNotFoundError: + exit(3) def string(string): for char in string: - pharse(char, [], True) + pharse(char, [[], []], True) sleep(string_delay / 100) def pharse(line, known, deltrue): global default_delay global string_delay - command = line.split() - if not deltrue: - if command[0] == "DELAY": - sleep(int(command[1]) / 100) - return - elif command[0] == "REM": - return - elif command[0] == "REPEAT": - return # todo - else: - sleep(default_delay / 100) - if command[0] == "STRING": - string(" ".join(command[1:])) + if line != " ": + command = line.split() + else: + command = [" "] + if command[0] == "DELAY": + sleep(int(command[1]) / 100) + return + elif command[0] == "REM": return + elif command[0] == "REPEAT": + return # todo elif command[0] == "DEFAULTCHARDELAY": string_delay = int(command[1]) return elif command[0] == "DEFAULTDELAY": default_delay = int(command[1]) return - elif command[0] in aliasmap: - pharse(aliasmap[command[0]] + " ".join(command[1:]), True) + else: + if not deltrue: + sleep(default_delay / 100) + if command[0] == "STRING": + string(line[len("STRING ") :]) return - elif command[0] in commap: - known.append(commap[command[0]]) + elif command[0] in keymap.commap: + known[0].append(keymap.commap[command[0]]) pharse(" ".join(command[1:]), known, True) return - elif command[0] in c1map: - known.append(c1map[command[0]]) + elif command[0] in keymap.c1map: + known[1].append(keymap.c1map[command[0]]) out(known) return + elif command[0] in keymap.c2map: + pharse(keymap.c2map[command[0]], known, True) + return + elif command[0] in keymap.aliasmap: + pharse(keymap.aliasmap[command[0]] + " " + " ".join(command[1:]), known, True) + return else: exit(2) def out(ccl): - # ccl_part=list(divide_chunks(ccl, n)) - rep = chr(0) * 2 - i = 2 - for e in ccl: - i += 1 + rep = "" + if len(ccl[0]) > 0: + for e in ccl[0]: + rep = rep + chr(e) + else: + rep = rep + chr(0) + rep = rep + chr(0) + for e in ccl[1]: rep = rep + chr(e) - rep = rep + (chr(0) * (8 - i)) + rep = rep + chr(0) * (8 - len(rep)) with open("/dev/hidg0", "rb+") as fd: fd.write(rep.encode()) fd.write((chr(0) * 8).encode()) def main(): - if len(sys.argv) >= 2: - file1 = open(sys.argv[1], "r") + if piargs.input is not None: + file1 = open(piargs.input, "r") while True: line = file1.readline() if not line: break - pharse(line.strip(), [], False) + pharse(line.strip(), [[], []], False) file1.close() - elif len(sys.argv) == 1: + else: while True: line = input() if not line: break - pharse(line.strip(), [], False) + pharse(line.strip(), [[], []], False) main()