From 2a540406e4b3586c85be9348cc4c29dbe8720897 Mon Sep 17 00:00:00 2001 From: Dillon Franke Date: Wed, 11 Dec 2024 15:06:34 -0800 Subject: [PATCH 1/3] Implement -ignore_duplicates_module --- README.md | 2 ++ hook.md | 2 +- tinyinst.cpp | 24 ++++++++++++++++++++---- tinyinst.h | 1 + 4 files changed, 24 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index ece5e89..d6f1c70 100755 --- a/README.md +++ b/README.md @@ -186,6 +186,8 @@ In addition to the general-purpose API documented above, TinyInst also implement `-indirect_instrumentation [none|local|global|auto]` which instrumentation to use for indirect jump/calls +`-ignore_duplicates_module [module name]` Ensures only the first loaded instance of `[module name]` is instrumented, ignoring subsequent duplicates. Useful when instrumenting system libraries (e.g., `CoreAudio`) on macOS Sequoia and later, where multiple distinct libraries with the same name may be loaded. + `-patch_return_addresses` - replaces return address with the original value, causes returns to be instrumented using whatever `-indirect_instrumentation` method is specified `-generate_unwind` - Generates stack unwinding data for instrumented code (for faster C++ exception handling). Note that it might not work correctly on some older Windows versions. diff --git a/hook.md b/hook.md index c0e9c82..7928037 100644 --- a/hook.md +++ b/hook.md @@ -23,7 +23,7 @@ It is expected that most hooking operations can be performed just using the brea If a hook needs to add additional assembly code, this can be done by implementing `WriteCodeBefore`/`WriteCodeAfter` methods of the hook class. Assembly code can be inserted by calling the `WriteCode` function with the buffer containing the assembly to be inserted. Note that both `WriteCodeBefore`/`WriteCodeAfter` get called during instrumentation time (before the function gets run) and, due to how `HookBeginEnd` is implemented, `WriteCodeAfter` can be called multiple times for a single hooked function. -Once the hook classes have been implemented for each function the user wants to hook, the user can register them by calling `RegisterHook` method inside their clien's constructor. +Once the hook classes have been implemented for each function the user wants to hook, the user can register them by calling `RegisterHook` method inside their client's constructor. ### Example diff --git a/tinyinst.cpp b/tinyinst.cpp index 99b59d7..d972947 100644 --- a/tinyinst.cpp +++ b/tinyinst.cpp @@ -43,6 +43,7 @@ ModuleInfo::ModuleInfo() { max_address = 0; loaded = false; instrumented = false; + ignore_duplicates = false; instrumented_code_local = NULL; instrumented_code_remote = NULL; instrumented_code_remote_previous = NULL; @@ -849,6 +850,8 @@ void TinyInst::OnModuleInstrumented(ModuleInfo* module) { } if(address) { resolved_hooks[address] = hook; + } else { + FATAL("Could not resolve function %s in module %s", hook->GetFunctionName().c_str(), hook->GetModuleName().c_str()); } } } @@ -1071,9 +1074,14 @@ void TinyInst::OnInstrumentModuleLoaded(void *module, ModuleInfo *target_module) target_module->module_header && (target_module->module_header != (void *)module)) { - WARN("Instrumented module loaded on a different address than seen previously\n" - "Module will need to be re-instrumented. Expect a drop in performance."); - ClearInstrumentation(target_module); + if (target_module->ignore_duplicates) { + WARN("Skipping duplicate module %s.", target_module->module_name.c_str()); + return; + } else { + WARN("Instrumented module loaded on a different address than seen previously\n" + "Module will need to be re-instrumented. Expect a drop in performance."); + ClearInstrumentation(target_module); + } } target_module->module_header = (void *)module; @@ -1091,7 +1099,7 @@ void TinyInst::OnInstrumentModuleLoaded(void *module, ModuleInfo *target_module) } } -// called when a potentialy interesting module gets loaded +// called when a potentially interesting module gets loaded void TinyInst::OnModuleLoaded(void *module, char *module_name) { Debugger::OnModuleLoaded(module, module_name); @@ -1261,6 +1269,9 @@ void TinyInst::Init(int argc, char **argv) { std::list module_names; GetOptionAll("-instrument_module", argc, argv, &module_names); + std::list ignored_duplicate_modules; + GetOptionAll("-ignore_duplicates_module", argc, argv, &ignored_duplicate_modules); + #if defined(__APPLE__) && defined(ARM64) std::set orig_uniq_mod_names; std::set new_uniq_mod_names; @@ -1300,6 +1311,11 @@ void TinyInst::Init(int argc, char **argv) { for (const auto module_name: module_names) { ModuleInfo *new_module = new ModuleInfo(); new_module->module_name = module_name; + for (const auto& ignored_module : ignored_duplicate_modules) { + if (strcmp(ignored_module, module_name) == 0) { + new_module->ignore_duplicates = true; + } + } instrumented_modules.push_back(new_module); // SAY("--- %s\n", module_name); } diff --git a/tinyinst.h b/tinyinst.h index ee1a8c4..5da073b 100644 --- a/tinyinst.h +++ b/tinyinst.h @@ -292,6 +292,7 @@ class ModuleInfo { size_t code_size; bool loaded; bool instrumented; + bool ignore_duplicates; std::list executable_ranges; size_t instrumented_code_size; From 39bad5994e9bfd7ccee1b252b45a2bc044301f88 Mon Sep 17 00:00:00 2001 From: Dillon Franke Date: Fri, 13 Dec 2024 15:13:54 -0800 Subject: [PATCH 2/3] Made skipping re-instrumentation of duplicate modules default behavior --- README.md | 2 -- tinyinst.cpp | 21 +++------------------ tinyinst.h | 1 - 3 files changed, 3 insertions(+), 21 deletions(-) diff --git a/README.md b/README.md index 498135f..478df8f 100755 --- a/README.md +++ b/README.md @@ -188,8 +188,6 @@ In addition to the general-purpose API documented above, TinyInst also implement `-indirect_instrumentation [none|local|global|auto]` which instrumentation to use for indirect jump/calls -`-ignore_duplicates_module [module name]` Ensures only the first loaded instance of `[module name]` is instrumented, ignoring subsequent duplicates. Useful when instrumenting system libraries (e.g., `CoreAudio`) on macOS Sequoia and later, where multiple distinct libraries with the same name may be loaded. - `-patch_return_addresses` - replaces return address with the original value, causes returns to be instrumented using whatever `-indirect_instrumentation` method is specified `-generate_unwind` - Generates stack unwinding data for instrumented code (for faster C++ exception handling). Note that it might not work correctly on some older Windows versions. diff --git a/tinyinst.cpp b/tinyinst.cpp index 654f4e6..c08089e 100644 --- a/tinyinst.cpp +++ b/tinyinst.cpp @@ -43,7 +43,6 @@ ModuleInfo::ModuleInfo() { max_address = 0; loaded = false; instrumented = false; - ignore_duplicates = false; instrumented_code_local = NULL; instrumented_code_remote = NULL; instrumented_code_remote_previous = NULL; @@ -852,7 +851,7 @@ void TinyInst::OnModuleInstrumented(ModuleInfo* module) { if(address) { resolved_hooks[address] = hook; } else { - FATAL("Could not resolve function %s in module %s", hook->GetFunctionName().c_str(), hook->GetModuleName().c_str()); + WARN("Could not resolve function %s in module %s", hook->GetFunctionName().c_str(), hook->GetModuleName().c_str()); } } } @@ -1078,14 +1077,8 @@ void TinyInst::OnInstrumentModuleLoaded(void *module, ModuleInfo *target_module) target_module->module_header && (target_module->module_header != (void *)module)) { - if (target_module->ignore_duplicates) { - WARN("Skipping duplicate module %s.", target_module->module_name.c_str()); - return; - } else { - WARN("Instrumented module loaded on a different address than seen previously\n" - "Module will need to be re-instrumented. Expect a drop in performance."); - ClearInstrumentation(target_module); - } + WARN("Skipping re-instrumentation of duplicate module %s.", target_module->module_name.c_str()); + return; } target_module->module_header = (void *)module; @@ -1285,9 +1278,6 @@ void TinyInst::Init(int argc, char **argv) { std::list module_names; GetOptionAll("-instrument_module", argc, argv, &module_names); - std::list ignored_duplicate_modules; - GetOptionAll("-ignore_duplicates_module", argc, argv, &ignored_duplicate_modules); - #if defined(__APPLE__) && defined(ARM64) std::set orig_uniq_mod_names; std::set new_uniq_mod_names; @@ -1327,11 +1317,6 @@ void TinyInst::Init(int argc, char **argv) { for (const auto module_name: module_names) { ModuleInfo *new_module = new ModuleInfo(); new_module->module_name = module_name; - for (const auto& ignored_module : ignored_duplicate_modules) { - if (strcmp(ignored_module, module_name) == 0) { - new_module->ignore_duplicates = true; - } - } AddInstrumentedModule(module_name, true); // SAY("--- %s\n", module_name); } diff --git a/tinyinst.h b/tinyinst.h index 616f6e8..22dfff6 100644 --- a/tinyinst.h +++ b/tinyinst.h @@ -293,7 +293,6 @@ class ModuleInfo { size_t code_size; bool loaded; bool instrumented; - bool ignore_duplicates; std::list executable_ranges; size_t instrumented_code_size; From 4ffa8c06e30f497c87fb621f0dd542757a8c7e60 Mon Sep 17 00:00:00 2001 From: Dillon Franke Date: Fri, 13 Dec 2024 15:19:11 -0800 Subject: [PATCH 3/3] removed duplicate module name addition --- tinyinst.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/tinyinst.cpp b/tinyinst.cpp index c08089e..ad7c760 100644 --- a/tinyinst.cpp +++ b/tinyinst.cpp @@ -1315,8 +1315,6 @@ void TinyInst::Init(int argc, char **argv) { #endif for (const auto module_name: module_names) { - ModuleInfo *new_module = new ModuleInfo(); - new_module->module_name = module_name; AddInstrumentedModule(module_name, true); // SAY("--- %s\n", module_name); }