In order to perform a rickroll over Lora, several things must happen:
- Broadcasting device sends trigger code
- Receiving device picks up trigger code
- Receiving device executes Catscratch payload
Luckily for us, this is a fairly simple task that involves modifying code.py, and creating a duckyscript payload (payload.txt).
Warning
Pinouts vary between USB and Bluetooth Nuggets. Be sure it matches the pinouts
# SPDX-FileCopyrightText: 2024 ladyada for Adafruit Industries & Skicka# SPDX-License-Identifier: MITs# Simple demo of sending and recieving data with the RFM95 LoRa radio.# Author: Tony DiCola / Kody Kinzieimportboardimportbusioimportdigitalioimportneopixelimportadafruit_rfm9ximportdisplayioimportterminaliofromadafruit_display_textimportlabelimportbusiofromadafruit_displayio_sh1106importSH1106importneopixelimporttimeimportusb_hidfromadafruit_hid.keyboardimportKeyboardfromadafruit_hid.keyboard_layout_usimportKeyboardLayoutUSimportusb_hidfromadafruit_hid.keyboardimportKeyboardfromadafruit_hid.keyboard_layout_usimportKeyboardLayoutUSimportadafruit_duckytime.sleep(1)# Sleep for a bit to avoid a race condition on some systemskeyboard=Keyboard(usb_hid.devices)keyboard_layout=KeyboardLayoutUS(keyboard)# We're in the US :)duck=adafruit_ducky.Ducky("payload.txt",keyboard,keyboard_layout)defRickMe():result=TruewhileresultisnotFalse:result=duck.loop()# Release any resources currently in use for the displaysdisplayio.release_displays()i2c=busio.I2C(scl=board.SCL,sda=board.SDA)display_bus=displayio.I2CDisplay(i2c,device_address=0x3C)# Define the width and height of the displayWIDTH=130HEIGHT=64display=SH1106(display_bus,width=WIDTH,height=HEIGHT)pixel=neopixel.NeoPixel(board.IO12,4,brightness=0.2)pixel[0]=(0,0,255)# equivalent# Define radio parameters.RADIO_FREQ_MHZ=915.0# Frequency of the radio in Mhz. Must match your# module! Can be a value like 915.0, 433.0, etc.# Define pins connected to the chip, use these if wiring up the breakout according to the guide:CS=digitalio.DigitalInOut(board.IO13)RESET=digitalio.DigitalInOut(board.IO5)# Or uncomment and instead use these if using a Feather M0 RFM9x board and the appropriate# CircuitPython build:# CS = digitalio.DigitalInOut(board.RFM9X_CS)# RESET = digitalio.DigitalInOut(board.RFM9X_RST)# Initialize SPI bus.spi=busio.SPI(board.IO6,MOSI=board.IO10,MISO=board.IO8)# Initialze RFM radiorfm9x=adafruit_rfm9x.RFM9x(spi,CS,RESET,RADIO_FREQ_MHZ)# Note that the radio is configured in LoRa mode so you can't control sync# word, encryption, frequency deviation, or other settings!# You can however adjust the transmit power (in dB). The default is 13 dB but# high power radios like the RFM95 can go up to 23 dB:rfm9x.tx_power=23# Send a packet. Note you can only send a packet up to 252 bytes in length.# This is a limitation of the radio packet size, so if you need to send larger# amounts of data you will need to break it into smaller send calls. Each send# call will wait for the previous one to finish before continuing.pixel[0]=(255,0,0)# equivalentrfm9x.send(bytes("Ping","utf-8"))print("Sent Ping message!")pixel[0]=(0,0,255)# equivalent# Wait to receive packets. Note that this library can't receive data at a fast# rate, in fact it can only receive and process one 252 byte packet at a time.# This means you should only use this for low bandwidth scenarios, like sending# and receiving a single message at a time.#print("Waiting for packets...")rxCounter=0whileTrue:packet=rfm9x.receive()# Optionally change the receive timeout from its default of 0.5 seconds:# packet = rfm9x.receive(timeout=5.0)# If no packet was received during the timeout then None is returned.ifpacketisNone:# Packet has not been receivedpixel[0]=(0,0,255)# equivalent#print("Received nothing! Listening again...")else:# Received a packet!rxCounter=rxCounter+1pixel[0]=(0,255,0)# equivalent# Print out the raw bytes of the packet:print("Packet Count: {}".format(rxCounter))# And decode to ASCII text and print it too. Note that you always# receive raw bytes and need to convert to a text format like ASCII# if you intend to do string processing on your data. Make sure the# sending side is sending ASCII data before you try to decode!packet_text=str(packet,"ascii")print("Msg: {0}".format(packet_text))# Also read the RSSI (signal strength) of the last received message and# print it.rssi=rfm9x.last_rssiprint("RSSI: {0} dB".format(rssi))if"rickme"inpacket_text:RickMe()#time.sleep(3)
And finally, our payload:
payload.txt
1 2 3 4 5 6 7 8 910
DELAY 1000
GUI SPACE
DELAY 1000
STRING terminal.app
ENTER
DELAY 1000
STRING open "https://youtu.be/dQw4w9WgXcQ"
ENTER
DELAY 5000
SPACE