From fd9f455bf311645825a8ed5cbe88896cef270aa0 Mon Sep 17 00:00:00 2001 From: icex2 Date: Wed, 14 Aug 2024 17:53:51 +0200 Subject: [PATCH] feat(procmon): Library to hook and monitor selected system calls A general debugging tool. 3rd party applications such as "procmon" (same name) provide these capabilites and even more. But, they are more difficult to run with bemanitools and don't provide a unified look at the output in combination with the log output by bemanitools. Provide an initial set of system call hooks that have already supported debugging efforts. More can be added when needed later. --- Module.mk | 4 + src/main/procmon-lib/Module.mk | 8 + src/main/procmon-lib/procmon.c | 96 +++++++++++ src/main/procmon-lib/procmon.h | 37 +++++ src/main/procmon/Module.mk | 13 ++ src/main/procmon/file.c | 176 ++++++++++++++++++++ src/main/procmon/file.h | 7 + src/main/procmon/module.c | 289 +++++++++++++++++++++++++++++++++ src/main/procmon/module.h | 7 + src/main/procmon/procmon.c | 73 +++++++++ src/main/procmon/procmon.def | 10 ++ src/main/procmon/procmon.h | 21 +++ src/main/procmon/thread.c | 106 ++++++++++++ src/main/procmon/thread.h | 7 + 14 files changed, 854 insertions(+) create mode 100644 src/main/procmon-lib/Module.mk create mode 100644 src/main/procmon-lib/procmon.c create mode 100644 src/main/procmon-lib/procmon.h create mode 100644 src/main/procmon/Module.mk create mode 100644 src/main/procmon/file.c create mode 100644 src/main/procmon/file.h create mode 100644 src/main/procmon/module.c create mode 100644 src/main/procmon/module.h create mode 100644 src/main/procmon/procmon.c create mode 100644 src/main/procmon/procmon.def create mode 100644 src/main/procmon/procmon.h create mode 100644 src/main/procmon/thread.c create mode 100644 src/main/procmon/thread.h diff --git a/Module.mk b/Module.mk index eb28f82..bc1d3a4 100644 --- a/Module.mk +++ b/Module.mk @@ -182,6 +182,8 @@ include src/main/p4ioemu/Module.mk include src/main/popnhook-util/Module.mk include src/main/popnhook1/Module.mk include src/main/popnio/Module.mk +include src/main/procmon/Module.mk +include src/main/procmon-lib/Module.mk include src/main/pcbidgen/Module.mk include src/main/sdvxhook/Module.mk include src/main/sdvxhook2-cn/Module.mk @@ -233,6 +235,7 @@ $(zipdir)/tools.zip: \ build/bin/indep-32/ezusb2-dbg-hook.dll \ build/bin/indep-32/ezusb2-tool.exe \ build/bin/indep-32/ezusb-tool.exe \ + build/bin/indep-32/procmon.dll \ | $(zipdir)/ $(V)echo ... $@ $(V)zip -j $@ $^ @@ -247,6 +250,7 @@ $(zipdir)/tools-x64.zip: \ build/bin/indep-64/iidx-ezusb2-exit-hook.dll \ build/bin/indep-64/jbiotest.exe \ build/bin/indep-64/mempatch-hook.dll \ + build/bin/indep-64/procmon.dll \ | $(zipdir)/ $(V)echo ... $@ $(V)zip -j $@ $^ diff --git a/src/main/procmon-lib/Module.mk b/src/main/procmon-lib/Module.mk new file mode 100644 index 0000000..994dd69 --- /dev/null +++ b/src/main/procmon-lib/Module.mk @@ -0,0 +1,8 @@ +libs += procmon-lib + +libs_procmon-lib := \ + util \ + +src_procmon-lib := \ + procmon.c \ + diff --git a/src/main/procmon-lib/procmon.c b/src/main/procmon-lib/procmon.c new file mode 100644 index 0000000..787aa2e --- /dev/null +++ b/src/main/procmon-lib/procmon.c @@ -0,0 +1,96 @@ +#define LOG_MODULE "procmon-lib" + +#include + +#include "core/log.h" + +#include "procmon-lib/procmon.h" + +#define PROCMON_LIB "procmon.dll" +#define CONCAT(x, y) x##y +#define LOAD_FUNC(lib_func, module, path, func_name) \ + lib_func = (CONCAT(func_name, _t)) GetProcAddress(module, #func_name); \ + if (lib_func == NULL) { \ + log_fatal("Failed to load function '%s' from '%s'", #func_name, path); \ + } + +bool procmon_available() +{ + HMODULE module; + + module = LoadLibraryExA(PROCMON_LIB, NULL, DONT_RESOLVE_DLL_REFERENCES); + + if (module == NULL) { + return false; + } else { + FreeLibrary(module); + return true; + } +} + +void procmon_init(struct procmon *procmon) +{ + log_assert(procmon); + + memset(procmon, 0, sizeof(*procmon)); +} + +void procmon_load(struct procmon *procmon) +{ + HMODULE module; + uint32_t api_version; + + log_assert(procmon); + + module = LoadLibraryA(PROCMON_LIB); + + if (module == NULL) { + LPSTR buffer; + + FormatMessageA( + FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, + GetLastError(), + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), + (LPSTR) &buffer, + 0, + NULL); + + log_fatal("Failed to load library %s: %s", PROCMON_LIB, buffer); + + LocalFree(buffer); + } + + procmon->module = module; + + LOAD_FUNC(procmon->api_version, module, PROCMON_LIB, procmon_api_version); + + api_version = procmon->api_version(); + + if (api_version != 0) { + log_fatal("Unsupported API version %d of %s", api_version, PROCMON_LIB); + } + + LOAD_FUNC(procmon->set_loggers, module, PROCMON_LIB, procmon_set_loggers); + LOAD_FUNC(procmon->init, module, PROCMON_LIB, procmon_init); + LOAD_FUNC( + procmon->file_mon_enable, module, PROCMON_LIB, procmon_file_mon_enable); + LOAD_FUNC( + procmon->module_mon_enable, + module, + PROCMON_LIB, + procmon_module_mon_enable); + LOAD_FUNC( + procmon->thread_mon_enable, + module, + PROCMON_LIB, + procmon_thread_mon_enable); +} + +void procmon_free(struct procmon *procmon) +{ + log_assert(procmon); + + FreeLibrary(procmon->module); +} \ No newline at end of file diff --git a/src/main/procmon-lib/procmon.h b/src/main/procmon-lib/procmon.h new file mode 100644 index 0000000..135a4b8 --- /dev/null +++ b/src/main/procmon-lib/procmon.h @@ -0,0 +1,37 @@ +#ifndef PROCMON_LIB_PROCMON_H +#define PROCMON_LIB_PROCMON_H + +#include + +#include +#include + +#include "core/log.h" + +typedef uint32_t (*procmon_api_version_t)(); +typedef void (*procmon_set_loggers_t)( + core_log_message_t misc, + core_log_message_t info, + core_log_message_t warning, + core_log_message_t fatal); +typedef void (*procmon_file_mon_enable_t)(); +typedef void (*procmon_module_mon_enable_t)(); +typedef void (*procmon_thread_mon_enable_t)(); +typedef void (*procmon_init_t)(); + +struct procmon { + HMODULE module; + procmon_api_version_t api_version; + procmon_set_loggers_t set_loggers; + procmon_file_mon_enable_t file_mon_enable; + procmon_module_mon_enable_t module_mon_enable; + procmon_thread_mon_enable_t thread_mon_enable; + procmon_init_t init; +}; + +void procmon_init(struct procmon *procmon); +bool procmon_available(); +void procmon_load(struct procmon *procmon); +void procmon_free(struct procmon *procmon); + +#endif \ No newline at end of file diff --git a/src/main/procmon/Module.mk b/src/main/procmon/Module.mk new file mode 100644 index 0000000..f1e355d --- /dev/null +++ b/src/main/procmon/Module.mk @@ -0,0 +1,13 @@ +dlls += procmon + +libs_procmon := \ + core \ + hook \ + util \ + +src_procmon := \ + file.c \ + module.c \ + procmon.c \ + thread.c \ + diff --git a/src/main/procmon/file.c b/src/main/procmon/file.c new file mode 100644 index 0000000..229455d --- /dev/null +++ b/src/main/procmon/file.c @@ -0,0 +1,176 @@ +#define LOG_MODULE "procmon-file" + +#include + +#include "core/log.h" + +#include "hook/table.h" + +#include "util/str.h" + +static HANDLE(STDCALL *real_CreateFileW)( + const wchar_t *lpFileName, + uint32_t dwDesiredAccess, + uint32_t dwShareMode, + SECURITY_ATTRIBUTES *lpSecurityAttributes, + uint32_t dwCreationDisposition, + uint32_t dwFlagsAndAttributes, + HANDLE hTemplateFile); +static HANDLE(STDCALL *real_CreateFileA)( + const char *lpFileName, + uint32_t dwDesiredAccess, + uint32_t dwShareMode, + SECURITY_ATTRIBUTES *lpSecurityAttributes, + uint32_t dwCreationDisposition, + uint32_t dwFlagsAndAttributes, + HANDLE hTemplateFile); + +static HANDLE STDCALL my_CreateFileW( + const wchar_t *lpFileName, + uint32_t dwDesiredAccess, + uint32_t dwShareMode, + SECURITY_ATTRIBUTES *lpSecurityAttributes, + uint32_t dwCreationDisposition, + uint32_t dwFlagsAndAttributes, + HANDLE hTemplateFile); + +static HANDLE STDCALL my_CreateFileA( + const char *lpFileName, + uint32_t dwDesiredAccess, + uint32_t dwShareMode, + SECURITY_ATTRIBUTES *lpSecurityAttributes, + uint32_t dwCreationDisposition, + uint32_t dwFlagsAndAttributes, + HANDLE hTemplateFile); + +static const struct hook_symbol _procmon_file_hook_syms[] = { + { + .name = "CreateFileW", + .patch = my_CreateFileW, + .link = (void **) &real_CreateFileW, + }, + { + .name = "CreateFileA", + .patch = my_CreateFileA, + .link = (void **) &real_CreateFileA, + }, +}; + +static HANDLE STDCALL my_CreateFileW( + const wchar_t *lpFileName, + uint32_t dwDesiredAccess, + uint32_t dwShareMode, + SECURITY_ATTRIBUTES *lpSecurityAttributes, + uint32_t dwCreationDisposition, + uint32_t dwFlagsAndAttributes, + HANDLE hTemplateFile) +{ + HANDLE result; + char *tmp; + + wstr_narrow(lpFileName, &tmp); + + log_misc( + "CreateFileW(lpFileName %s, dwDesiredAccess 0x%X, dwShareMode 0x%X, " + "dwCreationDisposition 0x%X, dwFlagsAndAttributes 0x%X, hTemplateFile " + "%p)", + tmp, + dwDesiredAccess, + dwShareMode, + dwCreationDisposition, + dwFlagsAndAttributes, + hTemplateFile); + + result = real_CreateFileW( + lpFileName, + dwDesiredAccess, + dwShareMode, + lpSecurityAttributes, + dwCreationDisposition, + dwFlagsAndAttributes, + hTemplateFile); + + log_misc( + "CreateFileW(lpFileName %s, dwDesiredAccess 0x%X, dwShareMode 0x%X, " + "dwCreationDisposition 0x%X, dwFlagsAndAttributes 0x%X, hTemplateFile " + "%p) = %p", + tmp, + dwDesiredAccess, + dwShareMode, + dwCreationDisposition, + dwFlagsAndAttributes, + hTemplateFile, + result); + + free(tmp); + + return result; +} + +static HANDLE STDCALL my_CreateFileA( + const char *lpFileName, + uint32_t dwDesiredAccess, + uint32_t dwShareMode, + SECURITY_ATTRIBUTES *lpSecurityAttributes, + uint32_t dwCreationDisposition, + uint32_t dwFlagsAndAttributes, + HANDLE hTemplateFile) +{ + HANDLE result; + + log_misc( + "CreateFileA(lpFileName %s, dwDesiredAccess 0x%X, dwShareMode 0x%X, " + "dwCreationDisposition 0x%X, dwFlagsAndAttributes 0x%X, hTemplateFile " + "%p)", + lpFileName, + dwDesiredAccess, + dwShareMode, + dwCreationDisposition, + dwFlagsAndAttributes, + hTemplateFile); + + result = real_CreateFileA( + lpFileName, + dwDesiredAccess, + dwShareMode, + lpSecurityAttributes, + dwCreationDisposition, + dwFlagsAndAttributes, + hTemplateFile); + + log_misc( + "CreateFileA(lpFileName %s, dwDesiredAccess 0x%X, dwShareMode 0x%X, " + "dwCreationDisposition 0x%X, dwFlagsAndAttributes 0x%X, hTemplateFile " + "%p) = %p", + lpFileName, + dwDesiredAccess, + dwShareMode, + dwCreationDisposition, + dwFlagsAndAttributes, + hTemplateFile, + result); + + return result; +} + +void procmon_file_init() +{ + hook_table_apply( + NULL, + "kernel32.dll", + _procmon_file_hook_syms, + lengthof(_procmon_file_hook_syms)); + + log_misc("init"); +} + +void procmon_file_fini() +{ + hook_table_revert( + NULL, + "kernel32.dll", + _procmon_file_hook_syms, + lengthof(_procmon_file_hook_syms)); + + log_misc("fini"); +} \ No newline at end of file diff --git a/src/main/procmon/file.h b/src/main/procmon/file.h new file mode 100644 index 0000000..6b9d751 --- /dev/null +++ b/src/main/procmon/file.h @@ -0,0 +1,7 @@ +#ifndef PROCMON_FILE_H +#define PROCMON_FILE_H + +void procmon_file_init(); +void procmon_file_fini(); + +#endif \ No newline at end of file diff --git a/src/main/procmon/module.c b/src/main/procmon/module.c new file mode 100644 index 0000000..3a130ac --- /dev/null +++ b/src/main/procmon/module.c @@ -0,0 +1,289 @@ +#define LOG_MODULE "procmon-module" + +#include + +#include "core/log.h" + +#include "hook/table.h" + +#include "util/str.h" + +static HMODULE(STDCALL *real_GetModuleHandleA)(LPCSTR lpModuleName); +static BOOL(STDCALL *real_GetModuleHandleExA)( + DWORD dwFlags, LPCSTR lpModuleName, HMODULE *phModule); +static BOOL(STDCALL *real_GetModuleHandleExW)( + DWORD dwFlags, LPCWSTR lpModuleName, HMODULE *phModule); +static HMODULE(STDCALL *real_GetModuleHandleW)(LPCWSTR lpModuleName); +static HMODULE(STDCALL *real_LoadLibraryA)(LPCSTR lpLibFileName); +static HMODULE(STDCALL *real_LoadLibraryW)(LPCWSTR lpLibFileName); +static HMODULE(STDCALL *real_LoadLibraryExA)( + LPCSTR lpLibFileName, HANDLE hFile, DWORD dwFlags); +static HMODULE(STDCALL *real_LoadLibraryExW)( + LPCWSTR lpLibFileName, HANDLE hFile, DWORD dwFlags); +static FARPROC(STDCALL *real_GetProcAddress)( + HMODULE hModule, LPCSTR lpProcName); + +static HMODULE STDCALL my_GetModuleHandleA(LPCSTR lpModuleName); +static BOOL STDCALL +my_GetModuleHandleExA(DWORD dwFlags, LPCSTR lpModuleName, HMODULE *phModule); +static BOOL STDCALL +my_GetModuleHandleExW(DWORD dwFlags, LPCWSTR lpModuleName, HMODULE *phModule); +static HMODULE STDCALL my_GetModuleHandleW(LPCWSTR lpModuleName); +static HMODULE STDCALL my_LoadLibraryA(LPCSTR lpLibFileName); +static HMODULE STDCALL my_LoadLibraryW(LPCWSTR lpLibFileName); +static HMODULE STDCALL +my_LoadLibraryExA(LPCSTR lpLibFileName, HANDLE hFile, DWORD dwFlags); +static HMODULE STDCALL +my_LoadLibraryExW(LPCWSTR lpLibFileName, HANDLE hFile, DWORD dwFlags); +static FARPROC STDCALL my_GetProcAddress(HMODULE hModule, LPCSTR lpProcName); + +static const struct hook_symbol _procmon_module_hook_syms[] = { + { + .name = "GetModuleHandleA", + .patch = my_GetModuleHandleA, + .link = (void **) &real_GetModuleHandleA, + }, + { + .name = "GetModuleHandleExA", + .patch = my_GetModuleHandleExA, + .link = (void **) &real_GetModuleHandleExA, + }, + { + .name = "GetModuleHandleExW", + .patch = my_GetModuleHandleExW, + .link = (void **) &real_GetModuleHandleExW, + }, + { + .name = "GetModuleHandleW", + .patch = my_GetModuleHandleW, + .link = (void **) &real_GetModuleHandleW, + }, + { + .name = "LoadLibraryA", + .patch = my_LoadLibraryA, + .link = (void **) &real_LoadLibraryA, + }, + { + .name = "LoadLibraryW", + .patch = my_LoadLibraryW, + .link = (void **) &real_LoadLibraryW, + }, + { + .name = "LoadLibraryExA", + .patch = my_LoadLibraryExA, + .link = (void **) &real_LoadLibraryExA, + }, + { + .name = "LoadLibraryExW", + .patch = my_LoadLibraryExW, + .link = (void **) &real_LoadLibraryExW, + }, + { + .name = "GetProcAddress", + .patch = my_GetProcAddress, + .link = (void **) &real_GetProcAddress, + }, +}; + +static HMODULE STDCALL my_GetModuleHandleA(LPCSTR lpModuleName) +{ + HMODULE result; + + log_misc("GetModuleHandleA(lpModuleName %s)", lpModuleName); + + result = real_GetModuleHandleA(lpModuleName); + + log_misc("GetModuleHandleA(lpModuleName %s) = %p", lpModuleName, result); + + return result; +} + +static BOOL STDCALL +my_GetModuleHandleExA(DWORD dwFlags, LPCSTR lpModuleName, HMODULE *phModule) +{ + BOOL result; + + log_misc( + "GetModuleHandleExA(dwFlags %lu, lpModuleName %s, phModule %p)", + dwFlags, + lpModuleName, + phModule); + + result = real_GetModuleHandleExA(dwFlags, lpModuleName, phModule); + + log_misc( + "GetModuleHandleExA(dwFlags %lu, lpModuleName %s, phModule %p) = %d", + dwFlags, + lpModuleName, + phModule, + result); + + return result; +} + +static BOOL STDCALL +my_GetModuleHandleExW(DWORD dwFlags, LPCWSTR lpModuleName, HMODULE *phModule) +{ + BOOL result; + char *tmp; + + wstr_narrow(lpModuleName, &tmp); + + log_misc( + "GetModuleHandleExW(dwFlags %lu, lpModuleName %s, phModule %p)", + dwFlags, + tmp, + phModule); + + result = real_GetModuleHandleExW(dwFlags, lpModuleName, phModule); + + log_misc( + "GetModuleHandleExW(dwFlags %lu, lpModuleName %s, phModule %p) = %d", + dwFlags, + tmp, + phModule, + result); + + free(tmp); + + return result; +} + +static HMODULE STDCALL my_GetModuleHandleW(LPCWSTR lpModuleName) +{ + HMODULE result; + char *tmp; + + wstr_narrow(lpModuleName, &tmp); + + log_misc("GetModuleHandleW(lpModuleName %s)", tmp); + + result = real_GetModuleHandleW(lpModuleName); + + log_misc("GetModuleHandleW(lpModuleName %s) = %p", tmp, result); + + free(tmp); + + return result; +} + +static HMODULE STDCALL my_LoadLibraryA(LPCSTR lpLibFileName) +{ + HMODULE result; + + log_misc("LoadLibraryA(lpLibFileName %s)", lpLibFileName); + + result = real_LoadLibraryA(lpLibFileName); + + log_misc("LoadLibraryA(lpLibFileName %s) = %p", lpLibFileName, result); + + return result; +} + +static HMODULE STDCALL my_LoadLibraryW(LPCWSTR lpLibFileName) +{ + HMODULE result; + char *tmp; + + wstr_narrow(lpLibFileName, &tmp); + + log_misc("LoadLibraryW(lpLibFileName %s)", tmp); + + result = real_LoadLibraryW(lpLibFileName); + + log_misc("LoadLibraryW(lpLibFileName %s) = %p", tmp, result); + + free(tmp); + + return result; +} + +static HMODULE STDCALL +my_LoadLibraryExA(LPCSTR lpLibFileName, HANDLE hFile, DWORD dwFlags) +{ + HMODULE result; + + log_misc( + "LoadLibraryExA(lpLibFileName %s, hFile %p, dwFlags %lu)", + lpLibFileName, + hFile, + dwFlags); + + result = real_LoadLibraryExA(lpLibFileName, hFile, dwFlags); + + log_misc( + "LoadLibraryExA(lpLibFileName %s, hFile %p, dwFlags %lu) = %p", + lpLibFileName, + hFile, + dwFlags, + result); + + return result; +} + +static HMODULE STDCALL +my_LoadLibraryExW(LPCWSTR lpLibFileName, HANDLE hFile, DWORD dwFlags) +{ + HMODULE result; + char *tmp; + + wstr_narrow(lpLibFileName, &tmp); + + log_misc( + "LoadLibraryExA(lpLibFileName %s, hFile %p, dwFlags %lu)", + tmp, + hFile, + dwFlags); + + result = real_LoadLibraryExW(lpLibFileName, hFile, dwFlags); + + log_misc( + "LoadLibraryExA(lpLibFileName %s, hFile %p, dwFlags %lu) = %p", + tmp, + hFile, + dwFlags, + result); + + free(tmp); + + return result; +} + +static FARPROC STDCALL my_GetProcAddress(HMODULE hModule, LPCSTR lpProcName) +{ + FARPROC result; + + log_misc("GetProcAddress(hModule %p, lpProcName %s)", hModule, lpProcName); + + result = real_GetProcAddress(hModule, lpProcName); + + log_misc( + "GetProcAddress(hModule %p, lpProcName %s = %p", + hModule, + lpProcName, + result); + + return result; +} + +void procmon_module_init() +{ + hook_table_apply( + NULL, + "kernel32.dll", + _procmon_module_hook_syms, + lengthof(_procmon_module_hook_syms)); + + log_misc("init"); +} + +void procmon_module_fini() +{ + hook_table_revert( + NULL, + "kernel32.dll", + _procmon_module_hook_syms, + lengthof(_procmon_module_hook_syms)); + + log_misc("fini"); +} \ No newline at end of file diff --git a/src/main/procmon/module.h b/src/main/procmon/module.h new file mode 100644 index 0000000..8cb8912 --- /dev/null +++ b/src/main/procmon/module.h @@ -0,0 +1,7 @@ +#ifndef PROCMON_MODULE_H +#define PROCMON_MODULE_H + +void procmon_module_init(); +void procmon_module_fini(); + +#endif \ No newline at end of file diff --git a/src/main/procmon/procmon.c b/src/main/procmon/procmon.c new file mode 100644 index 0000000..6120ae9 --- /dev/null +++ b/src/main/procmon/procmon.c @@ -0,0 +1,73 @@ +#define LOG_MODULE "procmon" + +#include +#include + +#include "core/log.h" + +#include "procmon/file.h" +#include "procmon/module.h" +#include "procmon/procmon.h" +#include "procmon/thread.h" + +static bool _procmon_file_mon_enabled; +static bool _procmon_module_mon_enabled; +static bool _procmon_thread_mon_enabled; + +uint32_t procmon_api_version() +{ + return 0; +} + +void procmon_set_loggers( + core_log_message_t misc, + core_log_message_t info, + core_log_message_t warning, + core_log_message_t fatal) +{ + core_log_impl_set(misc, info, warning, fatal); +} + +void procmon_init() +{ + _procmon_file_mon_enabled = false; + _procmon_module_mon_enabled = false; + _procmon_thread_mon_enabled = false; + + log_info("init"); +} + +void procmon_file_mon_enable() +{ + procmon_file_init(); + _procmon_file_mon_enabled = true; +} + +void procmon_module_mon_enable() +{ + procmon_module_init(); + _procmon_module_mon_enabled = true; +} + +void procmon_thread_mon_enable() +{ + procmon_thread_init(); + _procmon_thread_mon_enabled = true; +} + +void procmon_fini() +{ + if (_procmon_file_mon_enabled) { + procmon_file_fini(); + } + + if (_procmon_module_mon_enabled) { + procmon_module_fini(); + } + + if (_procmon_thread_mon_enabled) { + procmon_thread_fini(); + } + + log_info("fini"); +} \ No newline at end of file diff --git a/src/main/procmon/procmon.def b/src/main/procmon/procmon.def new file mode 100644 index 0000000..1dfb0d3 --- /dev/null +++ b/src/main/procmon/procmon.def @@ -0,0 +1,10 @@ +LIBRARY procmon + +EXPORTS + procmon_api_version + procmon_set_loggers + procmon_init + procmon_file_mon_enable + procmon_module_mon_enable + procmon_thread_mon_enable + procmon_fini diff --git a/src/main/procmon/procmon.h b/src/main/procmon/procmon.h new file mode 100644 index 0000000..0d485fb --- /dev/null +++ b/src/main/procmon/procmon.h @@ -0,0 +1,21 @@ +#ifndef PROCMON_PROCMON_H +#define PROCMON_PROCMON_H + +#include +#include + +#include "core/log.h" + +uint32_t procmon_api_version(); +void procmon_set_loggers( + core_log_message_t misc, + core_log_message_t info, + core_log_message_t warning, + core_log_message_t fatal); +void procmon_init(); +void procmon_file_mon_enable(); +void procmon_module_mon_enable(); +void procmon_thread_mon_enable(); +void procmon_fini(); + +#endif \ No newline at end of file diff --git a/src/main/procmon/thread.c b/src/main/procmon/thread.c new file mode 100644 index 0000000..790925f --- /dev/null +++ b/src/main/procmon/thread.c @@ -0,0 +1,106 @@ +#define LOG_MODULE "procmon-thread" + +#include + +#include "core/log.h" + +#include "hook/table.h" + +#ifdef _WIN64 +#define SIZE_T_FORMAT_SPECIFIER "llu" +#else +#define SIZE_T_FORMAT_SPECIFIER "lu" +#endif + +static HANDLE(STDCALL *real_CreateThread)( + LPSECURITY_ATTRIBUTES lpThreadAttributes, + SIZE_T dwStackSize, + LPTHREAD_START_ROUTINE lpStartAddress, + LPVOID lpParameter, + DWORD dwCreationFlags, + LPDWORD lpThreadId); + +static HANDLE STDCALL my_CreateThread( + LPSECURITY_ATTRIBUTES lpThreadAttributes, + SIZE_T dwStackSize, + LPTHREAD_START_ROUTINE lpStartAddress, + LPVOID lpParameter, + DWORD dwCreationFlags, + LPDWORD lpThreadId); + +static const struct hook_symbol _procmon_thread_hook_syms[] = { + { + .name = "CreateThread", + .patch = my_CreateThread, + .link = (void **) &real_CreateThread, + }, +}; + +static HANDLE STDCALL my_CreateThread( + LPSECURITY_ATTRIBUTES lpThreadAttributes, + SIZE_T dwStackSize, + LPTHREAD_START_ROUTINE lpStartAddress, + LPVOID lpParameter, + DWORD dwCreationFlags, + LPDWORD lpThreadId) +{ + HANDLE result; + + log_misc( + "CreateThread(lpThreadAttributes %p, dwStackSize " + "%" SIZE_T_FORMAT_SPECIFIER + ", lpStartAddress %p, lpParameter %p, dwCreationFlags %lu, lpThreadId " + "%p)", + lpThreadAttributes, + dwStackSize, + lpStartAddress, + lpParameter, + dwCreationFlags, + lpThreadId); + + result = real_CreateThread( + lpThreadAttributes, + dwStackSize, + lpStartAddress, + lpParameter, + dwCreationFlags, + lpThreadId); + + log_misc( + "CreateThread(lpThreadAttributes %p, dwStackSize " + "%" SIZE_T_FORMAT_SPECIFIER + ", lpStartAddress %p, lpParameter %p, dwCreationFlags %lu, lpThreadId " + "%p) = %p, tid %lu", + lpThreadAttributes, + dwStackSize, + lpStartAddress, + lpParameter, + dwCreationFlags, + lpThreadId, + result, + lpThreadId ? *lpThreadId : -1); + + return result; +} + +void procmon_thread_init() +{ + hook_table_apply( + NULL, + "kernel32.dll", + _procmon_thread_hook_syms, + lengthof(_procmon_thread_hook_syms)); + + log_misc("init"); +} + +void procmon_thread_fini() +{ + hook_table_revert( + NULL, + "kernel32.dll", + _procmon_thread_hook_syms, + lengthof(_procmon_thread_hook_syms)); + + log_misc("fini"); +} \ No newline at end of file diff --git a/src/main/procmon/thread.h b/src/main/procmon/thread.h new file mode 100644 index 0000000..c90e89c --- /dev/null +++ b/src/main/procmon/thread.h @@ -0,0 +1,7 @@ +#ifndef PROCMON_THREAD_H +#define PROCMON_THREAD_H + +void procmon_thread_init(); +void procmon_thread_fini(); + +#endif \ No newline at end of file