fixed some JCC issues... added new reloc type..

2.0
_xeroxz 4 years ago
parent 32c2b17fcf
commit 979bb6c2a1

@ -50,12 +50,15 @@
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<DebuggerFlavor>DbgengKernelDebugger</DebuggerFlavor> <DebuggerFlavor>DbgengKernelDebugger</DebuggerFlavor>
<EnableInf2cat>false</EnableInf2cat> <EnableInf2cat>false</EnableInf2cat>
<IncludePath>$(IncludePath);$(KMDF_INC_PATH)$(KMDF_VER_PATH)</IncludePath>
<ExecutablePath>$(LLVMInstallDir)\bin;$(ExecutablePath);</ExecutablePath>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<DebuggerFlavor>DbgengKernelDebugger</DebuggerFlavor> <DebuggerFlavor>DbgengKernelDebugger</DebuggerFlavor>
<EnableInf2cat>false</EnableInf2cat> <EnableInf2cat>false</EnableInf2cat>
<IntDir>$(SolutionDir)$(Platform)\$(Configuration)\</IntDir> <IntDir>$(SolutionDir)$(Platform)\$(Configuration)\</IntDir>
<IncludePath>$(IncludePath);$(KMDF_INC_PATH)$(KMDF_VER_PATH)</IncludePath> <IncludePath>$(IncludePath);$(KMDF_INC_PATH)$(KMDF_VER_PATH)</IncludePath>
<ExecutablePath>$(LLVMInstallDir)\bin;$(ExecutablePath);</ExecutablePath>
</PropertyGroup> </PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile> <ClCompile>
@ -99,6 +102,7 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClInclude Include="Theodosius.h" /> <ClInclude Include="Theodosius.h" />
<ClInclude Include="Types.h" />
</ItemGroup> </ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets"> <ImportGroup Label="ExtensionTargets">

@ -18,5 +18,8 @@
<ClInclude Include="Theodosius.h"> <ClInclude Include="Theodosius.h">
<Filter>Header Files</Filter> <Filter>Header Files</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="Types.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup> </ItemGroup>
</Project> </Project>

@ -1,8 +1,36 @@
#include "Theodosius.h" #include "Theodosius.h"
#include "Types.h"
MutateRoutine extern "C" void drv_entry() // this routine is not obfuscated...
void PrintCR3()
{
ULONG_PTR Cr3Value =
*reinterpret_cast<ULONG_PTR*>(
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"); DbgPrint("> Hello World!\n");
// non-exported symbols being resolved by jit linker...
DbgPrint("> PiDDBCacheTable = 0x%p\n", &PiDDBCacheTable); DbgPrint("> PiDDBCacheTable = 0x%p\n", &PiDDBCacheTable);
DbgPrint("> win32kfull!NtUserRegisterShellPTPListener = 0x%p\n", &NtUserRegisterShellPTPListener); 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();
} }

@ -1,11 +1,3 @@
#pragma once #pragma once
#include <intrin.h>
#define ObfuscateRoutine __declspec(code_seg(".theo"), noinline) #define ObfuscateRoutine __declspec(code_seg(".theo"), noinline)
#define MutateRoutine __declspec(code_seg(".theo1"), 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();

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

@ -1635,9 +1635,9 @@ typedef enum ZydisMnemonic_
/** /**
* Maximum value of this enum. * Maximum value of this enum.
*/ */
ZYDIS_MNEMONIC_MAX_VALUE = ZYDIS_MNEMONIC_XTEST, ZYDIS_MNEMONIC_MAX_VALUE = ZYDIS_MNEMONIC_XTEST,
/** /**
* The minimum number of bits required to represent all values of this enum. * 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) ZYDIS_MNEMONIC_REQUIRED_BITS = ZYAN_BITS_TO_REPRESENT(ZYDIS_MNEMONIC_MAX_VALUE)
} ZydisMnemonic; } ZydisMnemonic;

@ -47,7 +47,7 @@ namespace theo
} }
std::printf("[+] linking complete...\n"); std::printf("[+] linking complete...\n");
return mapped_symbols["drv_entry"]; return mapped_symbols["DrvEntry"];
} }
bool hmm_ctx::map_symbols(std::vector<lnk::obj_buffer_t>& objs) bool hmm_ctx::map_symbols(std::vector<lnk::obj_buffer_t>& objs)
@ -143,8 +143,8 @@ namespace theo
continue; continue;
std::printf(" > mapping obfuscated routine %s into memory...\n", symbol.symbol_name.c_str()); 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! while (true) // TODO: this is bad code... dont do this!
{ {
auto symbol_name = symbol.symbol_name; auto symbol_name = symbol.symbol_name;
@ -176,9 +176,16 @@ namespace theo
switch (reloc.type) switch (reloc.type)
{ {
case obfuscation::reloc_type::none: case obfuscation::reloc_type::jcc:
break; {
const auto next_instruc_symbol =
std::string(symbol.symbol_name).append("@")
.append(std::to_string(instruc_offset + instruc_len + reloc.rva));
*reinterpret_cast<std::uintptr_t*>(fix_reloc_addr) =
mapped_symbols[next_instruc_symbol];
break;
}
case obfuscation::reloc_type::next_instruction_addr: case obfuscation::reloc_type::next_instruction_addr:
{ {
const auto next_instruc_symbol = const auto next_instruc_symbol =
@ -190,6 +197,10 @@ namespace theo
break; // we resolved our own relocation... break; // we resolved our own relocation...
} }
case obfuscation::reloc_type::none:
{
break;
}
default: default:
{ {
// check this instruction to see if it needs any relocs... // check this instruction to see if it needs any relocs...

@ -180,18 +180,8 @@ int main(int argc, char** argv)
reinterpret_cast<const char*>( reinterpret_cast<const char*>(
drv_info->OffsetToFileName + drv_info->FullPathName); drv_info->OffsetToFileName + drv_info->FullPathName);
__try // false if we found the symbol...
{ return (!(result = utils::kmodule::get_export(drv_name, symbol_name)));
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; }
} }
); );
} }

@ -7,8 +7,11 @@ namespace obfuscation
: :
instruction(info) 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_JB:
case ZYDIS_MNEMONIC_JBE: case ZYDIS_MNEMONIC_JBE:
case ZYDIS_MNEMONIC_JCXZ: case ZYDIS_MNEMONIC_JCXZ:
@ -16,7 +19,6 @@ namespace obfuscation
case ZYDIS_MNEMONIC_JKNZD: case ZYDIS_MNEMONIC_JKNZD:
case ZYDIS_MNEMONIC_JKZD: case ZYDIS_MNEMONIC_JKZD:
case ZYDIS_MNEMONIC_JL: case ZYDIS_MNEMONIC_JL:
case ZYDIS_MNEMONIC_JLE:
case ZYDIS_MNEMONIC_JNB: case ZYDIS_MNEMONIC_JNB:
case ZYDIS_MNEMONIC_JNBE: case ZYDIS_MNEMONIC_JNBE:
case ZYDIS_MNEMONIC_JNL: case ZYDIS_MNEMONIC_JNL:
@ -31,38 +33,53 @@ namespace obfuscation
case ZYDIS_MNEMONIC_JS: case ZYDIS_MNEMONIC_JS:
case ZYDIS_MNEMONIC_JZ: case ZYDIS_MNEMONIC_JZ:
{ {
reloc_t inline_jmp_reloc
{
JMP_RIP_ADDR_IDX,
reloc_type::next_instruction_addr
};
const auto rva_fix_offset = instruction.first.length - const auto rva_fix_offset = instruction.first.length -
(instruction.first.operands[0].size / 8); (instruction.first.operands[0].size / 8);
const auto rva_fix_addr = const auto rva_fix_addr =
instruction.second.data() + rva_fix_offset; instruction.second.data() + rva_fix_offset;
reloc_t inline_jmp_reloc
{
reloc_type::next_instruction_addr,
JMP_RIP_ADDR_IDX
};
reloc_t inline_jmp_branch
{
reloc_type::jcc,
JMP_RIP_ADDR_IDX,
*reinterpret_cast<std::int32_t*>(rva_fix_addr)
};
std::printf(" > fixing JCC rva...\n"); std::printf(" > fixing JCC rva...\n");
std::printf(" > new rva = 0x%x\n", JMP_RIP_SIZE); std::printf(" > new rva = 0x%x\n", JMP_RIP_SIZE);
std::printf(" > old rva = 0x%x\n", std::printf(" > old rva = 0x%x\n",
*reinterpret_cast<std::uint32_t*>(rva_fix_addr)); *reinterpret_cast<std::int32_t*>(rva_fix_addr));
// when you inherit obfuscate please be mindful of JCC rvas... // when you inherit obfuscate please be mindful of JCC rvas...
*reinterpret_cast<std::uint32_t*>(rva_fix_addr) = JMP_RIP_SIZE; *reinterpret_cast<std::int32_t*>(rva_fix_addr) = JMP_RIP_SIZE;
gadget_stack.push_back({ instruction.second, {} }); 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_reloc }); gadget_stack.push_back({ jmp_rip, inline_jmp_branch });
break; break;
} }
case ZYDIS_MNEMONIC_JMP: 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 reloc_t inline_jmp_reloc
{ {
reloc_type::jcc,
JMP_RIP_ADDR_IDX, JMP_RIP_ADDR_IDX,
reloc_type::next_instruction_addr *reinterpret_cast<std::int32_t*>(rva_fix_addr)
}; };
gadget_stack.push_back({ jmp_rip, inline_jmp_reloc }); gadget_stack.push_back({ jmp_rip, inline_jmp_reloc });
break; break;
} }
@ -75,8 +92,8 @@ namespace obfuscation
{ {
reloc_t inline_jmp_reloc 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, {} }); gadget_stack.push_back({ instruction.second, {} });
@ -157,6 +174,6 @@ namespace obfuscation
// instruction gets executed... // instruction gets executed...
gadget_stack.insert( gadget_stack.insert(
gadget_stack.begin(), gadget_stack.begin(),
{ std::move(stack_palindrome), {NULL, reloc_type::none} }); { std::move(stack_palindrome), {reloc_type::none, NULL, NULL } });
} }
} }

@ -22,13 +22,15 @@ namespace obfuscation
enum class reloc_type enum class reloc_type
{ {
none = -1, none = -1,
next_instruction_addr = 1 jcc = 1,
next_instruction_addr = 2
}; };
struct reloc_t struct reloc_t
{ {
std::uint32_t offset;
reloc_type type; reloc_type type;
std::uint32_t offset;
std::int32_t rva;
}; };
using instruction_info_t = std::pair<ZydisDecodedInstruction, std::vector<std::uint8_t>>; using instruction_info_t = std::pair<ZydisDecodedInstruction, std::vector<std::uint8_t>>;

@ -284,6 +284,13 @@ namespace utils
DONT_RESOLVE_DLL_REFERENCES DONT_RESOLVE_DLL_REFERENCES
); );
if (!module_base)
{
// free the RTL_PROCESS_MODULES buffer...
VirtualFree(buffer, NULL, MEM_RELEASE);
return NULL;
}
const auto image_base = const auto image_base =
reinterpret_cast<std::uintptr_t>( reinterpret_cast<std::uintptr_t>(
modules->Modules[idx].ImageBase); modules->Modules[idx].ImageBase);

Loading…
Cancel
Save