From 979bb6c2a19cd4284a066285ad2ac772dc4b8ff1 Mon Sep 17 00:00:00 2001 From: _xeroxz Date: Sun, 7 Mar 2021 19:01:17 -0800 Subject: [PATCH] fixed some JCC issues... added new reloc type.. --- DemoDrv/DemoDrv.vcxproj | 4 ++ DemoDrv/DemoDrv.vcxproj.filters | 3 ++ DemoDrv/DriverEntry.cpp | 30 ++++++++++++- DemoDrv/Theodosius.h | 10 +---- DemoDrv/Types.h | 24 ++++++++++ Theodosius/Zydis/Generated/EnumMnemonic.h | 12 ++--- Theodosius/hmdm_ctx.cpp | 19 ++++++-- Theodosius/main.cpp | 14 +----- Theodosius/obfuscation/obfuscation.cpp | 53 +++++++++++++++-------- Theodosius/obfuscation/obfuscation.hpp | 6 ++- Theodosius/utils.hpp | 7 +++ 11 files changed, 130 insertions(+), 52 deletions(-) create mode 100644 DemoDrv/Types.h diff --git a/DemoDrv/DemoDrv.vcxproj b/DemoDrv/DemoDrv.vcxproj index 65c5abc..a9c8224 100644 --- a/DemoDrv/DemoDrv.vcxproj +++ b/DemoDrv/DemoDrv.vcxproj @@ -50,12 +50,15 @@ DbgengKernelDebugger false + $(IncludePath);$(KMDF_INC_PATH)$(KMDF_VER_PATH) + $(LLVMInstallDir)\bin;$(ExecutablePath); DbgengKernelDebugger false $(SolutionDir)$(Platform)\$(Configuration)\ $(IncludePath);$(KMDF_INC_PATH)$(KMDF_VER_PATH) + $(LLVMInstallDir)\bin;$(ExecutablePath); @@ -99,6 +102,7 @@ + diff --git a/DemoDrv/DemoDrv.vcxproj.filters b/DemoDrv/DemoDrv.vcxproj.filters index ef70a15..453c4b1 100644 --- a/DemoDrv/DemoDrv.vcxproj.filters +++ b/DemoDrv/DemoDrv.vcxproj.filters @@ -18,5 +18,8 @@ Header Files + + Header Files + \ No newline at end of file diff --git a/DemoDrv/DriverEntry.cpp b/DemoDrv/DriverEntry.cpp index 33dc13d..4dea036 100644 --- a/DemoDrv/DriverEntry.cpp +++ b/DemoDrv/DriverEntry.cpp @@ -1,8 +1,36 @@ #include "Theodosius.h" +#include "Types.h" -MutateRoutine extern "C" void drv_entry() +// this routine is not obfuscated... +void PrintCR3() +{ + ULONG_PTR Cr3Value = + *reinterpret_cast( + IoGetCurrentProcess() + CR3_OFFSET); + + DbgPrint("> Current CR3 = 0x%p\n", Cr3Value); +} + +ObfuscateRoutine void LoopDemo() +{ + // JCC's work! :) + for (auto idx = 0u; idx < 10; ++idx) + DbgPrint("> Loop Demo: %d\n", idx); +} + +// entry point must be named "DrvEntry" for this example... +MutateRoutine extern "C" void DrvEntry() { DbgPrint("> Hello World!\n"); + + // non-exported symbols being resolved by jit linker... DbgPrint("> PiDDBCacheTable = 0x%p\n", &PiDDBCacheTable); DbgPrint("> win32kfull!NtUserRegisterShellPTPListener = 0x%p\n", &NtUserRegisterShellPTPListener); + + // example of referencing itself... + DbgPrint("> DrvEntry = 0x%p\n", &DrvEntry); + + // example of calling other obfuscated/non obfuscated routines... + PrintCR3(); + LoopDemo(); } \ No newline at end of file diff --git a/DemoDrv/Theodosius.h b/DemoDrv/Theodosius.h index cb3e70b..a1d30bc 100644 --- a/DemoDrv/Theodosius.h +++ b/DemoDrv/Theodosius.h @@ -1,11 +1,3 @@ #pragma once -#include #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 +#define MutateRoutine __declspec(code_seg(".theo1"), noinline) \ No newline at end of file diff --git a/DemoDrv/Types.h b/DemoDrv/Types.h new file mode 100644 index 0000000..4b7a092 --- /dev/null +++ b/DemoDrv/Types.h @@ -0,0 +1,24 @@ +#pragma once +#define NT_SUCCESS(x) ((x) >= 0) +#define STATUS_INFO_LENGTH_MISMATCH 0xc0000004 +#define CR3_OFFSET 0x28 + +using NTSTATUS = unsigned long; +using PVOID = void*; + +using HANDLE = unsigned long; +using UCHAR = unsigned char; +using USHORT = unsigned short; +using ULONG = unsigned long; +using PULONG = unsigned long*; +typedef unsigned long long ULONG_PTR; + +// this is a demo of resolving non-exported symbols... +// win32kfull.sys export example... +extern "C" void NtUserRegisterShellPTPListener(); +extern "C" void* PiDDBCacheTable; + +extern "C" unsigned char* IoGetCurrentProcess(); +extern "C" unsigned long DbgPrint(const char* format, ...); +extern "C" PVOID ExAllocatePool(ULONG, ULONG); +extern "C" void ExFreePool(PVOID); \ No newline at end of file diff --git a/Theodosius/Zydis/Generated/EnumMnemonic.h b/Theodosius/Zydis/Generated/EnumMnemonic.h index bcb6265..899efb8 100644 --- a/Theodosius/Zydis/Generated/EnumMnemonic.h +++ b/Theodosius/Zydis/Generated/EnumMnemonic.h @@ -1635,9 +1635,9 @@ typedef enum ZydisMnemonic_ /** * Maximum value of this enum. */ - ZYDIS_MNEMONIC_MAX_VALUE = ZYDIS_MNEMONIC_XTEST, - /** - * The minimum number of bits required to represent all values of this enum. - */ - ZYDIS_MNEMONIC_REQUIRED_BITS = ZYAN_BITS_TO_REPRESENT(ZYDIS_MNEMONIC_MAX_VALUE) -} ZydisMnemonic; + ZYDIS_MNEMONIC_MAX_VALUE = ZYDIS_MNEMONIC_XTEST, + /** + * The minimum number of bits required to represent all values of this enum. + */ + ZYDIS_MNEMONIC_REQUIRED_BITS = ZYAN_BITS_TO_REPRESENT(ZYDIS_MNEMONIC_MAX_VALUE) +} ZydisMnemonic; \ No newline at end of file diff --git a/Theodosius/hmdm_ctx.cpp b/Theodosius/hmdm_ctx.cpp index d6deaf9..a4a0494 100644 --- a/Theodosius/hmdm_ctx.cpp +++ b/Theodosius/hmdm_ctx.cpp @@ -47,7 +47,7 @@ namespace theo } std::printf("[+] linking complete...\n"); - return mapped_symbols["drv_entry"]; + return mapped_symbols["DrvEntry"]; } bool hmm_ctx::map_symbols(std::vector& objs) @@ -143,8 +143,8 @@ namespace theo continue; std::printf(" > mapping obfuscated routine %s into memory...\n", symbol.symbol_name.c_str()); + std::int32_t instruc_offset = 0u; - unsigned instruc_offset = 0u; while (true) // TODO: this is bad code... dont do this! { auto symbol_name = symbol.symbol_name; @@ -176,9 +176,16 @@ namespace theo switch (reloc.type) { - case obfuscation::reloc_type::none: - break; + case obfuscation::reloc_type::jcc: + { + const auto next_instruc_symbol = + std::string(symbol.symbol_name).append("@") + .append(std::to_string(instruc_offset + instruc_len + reloc.rva)); + *reinterpret_cast(fix_reloc_addr) = + mapped_symbols[next_instruc_symbol]; + break; + } case obfuscation::reloc_type::next_instruction_addr: { const auto next_instruc_symbol = @@ -190,6 +197,10 @@ namespace theo break; // we resolved our own relocation... } + case obfuscation::reloc_type::none: + { + break; + } default: { // check this instruction to see if it needs any relocs... diff --git a/Theodosius/main.cpp b/Theodosius/main.cpp index 1dac4d6..8086cda 100644 --- a/Theodosius/main.cpp +++ b/Theodosius/main.cpp @@ -180,18 +180,8 @@ int main(int argc, char** argv) 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; } + // false if we found the symbol... + return (!(result = utils::kmodule::get_export(drv_name, symbol_name))); } ); } diff --git a/Theodosius/obfuscation/obfuscation.cpp b/Theodosius/obfuscation/obfuscation.cpp index ceb2162..0437ae5 100644 --- a/Theodosius/obfuscation/obfuscation.cpp +++ b/Theodosius/obfuscation/obfuscation.cpp @@ -7,8 +7,11 @@ namespace obfuscation : instruction(info) { - switch (instruction.first.mnemonic) + // idk what i did to zydis but + 1 fixed it? + // this is brutal... TODO: figure out tf is going on here... + switch (instruction.first.mnemonic + 1) { + case ZYDIS_MNEMONIC_JLE: case ZYDIS_MNEMONIC_JB: case ZYDIS_MNEMONIC_JBE: case ZYDIS_MNEMONIC_JCXZ: @@ -16,7 +19,6 @@ namespace obfuscation case ZYDIS_MNEMONIC_JKNZD: case ZYDIS_MNEMONIC_JKZD: case ZYDIS_MNEMONIC_JL: - case ZYDIS_MNEMONIC_JLE: case ZYDIS_MNEMONIC_JNB: case ZYDIS_MNEMONIC_JNBE: case ZYDIS_MNEMONIC_JNL: @@ -31,38 +33,53 @@ namespace obfuscation case ZYDIS_MNEMONIC_JS: case ZYDIS_MNEMONIC_JZ: { + const auto rva_fix_offset = instruction.first.length - + (instruction.first.operands[0].size / 8); + + const auto rva_fix_addr = + instruction.second.data() + rva_fix_offset; + reloc_t inline_jmp_reloc { - JMP_RIP_ADDR_IDX, - reloc_type::next_instruction_addr + reloc_type::next_instruction_addr, + JMP_RIP_ADDR_IDX }; - const auto rva_fix_offset = instruction.first.length - - (instruction.first.operands[0].size / 8); - - const auto rva_fix_addr = - instruction.second.data() + rva_fix_offset; + reloc_t inline_jmp_branch + { + reloc_type::jcc, + JMP_RIP_ADDR_IDX, + *reinterpret_cast(rva_fix_addr) + }; std::printf(" > fixing JCC rva...\n"); std::printf(" > new rva = 0x%x\n", JMP_RIP_SIZE); std::printf(" > old rva = 0x%x\n", - *reinterpret_cast(rva_fix_addr)); + *reinterpret_cast(rva_fix_addr)); // when you inherit obfuscate please be mindful of JCC rvas... - *reinterpret_cast(rva_fix_addr) = JMP_RIP_SIZE; + *reinterpret_cast(rva_fix_addr) = JMP_RIP_SIZE; gadget_stack.push_back({ instruction.second, {} }); gadget_stack.push_back({ jmp_rip, inline_jmp_reloc }); - gadget_stack.push_back({ jmp_rip, inline_jmp_reloc }); + gadget_stack.push_back({ jmp_rip, inline_jmp_branch }); break; } case ZYDIS_MNEMONIC_JMP: { + const auto rva_fix_offset = instruction.first.length - + (instruction.first.operands[0].size / 8); + + const auto rva_fix_addr = + instruction.second.data() + rva_fix_offset; + reloc_t inline_jmp_reloc - { - JMP_RIP_ADDR_IDX, - reloc_type::next_instruction_addr + { + reloc_type::jcc, + JMP_RIP_ADDR_IDX, + *reinterpret_cast(rva_fix_addr) }; + gadget_stack.push_back({ jmp_rip, inline_jmp_reloc }); break; } @@ -75,8 +92,8 @@ namespace obfuscation { reloc_t inline_jmp_reloc { - JMP_RIP_ADDR_IDX, - reloc_type::next_instruction_addr + reloc_type::next_instruction_addr, + JMP_RIP_ADDR_IDX }; gadget_stack.push_back({ instruction.second, {} }); @@ -157,6 +174,6 @@ namespace obfuscation // instruction gets executed... gadget_stack.insert( gadget_stack.begin(), - { std::move(stack_palindrome), {NULL, reloc_type::none} }); + { std::move(stack_palindrome), {reloc_type::none, NULL, NULL } }); } } \ No newline at end of file diff --git a/Theodosius/obfuscation/obfuscation.hpp b/Theodosius/obfuscation/obfuscation.hpp index 6946cf3..3708bc8 100644 --- a/Theodosius/obfuscation/obfuscation.hpp +++ b/Theodosius/obfuscation/obfuscation.hpp @@ -22,13 +22,15 @@ namespace obfuscation enum class reloc_type { none = -1, - next_instruction_addr = 1 + jcc = 1, + next_instruction_addr = 2 }; struct reloc_t { - std::uint32_t offset; reloc_type type; + std::uint32_t offset; + std::int32_t rva; }; using instruction_info_t = std::pair>; diff --git a/Theodosius/utils.hpp b/Theodosius/utils.hpp index f7dbcfc..a2da7be 100644 --- a/Theodosius/utils.hpp +++ b/Theodosius/utils.hpp @@ -284,6 +284,13 @@ namespace utils DONT_RESOLVE_DLL_REFERENCES ); + if (!module_base) + { + // free the RTL_PROCESS_MODULES buffer... + VirtualFree(buffer, NULL, MEM_RELEASE); + return NULL; + } + const auto image_base = reinterpret_cast( modules->Modules[idx].ImageBase);