From c560dc7ee2156891dc0dd2c271e4e7218e914434 Mon Sep 17 00:00:00 2001 From: Tau Date: Thu, 8 Nov 2018 16:02:34 -0500 Subject: [PATCH] util/spike.c: Add configurable log "spike" injector --- util/meson.build | 2 + util/spike.c | 191 +++++++++++++++++++++++++++++++++++++++++++++++ util/spike.h | 3 + 3 files changed, 196 insertions(+) create mode 100644 util/spike.c create mode 100644 util/spike.h diff --git a/util/meson.build b/util/meson.build index 1d69d090..455c6a36 100644 --- a/util/meson.build +++ b/util/meson.build @@ -19,5 +19,7 @@ util_lib = static_library( 'gfx.h', 'setupapi.c', 'setupapi.h', + 'spike.c', + 'spike.h', ], ) diff --git a/util/spike.c b/util/spike.c new file mode 100644 index 00000000..f399d494 --- /dev/null +++ b/util/spike.c @@ -0,0 +1,191 @@ +#include + +#include +#include +#include +#include + +#include "hook/pe.h" + +#include "util/dprintf.h" +#include "util/spike.h" + +/* Spike functions. Their "style" is named after the libc function they bear + the closest resemblance to. */ + +static void spike_fn_puts(const char *msg) +{ + char line[512]; + + sprintf_s(line, _countof(line), "%s\n", msg); + OutputDebugStringA(line); +} + +static void spike_fn_fputs(const char *msg) +{ + OutputDebugStringA(msg); +} + +static void spike_fn_vprintf( + const char *proc, + int line_no, + const char *fmt, + va_list ap) +{ + char msg[512]; + char line[512]; + + vsprintf_s(msg, _countof(msg), fmt, ap); + sprintf_s(line, _countof(line), "%s:%i: %s", proc, line_no, msg); + OutputDebugStringA(line); +} + +static void spike_fn_vwprintf( + const wchar_t *proc, + int line_no, + const wchar_t *fmt, + va_list ap) +{ + wchar_t msg[512]; + wchar_t line[512]; + + vswprintf_s(msg, _countof(msg), fmt, ap); + swprintf_s(line, _countof(line), L"%s:%i: %s", proc, line_no, msg); + OutputDebugStringW(line); +} + +static void spike_fn_perror( + int a1, + int a2, + int error, + const char *file, + int line_no, + const char *msg) +{ + char line[512]; + + sprintf_s( + line, + _countof(line), + "%s:%i:%08x: %s\n", + file, + line_no, + error, + msg); + + OutputDebugStringA(line); +} + +/* Spike inserters */ + +static void spike_insert_jmp(ptrdiff_t rva, void *proc) +{ + uint8_t *base; + uint8_t *target; + uint8_t *func_ptr; + uint32_t delta; + + base = (uint8_t *) GetModuleHandleW(NULL); + + target = base + rva; + func_ptr = proc; + delta = func_ptr - target - 4; /* -4: EIP delta, after end of target insn */ + + pe_patch(target, &delta, sizeof(delta)); +} + +static void spike_insert_ptr(ptrdiff_t rva, void *ptr) +{ + uint8_t *base; + uint8_t *target; + + base = (uint8_t *) GetModuleHandleW(NULL); + target = base + rva; + + pe_patch(target, &ptr, sizeof(ptr)); +} + +static void spike_insert_log_levels(ptrdiff_t rva, size_t count) +{ + uint8_t *base; + uint32_t *levels; + size_t i; + + base = (uint8_t *) GetModuleHandleW(NULL); + levels = (uint32_t *) (base + rva); + + for (i = 0 ; i < count ; i++) { + levels[i] = 255; + } +} + +/* Config reader */ + +void spike_hook_init(void) +{ + int match; + int count; + int rva; + char line[80]; + char *ret; + FILE *f; + + f = fopen("spike.txt", "r"); + + if (f == NULL) { + return; + } + + dprintf("Found spike config, inserting spikes\n"); + + for (;;) { + ret = fgets(line, sizeof(line), f); + + if (ret == NULL) { + break; + } + + if (line[0] == '#' || line[0] == '\r' || line[0] == '\n') { + continue; + } + + match = sscanf(line, "levels %i %i", &rva, &count); + + if (match == 2) { + spike_insert_log_levels((ptrdiff_t) rva, count); + } + + match = sscanf(line, "j_vprintf %i", &rva); + + if (match == 1) { + spike_insert_jmp((ptrdiff_t) rva, spike_fn_vprintf); + } + + match = sscanf(line, "j_vwprintf %i", &rva); + + if (match == 1) { + spike_insert_jmp((ptrdiff_t) rva, spike_fn_vwprintf); + } + + match = sscanf(line, "j_puts %i", &rva); + + if (match == 1) { + spike_insert_jmp((ptrdiff_t) rva, spike_fn_puts); + } + + match = sscanf(line, "j_perror %i", &rva); + + if (match == 1) { + spike_insert_jmp((ptrdiff_t) rva, spike_fn_perror); + } + + match = sscanf(line, "c_fputs %i", &rva); /* c == "callback" */ + + if (match == 1) { + spike_insert_ptr((ptrdiff_t) rva, spike_fn_fputs); + } + } + + dprintf("Spike insertion complete\n"); + fclose(f); +} diff --git a/util/spike.h b/util/spike.h new file mode 100644 index 00000000..a62b4c7b --- /dev/null +++ b/util/spike.h @@ -0,0 +1,3 @@ +#pragma once + +void spike_hook_init(void);