From 041460c89da2a56363b44eced87e7bbfd18325f4 Mon Sep 17 00:00:00 2001 From: _xeroxz Date: Mon, 8 Mar 2021 08:30:34 +0000 Subject: [PATCH] Update README.md --- README.md | 84 +++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 81 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index e1db379..d373345 100644 --- a/README.md +++ b/README.md @@ -137,7 +137,7 @@ The linker is able to get the address of the branching code by taking the rip re Theodosius uses the same class structure as HMDM does. Its a highly modular format which allows for extreme usage, supporting almost every idea one might have. In order to use Theo, you must first define three lambdas, `theo::memcpy_t` a method of copying memory, `theo::malloc_t` a method to allocate executable memory, and lastely `theo::resolve_symbol_t` a lamdba to resolve external symbols. -### theo::memcpy_t - copy memory lambda +### `theo::memcpy_t` - copy memory lambda This is used to write memory, it is never used to read memory. An example of this lambda using VDM could be: @@ -170,7 +170,7 @@ theo::memcpy_t _memcpy = }; ``` -### theo::malloc_t - allocate executable memory +### `theo::malloc_t` - allocate executable memory This lambda is used to allocate executable memory. Any method will do as long as the memcpy lambda can write to the allocated memory. An MSREXEC example for this lambda is defined below. @@ -216,7 +216,85 @@ theo::malloc_t _alloc = [&](std::size_t size) -> void* }; ``` -### `theo::resolve_symbol_t` - +### `theo::resolve_symbol_t` - resolve external symbol + +This lambda will try and resolve external symbols. Symbols which are not defined inside of any object files. For example `PiddbCacheTable`, an unexported ntoskrnl symbol, which normally people sig scan for, can now be jit linked. This is possible by parsing a MAP file, however you can recode this to support PDB's, etc. Again its completely opened ended on how you want to resolve symbols. + +```cpp +theo::resolve_symbol_t resolve_symbol = +[&, &extern_symbols = extern_symbols](const char* symbol_name) -> std::uintptr_t +{ + std::uintptr_t result = 0u; + for (auto& [drv_name, drv_symbols] : extern_symbols) + { + // each kernel module... find a driver with a matching map file name... + // I.E ntoskrnl.exe.map == ntoskrnl.exe... + utils::kmodule::each_module + ( + [&, &drv_name = drv_name, &drv_symbols = drv_symbols] + (PRTL_PROCESS_MODULE_INFORMATION drv_info, const char* drv_path) -> bool + { + const auto _drv_name = + reinterpret_cast( + drv_info->OffsetToFileName + drv_info->FullPathName); + + // if this is the driver, load it, loop over its sections + // calc the absolute virtual address of the symbol... + if (!strcmp(_drv_name, drv_name.c_str())) + { + const auto drv_load_addr = + reinterpret_cast( + LoadLibraryExA(drv_path, NULL, DONT_RESOLVE_DLL_REFERENCES)); + + std::uint32_t section_count = 1u; + utils::pe::each_section + ( + [&, &drv_symbols = drv_symbols] + (PIMAGE_SECTION_HEADER section_header, std::uintptr_t img_base) -> bool + { + if (section_count == drv_symbols[symbol_name].first) + { + result = reinterpret_cast(drv_info->ImageBase) + + section_header->VirtualAddress + drv_symbols[symbol_name].second; + + // we found the symbol... + return false; + } + + ++section_count; + // keep going over sections... + return true; + }, drv_load_addr + ); + } + + // keep looping over modules until we resolve the symbol... + return !result; + } + ); + } + + // if the symbol was not resolved in any of the map files then try + // to see if its an export from any other drivers... + if (!result) + { + utils::kmodule::each_module + ( + [&](PRTL_PROCESS_MODULE_INFORMATION drv_info, const char* drv_path) -> bool + { + const auto drv_name = + reinterpret_cast( + drv_info->OffsetToFileName + drv_info->FullPathName); + + // false if we found the symbol... + return (!(result = utils::kmodule::get_export(drv_name, symbol_name))); + } + ); + } + + return result; +}; +``` # Obfuscation