I really love Hak5's Rubber Ducky. I've seen similar projects but none with Adafruit's CircuitPython. Last year we at India Linux User Group Delhi (ILUG-D) celebrated CircuitPython Day and that was when I first got my hands on Express boards. The best thing about this board is that you got everything on board like Speaker, Mic, Bluetooth, Accelerometer, IR sensor, etc. I really like the fact that it can inject keystrokes via USB, Yea something similar to Rubber Ducky!
Writing a "Hello World!"Using this device is as easy as eating beans. Just plug it in and it'll mount itself. Make a new file called code.py
as CircuitPython will recognize this file as the main file from which it'll run code. You can use any IDE you want but I suggest you to use Mu Editor. It'll automatically recognize the board and then all you gotta do is write code.
Here is an example code which will write "Hello World!" acting as a keyboard.
from adafruit_circuitplayground.express import cpx
from adafruit_hid.keyboard import Keyboard
from adafruit_hid.keyboard_layout_us import KeyboardLayoutUS
from time import sleep
kbd = Keyboard()
layout = KeyboardLayoutUS(kbd)
# give some time to let the computer recognize the
# device as keyboard
sleep(4)
layout.write("Hello World!")
Note: layout
will inject only strings. By this I mean you can't press CTRL using this.
Here's the result :
Ok cool! Now lets make it open Notepad and then type stuff into it. To do that I'll have to explicitly press a key (Win+R in this case) and for that I'll use Keyboard
instance kbd
.
from adafruit_circuitplayground.express import cpx
from adafruit_hid.keyboard import Keyboard
from adafruit_hid.keycode import Keycode
from adafruit_hid.keyboard_layout_us import KeyboardLayoutUS
from time import sleep
kbd = Keyboard()
layout = KeyboardLayoutUS(kbd)
# give some time to let the computer recognize the
# device as keyboard
sleep(4)
# pressing WINDOWS+R to open RUN Prompt
kbd.press(Keycode.WINDOWS)
kbd.press(Keycode.R)
kbd.release(Keycode.WINDOWS)
kbd.release(Keycode.R)
# writing "notepad" in the RUN prompt
layout.write("notepad")
# hitting enter key to open notepad
kbd.press(Keycode.RETURN)
kbd.release(Keycode.RETURN)
# give some time to let notepad open
sleep(0.5)
# writing Hello World
layout.write("Hello World!")
Notice that I used Keycode
to provide the specific key code. You can look at the source if you want to see the codes. Also, note that youcan't press more than 6 keys at once.
No one wants to write 17 lines just to open Notepad and write Hello World. So I'll take Hak5's approach and will make a payload file parser first. That can be easily done in python something like:
try:
with open("payload.txt") as f:
lines = f.read().splitlines()
except:
print("There's no file!")
Now I want to make a dispatcher that'll parse the line and will provide with the correct keycode. That can be done using a dictionary something like this.
At this point the program will be able to do most of the stuff. But I need to add 2 more payload keywords : DELAY
and STRING
. DELAY
will just implement a time.sleep
and STRING
will implement a layout.write
.
As the board provides me with 2 push buttons, I'll use them to execute two different payloads.
The codeMy payload file will look something like this :
#MODE1
DELAY 4
WINDOWS R
STRING notepad
ENTER
DELAY 0.5
STRING HELLO WORLD!
#MODE2
DELAY 4
WINDOWS R
STRING shutdown -s -t 0
ENTER
MODE1 will open a notepad and write HELLO WORLD!
. Whereas, MODE2 will directly shutdown the computer. The portioning of the files in 2 modes can be done using list slicing.
# `lines` is defined in above code snippet
mode_a = lines[lines.index('#MODE1')+1:lines.index('#MODE2')]
mode_b = lines[lines.index('#MODE2')+1:]
The drop
function parses and drops the payload.
Final code lives on my github : https://github.com/nk521/cktpy/blob/master/rubber_python.py (note: you're about to see a really shitty code!)
Final wordsThis express board doesn't provide cool features like multi threading or interrupts (talking about CircuitPython). This is the reason that my code looks really weird because the only thing I can do now is to poll using an infinite loop. Consider starring and making my repo (https://github.com/nk521/cktpy/) a bit beautiful and clean. Also, you can add your CircuitPython projects over there.
Q/AQ. Now everytime I connect express board to my PC it just blasts my payload. How am I supposed to change the payload safely?
A. Boot in safe mode and then change the payload.txt
.
Back to sleep. πͺπ΄
Comments