From 3782248e20a08c8e0d66d5610285462a95a3f596 Mon Sep 17 00:00:00 2001 From: Peder Stray Date: Fri, 24 Mar 2023 19:12:10 +0100 Subject: [PATCH 1/5] Rewrite loop to be non-blocking and non-destructive --- adafruit_ducky.py | 122 +++++++++++++++++++++++----------------------- 1 file changed, 60 insertions(+), 62 deletions(-) diff --git a/adafruit_ducky.py b/adafruit_ducky.py index 9772bd8..8a866e6 100644 --- a/adafruit_ducky.py +++ b/adafruit_ducky.py @@ -128,78 +128,76 @@ def __init__( self.layout = layout self.lines = [] self.default_delay = 0 - self.last = 0 + self.prev_line = None + self.next_index = 0 + self.wait_until = 0 + self.repeat = 0 with open(filename, "r") as duckyscript: for line in duckyscript: - self.lines.append(line[:-1].rstrip("\r")) + line = line.strip(" \r") + if len(line) > 0: + self.lines.append(line) def loop( # pylint: disable=too-many-return-statements - self, line: Optional[str] = None + self ) -> bool: # pylint: disable=too-many-branches """Function that sends a line of the DuckyScript file over hid every time it is called""" - if line is None: - try: - line = self.lines[0] - except IndexError: - print("Done!") - return False - if len(line) != 0: - words = line.split(" ", 1) - start = words[0] - if start == "REM": - print(words[1]) - time.sleep(self.default_delay) - self.lines.pop(0) - return True - - if start in ("DEFAULT_DELAY", "DEFAULTDELAY"): - self.default_delay = int(words[1]) / 1000 - time.sleep(self.default_delay) - self.last = self.lines[0] - self.lines.pop(0) - return True - - if start == "DELAY": - time.sleep(int(words[1]) / 1000) - time.sleep(self.default_delay) - self.last = self.lines[0] - self.lines.pop(0) - return True - - if start == "STRING": - self.layout.write(words[1]) - time.sleep(self.default_delay) - self.last = self.lines[0] - self.lines.pop(0) - return True - - if start == "REPEAT": - print(int(words[1])) - for _ in range(int(words[1])): - self.lines.insert(0, self.last) - self.loop() - self.last = self.lines[0] - self.lines.pop(0) - return True - - self.write_key(start) - if len(words) == 1: - time.sleep(self.default_delay) - self.last = self.lines[0] - self.lines.pop(0) - self.keyboard.release_all() - return True - if len(words[1]): - self.loop(line=words[1]) + + now = time.monotonic_ns() + if now < self.wait_until: + return True + + try: + if self.repeat > 0: + self.repeat -= 1 + line = self.prev_line else: - self.keyboard.release_all() - return True + line = self.lines[self.next_index] + self.next_index += 1 + except IndexError: + print(" DONE!") + self.prev_line = None + self.next_index = 0 + return False + + words = line.split(" ", 1) + start = words[0] + + if start == "REPEAT": + self.repeat = int(words[1]) + return True + + self.prev_line = line + + # print(f" {line}") + + if start == "REM": + # print(words[1]) + return True + + self.wait_until = now + self.default_delay + + if start in ("DEFAULT_DELAY", "DEFAULTDELAY"): + self.wait_until -= self.default_delay + self.default_delay = int(words[1]) * 1000000 + self.wait_until += self.default_delay + return True + + if start == "DELAY": + self.wait_until += int(words[1]) * 1000000 + return True + + if start == "STRING": + self.layout.write(words[1]) + return True + + self.write_key(start) + if len(words) > 1: + for key in words[1].split(" "): + self.write_key(key) self.keyboard.release_all() - time.sleep(self.default_delay) - self.last = self.lines[0] - self.lines.pop(0) return True def write_key(self, start: str) -> None: From bc9fcc88188dec393fd333105702d747604e15bf Mon Sep 17 00:00:00 2001 From: Peder Stray Date: Fri, 24 Mar 2023 19:20:37 +0100 Subject: [PATCH 2/5] Drop optional since it is not in use --- adafruit_ducky.py | 1 - 1 file changed, 1 deletion(-) diff --git a/adafruit_ducky.py b/adafruit_ducky.py index 8a866e6..ee79f73 100644 --- a/adafruit_ducky.py +++ b/adafruit_ducky.py @@ -26,7 +26,6 @@ from adafruit_hid.keycode import Keycode try: - from typing import Optional from adafruit_hid.keyboard import Keyboard from adafruit_hid.keyboard_layout_base import KeyboardLayoutBase except ImportError: From 386b4b08f693b6702fdd8be805bacd2d37da6e81 Mon Sep 17 00:00:00 2001 From: Peder Stray Date: Fri, 24 Mar 2023 19:20:37 +0100 Subject: [PATCH 3/5] Fix some formatting issues --- adafruit_ducky.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/adafruit_ducky.py b/adafruit_ducky.py index ee79f73..855c4fe 100644 --- a/adafruit_ducky.py +++ b/adafruit_ducky.py @@ -139,7 +139,7 @@ def __init__( self.lines.append(line) def loop( # pylint: disable=too-many-return-statements - self + self, ) -> bool: # pylint: disable=too-many-branches """Function that sends a line of the DuckyScript file over hid every time it is called""" From c04a7c45cc258ae9d74bff8e57eb5e4a4eb38c0a Mon Sep 17 00:00:00 2001 From: Peder Stray Date: Tue, 25 Apr 2023 11:40:11 +0200 Subject: [PATCH 4/5] Add \n to strip of input lines to correctly handle last command --- adafruit_ducky.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/adafruit_ducky.py b/adafruit_ducky.py index 855c4fe..236dbe0 100644 --- a/adafruit_ducky.py +++ b/adafruit_ducky.py @@ -134,7 +134,7 @@ def __init__( with open(filename, "r") as duckyscript: for line in duckyscript: - line = line.strip(" \r") + line = line.strip(" \n\r") if len(line) > 0: self.lines.append(line) From 56a2285918d509b595349c81b154915128291d50 Mon Sep 17 00:00:00 2001 From: Peder Stray Date: Wed, 26 Apr 2023 15:58:11 +0200 Subject: [PATCH 5/5] Fix strip and split to allow for significant space in STRING --- adafruit_ducky.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/adafruit_ducky.py b/adafruit_ducky.py index 236dbe0..d588cd7 100644 --- a/adafruit_ducky.py +++ b/adafruit_ducky.py @@ -134,7 +134,7 @@ def __init__( with open(filename, "r") as duckyscript: for line in duckyscript: - line = line.strip(" \n\r") + line = line.lstrip(" ").rstrip("\n\r") if len(line) > 0: self.lines.append(line) @@ -193,7 +193,7 @@ def loop( # pylint: disable=too-many-return-statements self.write_key(start) if len(words) > 1: - for key in words[1].split(" "): + for key in filter(None, words[1].split(" ")): self.write_key(key) self.keyboard.release_all()