4 Commits

Author SHA1 Message Date
Dave
68b1262227 Refactor script running to support long delays without blocking webservice 2023-09-17 14:48:46 -05:00
Dave
74ef11770b Clarify getting latest release 2023-06-24 13:07:19 -05:00
Dave
a7992c2fb3 Update installation instructions 2023-06-24 12:58:58 -05:00
Dave
49e81125c1 Updated issue template 2023-06-24 10:01:39 -05:00
5 changed files with 119 additions and 34 deletions

View File

@@ -19,5 +19,11 @@ 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

@@ -16,7 +16,61 @@
<br />
## Install
## Quick Start Guide
Install and have your USB Rubber Ducky working in less than 5 minutes.
1. Download the latest release from the [Releases](https://github.com/dbisu/pico-ducky/releases) page.
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. Install CircutlPython on the Pico or Pico W
If using a Pico board:
Copy the adafruit-circuitpython-raspberry_pi_pico-en_US-8.0.0.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.
If using a Pico W board:
Copy the adafruit-circuitpython-raspberry_pi_pico_w-en_US-8.0.0.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.
4. Copy the lib folder to the root of the CIRCUITPY
5. Copy *.py to the root of the CIRCUITPY
6. Follow the instructions in README.md to enter setup mode
7. Copy your payload as payload.dd to the root of the CIRCUITPY
8. Unplug the device from the USB port and remove the setup jumper.
Enjoy your Pico-Ducky.
## Setup mode
To edit the payload, enter setup mode by connecting the pin 1 (`GP0`) to pin 3 (`GND`), this will stop the pico-ducky from injecting the payload in your own machine.
The easiest way to do so is by using a jumper wire between those pins as seen bellow.
![Setup mode with a jumper](images/setup-mode.png)
## 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.
- Enter setup mode.
- Copy your payload script to the pico-ducky.
- Disconnect the pico from your host PC.
- 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.
- Remove the jumper and reconnect to your PC to reprogram.
Pico: The default mode is USB mass storage enabled.
Pico W: The default mode is USB mass storage **disabled**
![USB enable/disable mode](images/usb-boot-mode.png)
-----
# Full Install Instructions
Install and have your USB Rubber Ducky working in less than 5 minutes.
@@ -70,14 +124,14 @@ API endpoints
/api/run/<filenumber>
```
### Setup mode
## Setup mode
To edit the payload, enter setup mode by connecting the pin 1 (`GP0`) to pin 3 (`GND`), this will stop the pico-ducky from injecting the payload in your own machine.
The easiest way to do so is by using a jumper wire between those pins as seen bellow.
![Setup mode with a jumper](images/setup-mode.png)
### 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.
- Enter setup mode.
@@ -92,7 +146,7 @@ Pico W: The default mode is USB mass storage **disabled**
![USB enable/disable mode](images/usb-boot-mode.png)
### Multiple payloads
## Multiple payloads
Multiple payloads can be stored on the Pico and Pico W.
To select a payload, ground one of these pins:
@@ -101,7 +155,7 @@ To select a payload, ground one of these pins:
- GP10 - payload3.dd
- GP11 - payload4.dd
### Changing Keyboard Layouts
## Changing Keyboard Layouts
Copied from [Neradoc/Circuitpython_Keyboard_Layouts](https://github.com/Neradoc/Circuitpython_Keyboard_Layouts/blob/main/PICODUCKY.md)

View File

@@ -11,6 +11,7 @@ import time
import digitalio
from board import *
import board
import duckyinpython
from duckyinpython import *
if(board.board_id == 'raspberry_pi_pico_w'):
import wifi
@@ -56,7 +57,8 @@ if(progStatus == False):
# not in setup mode, inject the payload
payload = selectPayload()
print("Running ", payload)
runScript(payload)
#runScript(payload)
duckyinpython.fileToRun = payload
print("Done")
else:
@@ -68,15 +70,16 @@ async def main_loop():
global led,button1
button_task = asyncio.create_task(monitor_buttons(button1))
script_task = asyncio.create_task(runScriptTask())
if(board.board_id == 'raspberry_pi_pico_w'):
pico_led_task = asyncio.create_task(blink_pico_w_led(led))
print("Starting Wifi")
startWiFi()
print("Starting Web Service")
webservice_task = asyncio.create_task(startWebService())
await asyncio.gather(pico_led_task, button_task, webservice_task)
await asyncio.gather(pico_led_task, button_task, webservice_task, script_task)
else:
pico_led_task = asyncio.create_task(blink_pico_led(led))
await asyncio.gather(pico_led_task, button_task)
await asyncio.gather(pico_led_task, button_task, script_task)
asyncio.run(main_loop())

View File

@@ -80,8 +80,8 @@ def parseLine(line):
if(line[0:3] == "REM"):
# ignore ducky script comments
pass
elif(line[0:5] == "DELAY"):
time.sleep(float(line[6:])/1000)
#elif(line[0:5] == "DELAY"):
# time.sleep(float(line[6:])/1000)
elif(line[0:6] == "STRING"):
sendString(line[7:])
elif(line[0:5] == "PRINT"):
@@ -133,26 +133,44 @@ def getProgrammingStatus():
defaultDelay = 0
def runScript(file):
global defaultDelay
async def runScriptTask():
global defaultDelay, fileToRun
print("starting runScript")
while True:
#print("Checking for file", fileToRun)
if fileToRun is not None:
duckyScriptPath = fileToRun
print("starting",duckyScriptPath)
with open(duckyScriptPath,"r",encoding='utf-8') as f:
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)
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)
await asyncio.sleep_ms(defaultDelay)
elif(line[0:5] == "DELAY"):
delay = int(line[6:])
#print("sleeping for ",delay)
#print(type(delay))
await asyncio.sleep_ms(delay)
previousLine = line
else:
#print("parsing line", line)
parseLine(line)
previousLine = line
#print("sleeping",defaultDelay)
await asyncio.sleep_ms(defaultDelay)
#print("done sleeping")
print("ending",duckyScriptPath)
fileToRun = None
await asyncio.sleep(1)
print("ending runScript")
def selectPayload():
global payload1Pin, payload2Pin, payload3Pin, payload4Pin
@@ -234,7 +252,7 @@ async def blink_pico_w_led(led):
await asyncio.sleep(0.5)
async def monitor_buttons(button1):
global inBlinkeyMode, inMenu, enableRandomBeep, enableSirenMode,pixel
global inBlinkeyMode, inMenu, enableRandomBeep, enableSirenMode,pixel, fileToRun
print("starting monitor_buttons")
button1Down = False
while True:
@@ -257,7 +275,8 @@ async def monitor_buttons(button1):
# Run selected payload
payload = selectPayload()
print("Running ", payload)
runScript(payload)
#runScript(payload)
fileToRun = payload
print("Done")
button1Down = False

View File

@@ -12,6 +12,7 @@ import wsgiserver as server
from adafruit_wsgi.wsgi_app import WSGIApp
import wifi
import duckyinpython
from duckyinpython import *
payload_html = """<!DOCTYPE html>
@@ -209,7 +210,8 @@ def run_script(request, filename):
print("run_script ", filename)
response = response_html.format("Running script " + filename)
#print(response)
runScript(filename)
#runScript(filename)
duckyinpython.fileToRun = filename
return("200 OK",[('Content-Type', 'text/html')], response)
@web_app.route("/")
@@ -223,7 +225,8 @@ def run_script(request, filenumber):
print("run_script ", filenumber)
response = response_html.format("Running script " + filename)
#print(response)
runScript(filename)
#runScript(filename)
duckyinpython.fileToRun = filename
return("200 OK",[('Content-Type', 'text/html')], response)
async def startWebService():
@@ -240,4 +243,4 @@ async def startWebService():
wsgiServer.start()
while True:
wsgiServer.update_poll()
await asyncio.sleep(0)
await asyncio.sleep(0)