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);