15 Commits
v1.1 ... v1.3

Author SHA1 Message Date
Dave
2876f80140 Update README to clarify non-US keyboard instructions (#70) 2022-04-10 11:51:41 -05:00
Aask
0988524506 making light pwm (#68)
Co-authored-by: unknown <ask.wietting@gmail.com>
2022-04-05 18:23:06 -05:00
dbisu
e11b087b75 Add exception handling to file open 2022-04-03 13:52:40 -05:00
mm12
f79fe2cb48 Update README.md (#65) 2022-03-27 13:27:58 -05:00
Dave
3d101c82d4 Disable auto reload when a new payload or code is deployed. Add blinking LED when board is idle, ready for reload or payload is finished running (#59) 2022-03-18 15:03:35 -05:00
Phil
3fd60760c6 Saving some memory (#55)
* saving some memory

* remove print

* better syntax

* Update duckyinpython.py
2022-03-10 18:11:35 -06:00
Dave
21ffbeb415 Adding support for four position switch to select payloads (#51) 2022-02-24 20:14:02 -06:00
Neradoc
895fc7af58 Removed keyboard_layout.py (#50)
`keyboard_layout.py` is now in adafruit_hid (version 5+) and no longer needed.
2022-02-11 22:03:44 -06:00
Elisha Hollander
11467900c5 remove second DELETE (#46) 2022-01-16 10:05:58 -06:00
dbisu
fc0c2556e0 Fixed typo 2021-12-11 10:57:41 -06:00
martia_f
bb5c33f068 Added new features and optimization [READ EXTENDED DESCRIPTION] (#39)
* [READ EXTENDED DESCRIPTION]

Changes made:
1. Removed a few print statements for a bit less cluttering (Makes debugging a bit harder)
2. Added a PRINT command for writing to console.
3. Added an IMPORT command for running external ".dd" files.
4. Added an LED command that toggles the builtin LED.

* Updated the DELETE keycode
2021-12-09 07:24:55 -06:00
dbisu
39537f4802 Update installation instructions 2021-11-29 20:35:27 -06:00
dbisu
ca5c012d8d Added license and copyright information clarity (#36) 2021-11-18 18:04:46 -06:00
Andreas Brett
21cf5ffdf2 fix: defaultdelay not set correctly (#34) 2021-11-06 11:59:05 -05:00
dbisu
df615dd645 Keyboard layouts (#30)
* Make switching keyboard layouts easier

* Fix broken image link

* fix typos
2021-10-31 11:42:46 -05:00
2 changed files with 214 additions and 29 deletions

View File

@@ -22,7 +22,7 @@ Install and have your USB Rubber Ducky working in less than 5 minutes.
1. Download [CircuitPython for the Raspberry Pi Pico](https://circuitpython.org/board/raspberry_pi_pico/). *Updated to 7.0.0 1. Download [CircuitPython for the Raspberry Pi Pico](https://circuitpython.org/board/raspberry_pi_pico/). *Updated to 7.0.0
2. Plug the device into a USB port. It will show up as a removable media device named `RPI-RP2`. 2. Plug the device into a USB port while holding the boot button. It will show up as a removable media device named `RPI-RP2`.
3. Copy the downloaded `.uf2` file to the root of the Pico (`RPI-RP2`). The device will reboot and after a second or so, it will reconnect as `CIRCUITPY`. 3. Copy the downloaded `.uf2` file to the root of the Pico (`RPI-RP2`). The device will reboot and after a second or so, it will reconnect as `CIRCUITPY`.
@@ -50,13 +50,83 @@ Enter setup mode.
Copy boot.py to the root of the pico-ducky. Copy boot.py to the root of the pico-ducky.
Copy your payload script to the pico-ducky. Copy your payload script to the pico-ducky.
Disconnect the pico from your host PC. Disconnect the pico from your host PC.
Connect a jumper wire between pin 18 and pin 20. Connect a jumper wire between pin 18 (`GND`) and pin 20 (`GPIO15`).
This will prevent the pico-ducky from showing up as a USB drive when plugged into the target computer. This will prevent the pico-ducky from showing up as a USB drive when plugged into the target computer.
Remove the jumper and reconnect to your PC to reprogram. Remove the jumper and reconnect to your PC to reprogram.
The default mode is USB mass storage enabled. The default mode is USB mass storage enabled.
![USB enable/disable mode](images/usb-boot-mode.png) ![USB enable/disable mode](images/usb-boot-mode.png)
### Changing Keyboard Layouts
Copied from [Neradoc/Circuitpython_Keyboard_Layouts](https://github.com/Neradoc/Circuitpython_Keyboard_Layouts/blob/main/PICODUCKY.md)
#### How to use one of these layouts with the pico-ducky repository.
**Go to the [latest release page](https://github.com/Neradoc/Circuitpython_Keyboard_Layouts/releases/latest), look if your language is in the list.**
#### If your language/layout is in the bundle
Download the `py` zip, named `circuitpython-keyboard-layouts-py-XXXXXXXX.zip`
**NOTE: You can use the mpy version targetting the version of Circuitpython that is on the device, but on Raspberry Pi Pico you don't need it - they only reduce file size and memory use on load, which the pico has plenty of.**
#### If your language/layout is not in the bundle
Try the online generator, it should get you a zip file with the bundles for yout language
https://www.neradoc.me/layouts/
#### Now you have a zip file
#### Find your language/layout in the lib directory
For a language `LANG`, copy the following files from the zip's `lib` folder to the `lib` directory of the board.
**DO NOT** modify the adafruit_hid directory. Your files go directly in `lib`.
**DO NOT** change the names or extensions of the files. Just pick the right ones.
Replace `LANG` with the letters for your language of choice.
- `keyboard_layout_win_LANG.py`
- `keycode_win_LANG.py`
Don't forget to get [the adafruit_hid library](https://github.com/adafruit/Adafruit_CircuitPython_HID/releases/latest).
This is what it should look like **if your language is French for example**.
![CIRCUITPY drive screenshot](https://github.com/Neradoc/Circuitpython_Keyboard_Layouts/raw/main/docs/drive_pico_ducky.png)
#### Modify the pico-ducky code to use your language file:
At the start of the file comment out these lines:
```py
from adafruit_hid.keyboard_layout_us import KeyboardLayoutUS as KeyboardLayout
from adafruit_hid.keycode import Keycode
```
Uncomment these lines:
*Replace `LANG` with the letters for your language of choice. The name must match the file (without the py or mpy extension).*
```py
from keyboard_layout_win_LANG import KeyboardLayout
from keycode_win_LANG import Keycode
```
##### Example: Set to German Keyboard (WIN_DE)
```py
from keyboard_layout_win_de import KeyboardLayout
from keycode_win_de import Keycode
```
Copy the files keyboard_layout_win_de.mpy and keycode_win_de.mpy to the /lib folder on the Pico board
```
adafruit_hid/
keyboard_layout_win_de.mpy
keycode_win_de.mpy
```
## Useful links and resources ## Useful links and resources
### Docs ### Docs

View File

@@ -1,10 +1,43 @@
# License : GPLv2.0
# copyright (c) 2021 Dave Bailey
# Author: Dave Bailey (dbisu, @daveisu)
import usb_hid import usb_hid
from adafruit_hid.keyboard import Keyboard from adafruit_hid.keyboard import Keyboard
from adafruit_hid.keyboard_layout_us import KeyboardLayoutUS
# comment out these lines for non_US keyboards
from adafruit_hid.keyboard_layout_us import KeyboardLayoutUS as KeyboardLayout
from adafruit_hid.keycode import Keycode from adafruit_hid.keycode import Keycode
# uncomment these lines for non_US keyboards
# replace LANG with appropriate language
#from keyboard_layout_win_LANG import KeyboardLayout
#from keycode_win_LANG import Keycode
import supervisor
import time import time
import digitalio import digitalio
from board import * from board import *
import pwmio
led = pwmio.PWMOut(LED, frequency=5000, duty_cycle=0)
def led_pwm_up(led):
for i in range(100):
# PWM LED up and down
if i < 50:
led.duty_cycle = int(i * 2 * 65535 / 100) # Up
time.sleep(0.01)
def led_pwm_down(led):
for i in range(100):
# PWM LED up and down
if i >= 50:
led.duty_cycle = 65535 - int((i - 50) * 2 * 65535 / 100) # Down
time.sleep(0.01)
# led = digitalio.DigitalInOut(LED)
# led.direction = digitalio.Direction.OUTPUT
duckyCommands = { duckyCommands = {
'WINDOWS': Keycode.WINDOWS, 'GUI': Keycode.GUI, 'WINDOWS': Keycode.WINDOWS, 'GUI': Keycode.GUI,
@@ -18,6 +51,7 @@ duckyCommands = {
'INSERT': Keycode.INSERT, 'NUMLOCK': Keycode.KEYPAD_NUMLOCK, 'PAGEUP': Keycode.PAGE_UP, 'INSERT': Keycode.INSERT, 'NUMLOCK': Keycode.KEYPAD_NUMLOCK, 'PAGEUP': Keycode.PAGE_UP,
'PAGEDOWN': Keycode.PAGE_DOWN, 'PRINTSCREEN': Keycode.PRINT_SCREEN, 'ENTER': Keycode.ENTER, 'PAGEDOWN': Keycode.PAGE_DOWN, 'PRINTSCREEN': Keycode.PRINT_SCREEN, 'ENTER': Keycode.ENTER,
'SCROLLLOCK': Keycode.SCROLL_LOCK, 'SPACE': Keycode.SPACE, 'TAB': Keycode.TAB, 'SCROLLLOCK': Keycode.SCROLL_LOCK, 'SPACE': Keycode.SPACE, 'TAB': Keycode.TAB,
'BACKSPACE': Keycode.BACKSPACE,
'A': Keycode.A, 'B': Keycode.B, 'C': Keycode.C, 'D': Keycode.D, 'E': Keycode.E, 'A': Keycode.A, 'B': Keycode.B, 'C': Keycode.C, 'D': Keycode.D, 'E': Keycode.E,
'F': Keycode.F, 'G': Keycode.G, 'H': Keycode.H, 'I': Keycode.I, 'J': Keycode.J, 'F': Keycode.F, 'G': Keycode.G, 'H': Keycode.H, 'I': Keycode.I, 'J': Keycode.J,
'K': Keycode.K, 'L': Keycode.L, 'M': Keycode.M, 'N': Keycode.N, 'O': Keycode.O, 'K': Keycode.K, 'L': Keycode.L, 'M': Keycode.M, 'N': Keycode.N, 'O': Keycode.O,
@@ -27,11 +61,11 @@ duckyCommands = {
'F4': Keycode.F4, 'F5': Keycode.F5, 'F6': Keycode.F6, 'F7': Keycode.F7, 'F4': Keycode.F4, 'F5': Keycode.F5, 'F6': Keycode.F6, 'F7': Keycode.F7,
'F8': Keycode.F8, 'F9': Keycode.F9, 'F10': Keycode.F10, 'F11': Keycode.F11, 'F8': Keycode.F8, 'F9': Keycode.F9, 'F10': Keycode.F10, 'F11': Keycode.F11,
'F12': Keycode.F12, 'F12': Keycode.F12,
}
}
def convertLine(line): def convertLine(line):
newline = [] newline = []
print(line) # print(line)
# loop on each key - the filter removes empty values # loop on each key - the filter removes empty values
for key in filter(None, line.split(" ")): for key in filter(None, line.split(" ")):
key = key.upper() key = key.upper()
@@ -46,7 +80,7 @@ def convertLine(line):
else: else:
# if it's not a known key name, show the error for diagnosis # if it's not a known key name, show the error for diagnosis
print(f"Unknown key: <{key}>") print(f"Unknown key: <{key}>")
print(newline) # print(newline)
return newline return newline
def runScriptLine(line): def runScriptLine(line):
@@ -58,6 +92,7 @@ def sendString(line):
layout.write(line) layout.write(line)
def parseLine(line): def parseLine(line):
global defaultDelay
if(line[0:3] == "REM"): if(line[0:3] == "REM"):
# ignore ducky script comments # ignore ducky script comments
pass pass
@@ -65,46 +100,126 @@ def parseLine(line):
time.sleep(float(line[6:])/1000) time.sleep(float(line[6:])/1000)
elif(line[0:6] == "STRING"): elif(line[0:6] == "STRING"):
sendString(line[7:]) sendString(line[7:])
elif(line[0:5] == "PRINT"):
print("[SCRIPT]: " + line[6:])
elif(line[0:6] == "IMPORT"):
runScript(line[7:])
elif(line[0:13] == "DEFAULT_DELAY"): elif(line[0:13] == "DEFAULT_DELAY"):
defaultDelay = int(line[14:]) * 10 defaultDelay = int(line[14:]) * 10
elif(line[0:12] == "DEFAULTDELAY"): elif(line[0:12] == "DEFAULTDELAY"):
defaultDelay = int(line[13:]) * 10 defaultDelay = int(line[13:]) * 10
elif(line[0:3] == "LED"):
if(led.value == True):
led.value = False
else:
led.value = True
else: else:
newScriptLine = convertLine(line) newScriptLine = convertLine(line)
runScriptLine(newScriptLine) runScriptLine(newScriptLine)
kbd = Keyboard(usb_hid.devices) kbd = Keyboard(usb_hid.devices)
layout = KeyboardLayoutUS(kbd) layout = KeyboardLayout(kbd)
# turn off automatically reloading when files are written to the pico
supervisor.disable_autoreload()
# sleep at the start to allow the device to be recognized by the host computer # sleep at the start to allow the device to be recognized by the host computer
time.sleep(.5) time.sleep(.5)
# check GP0 for setup mode led_pwm_up(led)
# see setup mode for instructions
progStatus = False def getProgrammingStatus():
progStatusPin = digitalio.DigitalInOut(GP0) # check GP0 for setup mode
progStatusPin.switch_to_input(pull=digitalio.Pull.UP) # see setup mode for instructions
progStatus = not progStatusPin.value progStatusPin = digitalio.DigitalInOut(GP0)
progStatusPin.switch_to_input(pull=digitalio.Pull.UP)
progStatus = not progStatusPin.value
return(progStatus)
defaultDelay = 0 defaultDelay = 0
def runScript(file):
global defaultDelay
duckyScriptPath = file
try:
f = open(duckyScriptPath,"r",encoding='utf-8')
previousLine = ""
for line in f:
line = line.rstrip()
if(line[0:6] == "REPEAT"):
for i in range(int(line[7:])):
#repeat the last command
parseLine(previousLine)
time.sleep(float(defaultDelay)/1000)
else:
parseLine(line)
previousLine = line
time.sleep(float(defaultDelay)/1000)
except OSError as e:
print("Unable to open file ", file)
def selectPayload():
payload = "payload.dd"
# check switch status
# payload1 = GPIO4 to GND
# payload2 = GPIO5 to GND
# payload3 = GPIO10 to GND
# payload4 = GPIO11 to GND
payload1Pin = digitalio.DigitalInOut(GP4)
payload1Pin.switch_to_input(pull=digitalio.Pull.UP)
payload1State = not payload1Pin.value
payload2Pin = digitalio.DigitalInOut(GP5)
payload2Pin.switch_to_input(pull=digitalio.Pull.UP)
payload2State = not payload2Pin.value
payload3Pin = digitalio.DigitalInOut(GP10)
payload3Pin.switch_to_input(pull=digitalio.Pull.UP)
payload3State = not payload3Pin.value
payload4Pin = digitalio.DigitalInOut(GP11)
payload4Pin.switch_to_input(pull=digitalio.Pull.UP)
payload4State = not payload4Pin.value
if(payload1State == True):
payload = "payload.dd"
elif(payload2State == True):
payload = "payload2.dd"
elif(payload3State == True):
payload = "payload3.dd"
elif(payload4State == True):
payload = "payload4.dd"
else:
# if all pins are high, then no switch is present
# default to payload1
payload = "payload.dd"
return payload
progStatus = False
progStatus = getProgrammingStatus()
if(progStatus == False): if(progStatus == False):
# not in setup mode, inject the payload # not in setup mode, inject the payload
duckyScriptPath = "payload.dd" payload = selectPayload()
f = open(duckyScriptPath,"r",encoding='utf-8') print("Running ", payload)
print("Running payload.dd") runScript(payload)
previousLine = ""
duckyScript = f.readlines()
for line in duckyScript:
line = line.rstrip()
if(line[0:6] == "REPEAT"):
for i in range(int(line[7:])):
#repeat the last command
parseLine(previousLine)
time.sleep(float(defaultDelay)/1000)
else:
parseLine(line)
previousLine = line
time.sleep(float(defaultDelay)/1000)
print("Done") print("Done")
else: else:
print("Update your payload") print("Update your payload")
led_state = False
while True:
if led_state:
led_pwm_up(led)
led_state = False
else:
led_pwm_down(led)
led_state = True