From 6099c231382327d1eb5168fc2faa2f9d918e4dcb Mon Sep 17 00:00:00 2001 From: _xeroxz Date: Sun, 7 Mar 2021 15:09:58 -0800 Subject: [PATCH] finished external symbol resolver demo... --- DemoDrv/DriverEntry.cpp | 4 +- DemoDrv/Theodosius.h | 4 + Theodosius/Theodosius.vcxproj.user | 4 +- Theodosius/hmdm_ctx.h | 10 +- Theodosius/linker/linker.cpp | 33 +++++++ Theodosius/linker/linker.hpp | 4 + Theodosius/main.cpp | 144 ++++++++++++++++++++++++++--- 7 files changed, 182 insertions(+), 21 deletions(-) diff --git a/DemoDrv/DriverEntry.cpp b/DemoDrv/DriverEntry.cpp index c6048e1..33dc13d 100644 --- a/DemoDrv/DriverEntry.cpp +++ b/DemoDrv/DriverEntry.cpp @@ -1,6 +1,8 @@ #include "Theodosius.h" -ObfuscateRoutine extern "C" void drv_entry() +MutateRoutine extern "C" void drv_entry() { DbgPrint("> Hello World!\n"); + DbgPrint("> PiDDBCacheTable = 0x%p\n", &PiDDBCacheTable); + DbgPrint("> win32kfull!NtUserRegisterShellPTPListener = 0x%p\n", &NtUserRegisterShellPTPListener); } \ No newline at end of file diff --git a/DemoDrv/Theodosius.h b/DemoDrv/Theodosius.h index 970f7ab..cb3e70b 100644 --- a/DemoDrv/Theodosius.h +++ b/DemoDrv/Theodosius.h @@ -3,5 +3,9 @@ #define ObfuscateRoutine __declspec(code_seg(".theo"), noinline) #define MutateRoutine __declspec(code_seg(".theo1"), noinline) +// win32kfull.sys export example... +extern "C" void NtUserRegisterShellPTPListener(); +extern "C" void* PiDDBCacheTable; + extern "C" unsigned long DbgPrint(const char* format, ...); extern "C" unsigned long long IoGetCurrentProcess(); \ No newline at end of file diff --git a/Theodosius/Theodosius.vcxproj.user b/Theodosius/Theodosius.vcxproj.user index cfba79c..b3192f3 100644 --- a/Theodosius/Theodosius.vcxproj.user +++ b/Theodosius/Theodosius.vcxproj.user @@ -1,11 +1,11 @@  - C:\Users\_xeroxz\Desktop\drv\DemoDrv.lib + --libs C:\Users\_xeroxz\Desktop\drv\DemoDrv.lib --maps C:\Users\_xeroxz\Desktop\ntoskrnl.exe.map WindowsLocalDebugger - C:\Users\_xeroxz\Desktop\drv\DemoDrv.lib + --libs C:\Users\_xeroxz\Desktop\drv\DemoDrv.lib --maps C:\Users\_xeroxz\Desktop\ntoskrnl.exe.map WindowsLocalDebugger \ No newline at end of file diff --git a/Theodosius/hmdm_ctx.h b/Theodosius/hmdm_ctx.h index 9c62677..11568d7 100644 --- a/Theodosius/hmdm_ctx.h +++ b/Theodosius/hmdm_ctx.h @@ -16,13 +16,13 @@ #pragma comment(lib, "Dbghelp.lib") namespace theo { - using kalloc_t = std::function; - using kmemcpy_t = std::function; + using malloc_t = std::function; + using memcpy_t = std::function; using kmemset_t = std::function; using resolve_symbol_t = std::function; using image_entry_t = std::uintptr_t; - using mapper_routines_t = std::tuple; + using mapper_routines_t = std::tuple; class hmm_ctx { @@ -30,8 +30,8 @@ namespace theo explicit hmm_ctx(const mapper_routines_t& routines); auto map_objs(std::vector& objs) -> image_entry_t; - kalloc_t kalloc; - kmemcpy_t kmemcpy; + malloc_t kalloc; + memcpy_t kmemcpy; resolve_symbol_t resolve_symbol; private: bool map_symbols(std::vector& objs); diff --git a/Theodosius/linker/linker.cpp b/Theodosius/linker/linker.cpp index 48a8128..384edf1 100644 --- a/Theodosius/linker/linker.cpp +++ b/Theodosius/linker/linker.cpp @@ -28,6 +28,39 @@ namespace lnk return result - sym.section_offset; } + auto get_map_symbols(std::string map_path) -> map_symbols_t + { + std::ifstream map_file(map_path); + + if (!map_file.is_open()) + return { {}, {} }; + + std::string line; + map_symbols_t result; + while (std::getline(map_file, line)) + { + const auto colon_index = line.find(":"); + if (colon_index == std::string::npos) + break; + + const auto section_number = + std::strtoul(line.substr(1, + colon_index).c_str(), NULL, 16); + + const auto section_offset = + std::strtoull(line.substr( + colon_index + 1, 16).c_str(), NULL, 16); + + auto symbol = line.substr( + colon_index + 16 + 8, + line.length() - (colon_index + 16 + 7)); + + symbol[symbol.length()] = '\0'; + result[symbol] = { section_number, section_offset }; + } + return result; + } + auto get_objs(std::string lib_path, std::vector& objs) -> bool { std::vector lib_file; diff --git a/Theodosius/linker/linker.hpp b/Theodosius/linker/linker.hpp index a52c67c..90a0948 100644 --- a/Theodosius/linker/linker.hpp +++ b/Theodosius/linker/linker.hpp @@ -3,6 +3,7 @@ #include #include #include +#include #include "../utils.hpp" namespace lnk @@ -54,8 +55,11 @@ namespace lnk }; using obj_buffer_t = std::vector; + using map_symbols_t = std::map>; + auto get_symbol_size(symbol_t& sym, obj_buffer_t& obj) -> std::uint32_t; auto get_objs(std::string lib_path, std::vector& objs) -> bool; + auto get_map_symbols(std::string map_path) -> map_symbols_t; namespace sym { diff --git a/Theodosius/main.cpp b/Theodosius/main.cpp index 39987ea..1dac4d6 100644 --- a/Theodosius/main.cpp +++ b/Theodosius/main.cpp @@ -5,25 +5,65 @@ #include "hmdm_ctx.h" #include "linker/linker.hpp" +using extern_symbols_t = std::vector>; +using objs_buffer_t = std::vector; + +auto get_mapping_info(int argc, char** argv) -> std::pair +{ + auto maps_offset = 0u; + std::vector image_objs; + std::vector> extern_symbols; + + for (auto idx = 2; idx < argc; ++idx) + { + if (!strcmp(argv[idx], "--maps")) + { + maps_offset = idx + 1; + break; + } + + if (!lnk::get_objs(argv[idx], image_objs)) + { + std::printf("> failed to parse lib...\n"); + return {}; + } + } + + if (maps_offset) + { + for (auto idx = maps_offset; idx <= argc - 1; ++idx) + { + extern_symbols.push_back + ({ + std::filesystem::path(argv[idx]).stem().string(), + lnk::get_map_symbols(argv[idx]) + }); + } + } + + return { image_objs, extern_symbols }; +} + int main(int argc, char** argv) { - if (argc < 2) + if (argc < 3 || strcmp(argv[1], "--libs")) { - std::printf("> please provide a folder of objs to be linked...\n"); + std::printf("[!] invalid usage... please use one of the following:\n"); + std::printf(" > theo.exe --libs one.lib two.lib three.lib\n"); + std::printf(" > theo.exe --libs one.lib --maps ntoskrnl.exe.map win32kbase.sys.map\n"); return -1; } - // read each .obj file from directory into std::vector... - std::vector image_objs; - if (!lnk::get_objs(argv[1], image_objs)) + auto [image_objs, extern_symbols] = get_mapping_info(argc, argv); + std::printf("[+] number of objs = %d\n", image_objs.size()); + + if (!image_objs.size()) { - std::printf("> failed to parse lib...\n"); + std::printf("[!] failed to parse .lib...\n"); return -1; } - std::printf("> number of objs = %d\n", image_objs.size()); const auto [drv_handle, drv_key, drv_status] = vdm::load_drv(); - if (drv_status != STATUS_SUCCESS || drv_handle == INVALID_HANDLE_VALUE) { std::printf("> failed to load driver... reason -> 0x%x\n", drv_status); @@ -37,7 +77,7 @@ int main(int argc, char** argv) }; vdm::msrexec_ctx msrexec(_write_msr); - theo::kalloc_t _kalloc = [&](std::size_t size) -> void* + theo::malloc_t _kalloc = [&](std::size_t size) -> void* { void* alloc_base; msrexec.exec @@ -57,7 +97,7 @@ int main(int argc, char** argv) return alloc_base; }; - theo::kmemcpy_t _kmemcpy = + theo::memcpy_t _kmemcpy = [&](void* dest, const void* src, std::size_t size) -> void* { void* result = nullptr; @@ -74,11 +114,89 @@ int main(int argc, char** argv) ); return result; }; - + theo::resolve_symbol_t resolve_symbol = - [&](const char* symbol_name) -> std::uintptr_t + [&, &extern_symbols = extern_symbols](const char* symbol_name) -> std::uintptr_t { - return utils::kmodule::get_export("ntoskrnl.exe", symbol_name); + 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); + + __try + { + const auto temp_result = + utils::kmodule::get_export(drv_name, symbol_name); + + if (!temp_result) + return true; + + // false if we found the symbol... + return (!(result = temp_result)); + } + __except (EXCEPTION_EXECUTE_HANDLER) { return true; } + } + ); + } + + return result; }; theo::hmm_ctx drv_mapper({ _kalloc, _kmemcpy, resolve_symbol });