You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
Theodosius/README.md

96 lines
5.4 KiB

4 years ago
<div align="center">
<div>
4 years ago
<img width="27%" src="https://githacks.org/_xeroxz/theodosius/-/raw/07b58a233c0fbd289856c90158fe342fc4be4deb/imgs/theo.jpg"/>
4 years ago
</div>
</div>
4 years ago
# Theodosius - Jit linker, Mapper, Mutator, and Obfuscator
4 years ago
4 years ago
Theodosius (Theo for short) is a jit linker created entirely for obfuscation and mutation of both code, and code flow. The project is extremely modular in design and supports
4 years ago
both kernel and usermode projects. Since Theo inherits HMDM (highly modular driver mapper), any vulnerable driver that exposes arbitrary MSR writes, or physical memory read/write can be used with this framework to map unsigned code into the kernel. This is possible since HMDM inherits VDM (vulnerable driver manipulation), and MSREXEC (elevation of arbitrary MSR writes to kernel execution).
4 years ago
4 years ago
Since Theo is a jit linker, unexported symbols can be jit linked. Resolving such symbols is open ended and allows the programmer of this framework to handle how they want to resolve symbols. More on this later (check out example projects).
4 years ago
# RIP Relative Addressing
In order to allow for a routine to be scattered throughout a 64bit address space, RIP relative addressing must not be used. In order to facilitate this, a very special version
of clang-cl is used which can use `mcmodel=large`. This will generate instructions which do not use RIP relative addressing when referencing symbols outside of the routine in which the
instruction itself resides. The only exception to this is JCC instructions, (besides call) also known as branching instructions. Take this c++ code for an example:
```cpp
ObfuscateRoutine
extern "C" int ModuleEntry()
{
MessageBoxA(0, "Demo", "Hello From Obfuscated Routine!", 0);
UsermodeMutateDemo();
UsermodeNoObfuscation();
}
```
This c++ function, compiled by clang-cl with `mcmodel=large`, will generate a routine with the following instructions:
```nasm
0x00: ; void UsermodeNoObfuscation(void)
0x00: public ?UsermodeNoObfuscation@@YAXXZ
0x00: ?UsermodeNoObfuscation@@YAXXZ proc near ; CODE XREF: ModuleEntry+42↓p
0x00: var_4 = dword ptr -4
0x00: 48 83 EC 28 sub rsp, 28h
0x04: C7 44 24 24 00 00 00 00 mov [rsp+28h+var_4], 0
0x0C: loc_C:
0x0C: 83 7C 24 24 05 cmp [rsp+28h+var_4], 5
0x11: 0F 83 38 00 00 00 jnb loc_4F
0x17: 31 C0 xor eax, eax
0x19: 48 BA 28 01 00 00 00 00 00 00 mov rdx, offset ??_C@_04DKDMNOEB@Demo?$AA@ ; "Demo"
0x23: 49 B8 00 01 00 00 00 00 00 00 mov r8, offset ??_C@_0CD@JEJKPGNA@Hello?5... ; "Hello From Non-Obfuscated Routine!"
0x2D: 48 B8 A0 01 00 00 00 00 00 00 mov rax, offset MessageBoxA
0x37: 45 31 C9 xor r9d, r9d ; uType
0x3A: 44 89 C9 mov ecx, r9d ; hWnd
0x3D: FF D0 call rax ; MessageBoxA
0x3F: 8B 44 24 24 mov eax, [rsp+28h+var_4]
0x43: 83 C0 01 add eax, 1
0x46: 89 44 24 24 mov [rsp+28h+var_4], eax
0x4A: E9 BD FF FF FF jmp loc_C
0x4F: loc_4F:
0x4F: 48 83 C4 28 add rsp, 28h
0x53: C3 retn
0x53: ?UsermodeNoObfuscation@@YAXXZ endp
```
4 years ago
# Obfuscation
The usage of the word obfuscation in this project is use to define any changes made to code, this includes code flow. `obfuscation::obfuscate`, a base class, which is inherited and expanded upon by `obfuscation::mutation`, obfuscates code flow by inserting `JMP [RIP+0x0]` instructions after every single instruction. This allows for a routine to be broken up into unique allocations of memory and thus provides more canvas room for creative ideas.
### Obfuscation - Base Class
4 years ago
The base class, as described in the above section, contains a handful of util routines and a single explicit constructor which is the corner stone of the class. The constructor fixes JCC relative virtual addresses so that if the condition is met, instead of jumping instruction pointer relativitly, it will jump to an addition jmp (`JMP [RIP+0x0]`). LEA, nor CALL are rip relative, even for symbols defined inside of the routine in which the instruction is compiled into. In other words JCC instructions are the only instruction pointer relative instructions that are generated.
```cpp
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)
};
4 years ago
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<std::int32_t*>(rva_fix_addr));
4 years ago
// when you inherit obfuscate please be mindful of JCC rvas...
*reinterpret_cast<std::int32_t*>(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_branch });
```
### Mutation - Inherts Obfuscation
4 years ago