12 Commits

Author SHA1 Message Date
Dave
d4957e2e95 Doc updates (#104)
* Update instructions to include copying boot.py

* Clean up instructions

* Fix formatting
2022-09-26 20:59:21 -05:00
Dave
6516c8bbe4 Add reset instructions (#99) 2022-09-19 18:11:26 -05:00
Dave
3a7411e55e Change button monitoring and LED to async tasks (#98) 2022-09-18 11:36:22 -05:00
Dave
e51a769cdd Fix library includes and GPIO names (#93) 2022-09-03 08:34:07 -05:00
Dave
f02c061543 Add button to run scripts (#92) 2022-08-28 22:56:16 -05:00
Dave
8a4e710725 Install tool (#77)
* Add link to installation tool

* Update links
2022-06-12 14:10:48 -05:00
Dave
852e8694dd Update issue templates 2022-04-25 18:00:18 -05:00
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
4 changed files with 212 additions and 34 deletions

34
.github/ISSUE_TEMPLATE/bug_report.md vendored Normal file
View File

@@ -0,0 +1,34 @@
---
name: Bug report
about: Create a report to help us improve
title: ''
labels: ''
assignees: ''
---
**Describe the bug**
A clear and concise description of what the bug is.
**To Reproduce**
Steps to reproduce the behavior:
1. Go to '...'
2. Click on '....'
3. Scroll down to '....'
4. See error
**Expected behavior**
A clear and concise description of what you expected to happen.
**Screenshots**
If applicable, add screenshots to help explain your problem.
**Debug info**
If possible, include debug serial data.
On Windows, use PuTTY, connect to the debug serial port (commonly COM3, but could vary)
On Linux, use minicom (minicom -b 115200 -o -D /dev/ttyACM0, where ttyACM0 corresponds to your device)
**Additional context**
Add any other context about the problem here.

View File

@@ -20,21 +20,30 @@
Install and have your USB Rubber Ducky working in less than 5 minutes. 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. Clone the repo to get a local copy of the files. `git clone https://github.com/dbisu/pico-ducky.git`
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`. 2. Download [CircuitPython for the Raspberry Pi Pico](https://circuitpython.org/board/raspberry_pi_pico/). *Updated to 7.0.0
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. Plug the device into a USB port while holding the boot button. It will show up as a removable media device named `RPI-RP2`.
4. Download `adafruit-circuitpython-bundle-7.x-mpy-YYYYMMDD.zip` [here](https://github.com/adafruit/Adafruit_CircuitPython_Bundle/releases/latest) and extract it outside the device. 4. 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`.
5. Navigate to `lib` in the recently extracted folder and copy `adafruit_hid` to the `lib` folder in your Raspberry Pi Pico. 5. Download `adafruit-circuitpython-bundle-7.x-mpy-YYYYMMDD.zip` [here](https://github.com/adafruit/Adafruit_CircuitPython_Bundle/releases/latest) and extract it outside the device.
6. Click [here](https://raw.githubusercontent.com/dbisu/pico-ducky/main/duckyinpython.py), press CTRL + S and save the file as `code.py` in the root of the Raspberry Pi Pico, overwriting the previous file. 6. Navigate to `lib` in the recently extracted folder and copy `adafruit_hid` to the `lib` folder on your Raspberry Pi Pico.
7. Find a script [here](https://github.com/hak5darren/USB-Rubber-Ducky/wiki/Payloads) or [create your own one using Ducky Script](https://github.com/hak5darren/USB-Rubber-Ducky/wiki/Duckyscript) and save it as `payload.dd` in the Pico. 7. Copy `adafruit_debouncer.mpy` and `adafruit_ticks.mpy` to the `lib` folder on your Raspberry Pi Pico.
8. Be careful, if your device isn't in [setup mode](#setup-mode), the device will reboot and after half a second, the script will run. 8. Copy `asyncio` to the `lib` folder on your Pico.
9. Copy `boot.py` from your clone to the root of your Pico.
10. Copy `duckyinpython.py` as `code.py` in the root of the Raspberry Pi Pico, overwriting the previous file.
Linux: `cp duckyinpython.py </path/to/pico/code.py`
11. Find a script [here](https://github.com/hak5darren/USB-Rubber-Ducky/wiki/Payloads) or [create your own one using Ducky Script](https://github.com/hak5darren/USB-Rubber-Ducky/wiki/Duckyscript) and save it as `payload.dd` in the Pico.
12. Be careful, if your device isn't in [setup mode](#setup-mode), the device will reboot and after half a second, the script will run.
### Setup mode ### Setup mode
@@ -46,11 +55,10 @@ The easiest way to so is by using a jumper wire between those pins as seen bello
### USB enable/disable mode ### USB enable/disable mode
If you need the pico-ducky to not show up as a USB mass storage device for stealth, follow these instructions. If you need the pico-ducky to not show up as a USB mass storage device for stealth, follow these instructions.
Enter setup mode. Enter setup mode.
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.
@@ -111,8 +119,33 @@ from keyboard_layout_win_LANG import KeyboardLayout
from keycode_win_LANG import Keycode 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
### How to recover your Pico if it becomes corrupted or doesn't boot.
[Reset Instructions](RESET.md)
### Installation Tool
[raspberrypi5621](https://github.com/raspberrypi5621) Created a tool to convert a blank RPi Pico to a ducky.
You can find the tool [here](https://github.com/raspberrypi5621/pyducky)
### Docs ### Docs
[CircuitPython](https://circuitpython.readthedocs.io/en/6.3.x/README.html) [CircuitPython](https://circuitpython.readthedocs.io/en/6.3.x/README.html)

7
RESET.md Normal file
View File

@@ -0,0 +1,7 @@
# Instructions on how to reset a Raspberry Pi Pico
Follow these instructions if your Pico ends up in an odd state
1. Download the reset firmware from [flash_nuke.uf2](https://datasheets.raspberrypi.com/soft/flash_nuke.uf2)
2. While holding the BOOTSEL button on the Pico, plug in the USB cable to your computer.
3. When the RPI-RP2 drive shows up on your computer, copy the flash_nuke.uf2 file to the Pico
4. After the device reboots, follow the Install instructions [here](https://github.com/dbisu/pico-ducky/blob/main/README.md)

View File

@@ -14,11 +14,33 @@ from adafruit_hid.keycode import Keycode
#from keyboard_layout_win_LANG import KeyboardLayout #from keyboard_layout_win_LANG import KeyboardLayout
#from keycode_win_LANG import Keycode #from keycode_win_LANG import Keycode
import supervisor
import time import time
import digitalio import digitalio
from digitalio import DigitalInOut, Pull
from adafruit_debouncer import Debouncer
from board import * from board import *
led = digitalio.DigitalInOut(LED) import pwmio
led.direction = digitalio.Direction.OUTPUT import asyncio
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,
@@ -101,9 +123,28 @@ def parseLine(line):
kbd = Keyboard(usb_hid.devices) kbd = Keyboard(usb_hid.devices)
layout = KeyboardLayout(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)
led_pwm_up(led)
#init button
button1_pin = DigitalInOut(GP22) # defaults to input
button1_pin.pull = Pull.UP # turn on internal pull-up resistor
button1 = Debouncer(button1_pin)
#init payload selection switch
payload1Pin = digitalio.DigitalInOut(GP4)
payload1Pin.switch_to_input(pull=digitalio.Pull.UP)
payload2Pin = digitalio.DigitalInOut(GP5)
payload2Pin.switch_to_input(pull=digitalio.Pull.UP)
payload3Pin = digitalio.DigitalInOut(GP10)
payload3Pin.switch_to_input(pull=digitalio.Pull.UP)
payload4Pin = digitalio.DigitalInOut(GP11)
payload4Pin.switch_to_input(pull=digitalio.Pull.UP)
def getProgrammingStatus(): def getProgrammingStatus():
# check GP0 for setup mode # check GP0 for setup mode
@@ -120,38 +161,34 @@ def runScript(file):
global defaultDelay global defaultDelay
duckyScriptPath = file duckyScriptPath = file
f = open(duckyScriptPath,"r",encoding='utf-8') try:
previousLine = "" f = open(duckyScriptPath,"r",encoding='utf-8')
for line in f: previousLine = ""
line = line.rstrip() for line in f:
if(line[0:6] == "REPEAT"): line = line.rstrip()
for i in range(int(line[7:])): if(line[0:6] == "REPEAT"):
#repeat the last command for i in range(int(line[7:])):
parseLine(previousLine) #repeat the last command
time.sleep(float(defaultDelay)/1000) parseLine(previousLine)
else: time.sleep(float(defaultDelay)/1000)
parseLine(line) else:
previousLine = line parseLine(line)
time.sleep(float(defaultDelay)/1000) previousLine = line
time.sleep(float(defaultDelay)/1000)
except OSError as e:
print("Unable to open file ", file)
def selectPayload(): def selectPayload():
global payload1Pin, payload2Pin, payload3Pin, payload4Pin
payload = "payload.dd" payload = "payload.dd"
# check switch status # check switch status
# payload1 = GPIO4 to GND # payload1 = GPIO4 to GND
# payload2 = GPIO5 to GND # payload2 = GPIO5 to GND
# payload3 = GPIO10 to GND # payload3 = GPIO10 to GND
# payload4 = GPIO11 to GND # payload4 = GPIO11 to GND
payload1Pin = digitalio.DigitalInOut(GP4)
payload1Pin.switch_to_input(pull=digitalio.Pull.UP)
payload1State = not payload1Pin.value payload1State = not payload1Pin.value
payload2Pin = digitalio.DigitalInOut(GP5)
payload2Pin.switch_to_input(pull=digitalio.Pull.UP)
payload2State = not payload2Pin.value payload2State = not payload2Pin.value
payload3Pin = digitalio.DigitalInOut(GP10)
payload3Pin.switch_to_input(pull=digitalio.Pull.UP)
payload3State = not payload3Pin.value payload3State = not payload3Pin.value
payload4Pin = digitalio.DigitalInOut(GP11)
payload4Pin.switch_to_input(pull=digitalio.Pull.UP)
payload4State = not payload4Pin.value payload4State = not payload4Pin.value
@@ -175,6 +212,63 @@ def selectPayload():
return payload return payload
async def blink_pico_led(led):
print("starting blink_pico_led")
led_state = False
while True:
if led_state:
#led_pwm_up(led)
print("led up")
for i in range(100):
# PWM LED up and down
if i < 50:
led.duty_cycle = int(i * 2 * 65535 / 100) # Up
await asyncio.sleep(0.01)
led_state = False
else:
#led_pwm_down(led)
print("led down")
for i in range(100):
# PWM LED up and down
if i >= 50:
led.duty_cycle = 65535 - int((i - 50) * 2 * 65535 / 100) # Down
await asyncio.sleep(0.01)
led_state = True
await asyncio.sleep(0)
async def monitor_buttons(button1):
global inBlinkeyMode, inMenu, enableRandomBeep, enableSirenMode,pixel
print("starting monitor_buttons")
button1Down = False
while True:
button1.update()
button1Pushed = button1.fell
button1Released = button1.rose
button1Held = not button1.value
if(button1Pushed):
print("Button 1 pushed")
button1Down = True
if(button1Released):
print("Button 1 released")
if(button1Down):
print("push and released")
if(button1Released):
if(button1Down):
# Run selected payload
payload = selectPayload()
print("Running ", payload)
runScript(payload)
print("Done")
button1Down = False
await asyncio.sleep(0)
progStatus = False progStatus = False
progStatus = getProgrammingStatus() progStatus = getProgrammingStatus()
@@ -187,3 +281,13 @@ if(progStatus == False):
print("Done") print("Done")
else: else:
print("Update your payload") print("Update your payload")
led_state = False
async def main_loop():
global led,button1
pico_led_task = asyncio.create_task(blink_pico_led(led))
button_task = asyncio.create_task(monitor_buttons(button1))
await asyncio.gather(pico_led_task, button_task)
asyncio.run(main_loop())