From efd2491a3d19160d9cae2a094e7baa9f2d958196 Mon Sep 17 00:00:00 2001 From: Michael Smith Date: Mon, 26 Feb 2024 18:54:16 +0000 Subject: Implement initial version --- src/injected.c | 77 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 77 insertions(+) create mode 100644 src/injected.c (limited to 'src/injected.c') diff --git a/src/injected.c b/src/injected.c new file mode 100644 index 0000000..bd69474 --- /dev/null +++ b/src/injected.c @@ -0,0 +1,77 @@ +/* + * Copyright © 2024 Michael Smith + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED “AS IS” AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, + * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM + * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR + * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include + +#define FAKEIAT_DEFINES +#include "fakeiat.h" +#include "intdefs.h" +#include "x86.h" + +// The stuff in this file gets called in the address space of the child process! +// Because we're an EXE, our IAT doesn't get filled properly, so in order to +// call kernel32 functions without crashing, make sure they're in the fake IAT. +// See fakeiat.h and wrap.c. + +__declspec(align(4096)) +static uchar trampoline[4096]; // has to be a whole page, obviously + +// simplified version of the usual hook.c code since there's only a single +// function to hook and no need to unhook +static bool hook(void *func_, void *target) { + ulong old; + if (!VirtualProtect(trampoline, sizeof(trampoline), + PAGE_EXECUTE_READWRITE, &old)) { + return false; + } + uchar *func = func_; + while (*func == X86_JMPIW) func += *(int *)(func + 1) + 5; + if (!VirtualProtect(func, 5, PAGE_EXECUTE_READWRITE, &old)) return false; + int len = 0; + for (;;) { + if (func[len] == X86_CALL) return false; + int ilen = x86_len(func + len); + if (ilen == -1) return false; + len += ilen; + if (len >= 5) break; + if (func[len] == X86_JMPIW) return false; + } + memcpy(trampoline, func, len); + trampoline[len] = X86_JMPIW; + uint diff = func - (trampoline + 5); // goto the continuation + memcpy(trampoline + len + 1, &diff, 4); + diff = (uchar *)target - (func + 5); // goto the hook target + func[0] = X86_JMPIW; + memcpy(func + 1, &diff, 4); + // -1 is the current process, and it's a constant in the WDK, so it's + // assumed we can safely avoid the useless GetCurrentProcess call + FlushInstructionCache((void *)-1, func, 5); + return true; +} + +typedef void (*__stdcall GetSystemInfo_func)(SYSTEM_INFO *info); +#define orig_GetSystemInfo ((GetSystemInfo_func)trampoline) +static void __stdcall hook_GetSystemInfo(SYSTEM_INFO *info) { + orig_GetSystemInfo(info); + // Here's where the magic happens! NOTE: the actual limit is a bit higher + // than this, but there's probably not much reason to go over this either. + if (info->dwNumberOfProcessors > 24) info->dwNumberOfProcessors = 24; +} + +__declspec(noinline) int __stdcall injectedentry(int unused) { + return hook((void *)GetSystemInfo, (void *)&hook_GetSystemInfo); +} -- cgit v1.2.3