OreBolt-OS/modules/orebolt-pauto/pauto.c

218 lines
7.5 KiB
C
Executable File

/*
* pauto.c -- Payload Automation (HID Keystroke Injector) module
*
* SPDX-License-Identifier: GPL-2.0-or-later
*
* Payload Automation (HID keystroke injector). Scans /data/vault/payloads/ for .macro
* files, parses the OreBolt macro command language (DELAY,
* STRING, REM, modifier+key combos), and sends 8-byte USB
* HID reports via /dev/hidg0. Full USB HID keycode table
* for a-z, A-Z, 0-9, punctuation, F1-F12, and special keys.
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <dirent.h>
#include <fcntl.h>
#include <linux/input.h>
#include "h2_ui.h"
#include "log_manager.h"
#define PAYLOAD_DIR "/data/vault/payloads"
#define HID_DEV "/dev/hidg0"
#define MAX_PAYLOADS 8
#define LINE_BUF 256
#define DELAY_US 12000
static char payload_names[MAX_PAYLOADS][64];
static int payload_count;
static void scan_payloads(void) {
DIR *dir = opendir(PAYLOAD_DIR);
struct dirent *ent;
payload_count = 0;
if (!dir) return;
while ((ent = readdir(dir)) != NULL && payload_count < MAX_PAYLOADS) {
if (ent->d_name[0] == '.') continue;
const char *dot = strrchr(ent->d_name, '.');
if (!dot || strcmp(dot, ".macro") != 0) continue;
strncpy(payload_names[payload_count], ent->d_name, 63);
payload_names[payload_count][63] = '\0';
payload_count++;
}
closedir(dir);
}
static void send_hid_report(int hid_fd, uint8_t modifier, uint8_t keycode) {
uint8_t report[8] = {0};
report[0] = modifier;
report[2] = keycode;
write(hid_fd, report, 8);
memset(report, 0, 8);
write(hid_fd, report, 8);
usleep(DELAY_US);
}
static uint8_t ascii_to_keycode(char c, uint8_t *modifier) {
*modifier = 0;
if (c >= 'a' && c <= 'z') return (uint8_t)(0x04 + (c - 'a'));
if (c >= 'A' && c <= 'Z') { *modifier = 0x02; return (uint8_t)(0x04 + (c - 'A')); }
if (c >= '1' && c <= '9') return (uint8_t)(0x1e + (c - '1'));
if (c == '0') return 0x27;
if (c == ' ') return 0x2c;
if (c == '\n') return 0x28;
if (c == '-') return 0x2d;
if (c == '=') return 0x2e;
if (c == '[') return 0x2f;
if (c == ']') return 0x30;
if (c == '\\') return 0x31;
if (c == ';') return 0x33;
if (c == '\'') return 0x34;
if (c == '`') return 0x35;
if (c == ',') return 0x36;
if (c == '.') return 0x37;
if (c == '/') return 0x38;
if (c == '\t') return 0x2b;
return 0;
}
static uint8_t lookup_modifier(const char *token) {
if (strcmp(token, "CTRL") == 0 || strcmp(token, "CONTROL") == 0) return 0x01;
if (strcmp(token, "SHIFT") == 0) return 0x02;
if (strcmp(token, "ALT") == 0) return 0x04;
if (strcmp(token, "GUI") == 0) return 0x08;
return 0;
}
static uint8_t lookup_keycode(const char *token) {
if (strcmp(token, "ENTER") == 0 || strcmp(token, "RETURN") == 0) return 0x28;
if (strcmp(token, "SPACE") == 0) return 0x2c;
if (strcmp(token, "TAB") == 0) return 0x2b;
if (strcmp(token, "ESC") == 0 || strcmp(token, "ESCAPE") == 0) return 0x29;
if (strcmp(token, "BACKSPACE") == 0) return 0x2a;
if (strcmp(token, "DELETE") == 0 || strcmp(token, "DEL") == 0) return 0x4c;
if (strcmp(token, "F1") == 0) return 0x3a;
if (strcmp(token, "F2") == 0) return 0x3b;
if (strcmp(token, "F3") == 0) return 0x3c;
if (strcmp(token, "F4") == 0) return 0x3d;
if (strcmp(token, "F5") == 0) return 0x3e;
if (strcmp(token, "F6") == 0) return 0x3f;
if (strcmp(token, "F7") == 0) return 0x40;
if (strcmp(token, "F8") == 0) return 0x41;
if (strcmp(token, "F9") == 0) return 0x42;
if (strcmp(token, "F10") == 0) return 0x43;
if (strcmp(token, "F11") == 0) return 0x44;
if (strcmp(token, "F12") == 0) return 0x45;
if (token[0] != '\0' && token[1] == '\0') {
uint8_t mod;
uint8_t kc = ascii_to_keycode(token[0], &mod);
if (kc) return kc;
}
return 0;
}
static void execute_payload(const char *filename) {
int hid_fd = open(HID_DEV, O_WRONLY);
if (hid_fd < 0) { LOG_ERR("cannot open %s", HID_DEV); return; }
char path[128];
snprintf(path, sizeof(path), "%s/%s", PAYLOAD_DIR, filename);
FILE *fp = fopen(path, "r");
if (!fp) { close(hid_fd); return; }
LOG_INF("executing payload: %s", filename);
char line[LINE_BUF];
while (fgets(line, LINE_BUF, fp)) {
line[strcspn(line, "\r\n")] = '\0';
if (strncmp(line, "DELAY ", 6) == 0) {
long ms = atol(line + 6);
if (ms < 0) ms = 0;
if (ms > 60000) ms = 60000;
usleep((useconds_t)(ms * 1000));
continue;
}
if (strncmp(line, "STRING ", 7) == 0) {
const char *p = line + 7;
while (*p) {
uint8_t mod = 0, key = ascii_to_keycode(*p, &mod);
if (key) send_hid_report(hid_fd, mod, key);
p++;
}
continue;
}
if (strncmp(line, "REM ", 4) == 0 || strcmp(line, "REM") == 0) continue;
char tokens[8][32];
int ntok = 0;
char *p = line;
while (*p && ntok < 8) {
while (*p == ' ') p++;
if (!*p) break;
int ti = 0;
while (*p && *p != ' ' && ti < 31) tokens[ntok][ti++] = *p++;
tokens[ntok][ti] = '\0';
ntok++;
}
if (ntok == 0) continue;
if (ntok == 1) {
uint8_t kc = lookup_keycode(tokens[0]);
if (kc) { send_hid_report(hid_fd, 0, kc); continue; }
}
uint8_t mods = 0;
for (int t = 0; t < ntok - 1; t++) mods |= lookup_modifier(tokens[t]);
uint8_t keycode = lookup_keycode(tokens[ntok - 1]);
if (mods || keycode) { send_hid_report(hid_fd, mods, keycode); continue; }
}
fclose(fp);
close(hid_fd);
LOG_INF("payload complete: %s", filename);
}
int main(void) {
init_h2_graphics_runtime("HID KEYSTROKE INJECTOR");
LOG_INF("pauto module started");
lv_obj_t *scr = lv_scr_act();
lv_obj_t *title = lv_label_create(scr);
lv_label_set_text(title, "HID PAYLOAD INJECTOR");
lv_obj_align(title, LV_ALIGN_TOP_MID, 0, 15);
lv_obj_set_style_text_color(title, COLOR_PRIMARY, LV_PART_MAIN);
scan_payloads();
LOG_INF("found %d .macro payloads", payload_count);
lv_obj_t *list = lv_list_create(scr);
lv_obj_set_size(list, 280, 140);
lv_obj_align(list, LV_ALIGN_CENTER, 0, 15);
if (payload_count == 0) {
lv_list_add_text(list, "No .macro files found in payload dir");
}
int sel = 0;
for (int i = 0; i < payload_count; i++) {
lv_list_add_btn(list, LV_SYMBOL_FILE, payload_names[i]);
}
int input_fd = open("/dev/input/event0", O_RDONLY | O_NONBLOCK);
struct input_event ev;
while (1) {
lv_timer_handler();
if (input_fd >= 0 && read(input_fd, &ev, sizeof(struct input_event)) > 0) {
if (ev.type == EV_REL && ev.code == 0) {
if (ev.value > 0 && sel < payload_count - 1) sel++;
else if (ev.value < 0 && sel > 0) sel--;
}
if (ev.type == EV_KEY && ev.code == H2_KEY_PLAY && ev.value == 1 && payload_count > 0) {
execute_payload(payload_names[sel]);
}
if (ev.type == EV_KEY && ev.code == H2_KEY_BACK && ev.value == 1) break;
}
usleep(20000);
}
if (input_fd >= 0) close(input_fd);
LOG_INF("pauto module exited");
return 0;
}