From 15e848a5db89bbd5716aecb89b1196e0e8acbedc Mon Sep 17 00:00:00 2001 From: _xeroxz Date: Mon, 8 Mar 2021 08:41:09 +0000 Subject: [PATCH] Update README.md --- README.md | 204 +++++++++++++++++++++++++++--------------------------- 1 file changed, 102 insertions(+), 102 deletions(-) diff --git a/README.md b/README.md index 8682dae..791536b 100644 --- a/README.md +++ b/README.md @@ -31,108 +31,6 @@ Static linking is when the linker links entire routines not created by you, into Dynamic linking is when external symbols are resolved at runtime. This is done by imports and exports in DLL's (dynamiclly linked libraries). Theo supports "dynamic linking", or in better terms, linking against exported routines. You can see examples of this inside of both usermode and kernelmode examples. -# 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: - -``` -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 -``` - -As you can see from the code above, (sorry for the terrible syntax highlighting), references to strings and calls to functions are done by first loading the address of the symbol into a register and then interfacing with the symbol. - -``` -0x2D: 48 B8 A0 01 00 00 00 00 00 00 mov rax, offset MessageBoxA -; ... -0x3D: FF D0 call rax ; MessageBoxA -``` - -Each of these instructions can be anywhere in virtual memory and it would not effect code execution one bit. However this is not the case with routines which have conditional branches. Take the following c++ code for example. - -```cpp -ObfuscateRoutine -void LoopDemo() -{ - for (auto idx = 0u; idx < 10; ++idx) - DbgPrint("> Loop Demo: %d\n", idx); -} -``` - -This c++ function, compiled by clang-cl with `mcmodel=large`, will generate a routine with the following instructions: - -``` -0x58 ; void LoopDemo(void) -0x58 public ?LoopDemo@@YAXXZ -0x58 ?LoopDemo@@YAXXZ proc near -0x58 var_4 = dword ptr -4 -0x58 -0x58 48 83 EC 28 sub rsp, 28h -0x5C C7 44 24 24 00 00 00 00 mov [rsp+28h+var_4], 0 -0x64 loc_64: -0x64 83 7C 24 24 0A cmp [rsp+28h+var_4], 0Ah -0x69 0F 83 2A 00 00 00 jnb loc_99 -0x6F 8B 54 24 24 mov edx, [rsp+28h+var_4] -0x73 48 B9 60 01 00 00 00 00 00 00 mov rcx, offset ??_C@_0BB@HGKDPLMC@?$.... ; "> Loop Demo: %d\n" -0x7D 48 B8 38 02 00 00 00 00 00 00 mov rax, offset DbgPrint -0x87 FF D0 call rax ; DbgPrint -0x89 8B 44 24 24 mov eax, [rsp+28h+var_4] -0x8D 83 C0 01 add eax, 1 -0x90 89 44 24 24 mov [rsp+28h+var_4], eax -0x94 E9 CB FF FF FF jmp loc_64 -0x99 loc_99: -0x99 48 83 C4 28 add rsp, 28h -0x9D C3 retn -0x9D ?LoopDemo@@YAXXZ endp -``` - -Uh oh, `jnb loc_99`?, thats RIP relative! In order to handle branching operations, a "jump table" is generated by `obfuscation::obfuscate` explicit default constructor. Instead of branching to the RIP relative code, it will instead branch to an inline jump (`JMP [RIP+0x0]`). As demonstrated below, the branching operation is altered to branch to an asbolute jump. - -``` -ffff998b`c5369e60 0f830e000000 jnb ffff998b`c5369e74 -ffff998b`c5369e66 ff2500000000 jmp qword ptr [ffff998b`c5369e6c] -... -ffff998b`c5369e74 ff2500000000 jmp qword ptr [ffff998b`c5369e7a] -``` - -The linker is able to get the address of the branching code by taking the rip relative virtual address of the branching operation, which is a signed number, and adding it to the current byte offset into the current routine, plus the size of the branching instruction. For example `LoopDemo@17` + size of the branching instruction, which is six bytes, then adding the signed relative virtual address (0x2A). The result of this simple calculation gives us `LoopDemo@65`, which is correct, the branch goes to `add rsp, 28h` in the above example. - # Usage - Using Theodosius Theodosius uses the same class structure as HMDM does. Its a highly modular format which allows for extreme usage, supporting almost every idea one might have. In order to use Theo, you must first define three lambdas, `theo::memcpy_t` a method of copying memory, `theo::malloc_t` a method to allocate executable memory, and lastely `theo::resolve_symbol_t` a lamdba to resolve external symbols. @@ -378,6 +276,108 @@ CreateRemoteThread ); ``` +# 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: + +``` +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 +``` + +As you can see from the code above, (sorry for the terrible syntax highlighting), references to strings and calls to functions are done by first loading the address of the symbol into a register and then interfacing with the symbol. + +``` +0x2D: 48 B8 A0 01 00 00 00 00 00 00 mov rax, offset MessageBoxA +; ... +0x3D: FF D0 call rax ; MessageBoxA +``` + +Each of these instructions can be anywhere in virtual memory and it would not effect code execution one bit. However this is not the case with routines which have conditional branches. Take the following c++ code for example. + +```cpp +ObfuscateRoutine +void LoopDemo() +{ + for (auto idx = 0u; idx < 10; ++idx) + DbgPrint("> Loop Demo: %d\n", idx); +} +``` + +This c++ function, compiled by clang-cl with `mcmodel=large`, will generate a routine with the following instructions: + +``` +0x58 ; void LoopDemo(void) +0x58 public ?LoopDemo@@YAXXZ +0x58 ?LoopDemo@@YAXXZ proc near +0x58 var_4 = dword ptr -4 +0x58 +0x58 48 83 EC 28 sub rsp, 28h +0x5C C7 44 24 24 00 00 00 00 mov [rsp+28h+var_4], 0 +0x64 loc_64: +0x64 83 7C 24 24 0A cmp [rsp+28h+var_4], 0Ah +0x69 0F 83 2A 00 00 00 jnb loc_99 +0x6F 8B 54 24 24 mov edx, [rsp+28h+var_4] +0x73 48 B9 60 01 00 00 00 00 00 00 mov rcx, offset ??_C@_0BB@HGKDPLMC@?$.... ; "> Loop Demo: %d\n" +0x7D 48 B8 38 02 00 00 00 00 00 00 mov rax, offset DbgPrint +0x87 FF D0 call rax ; DbgPrint +0x89 8B 44 24 24 mov eax, [rsp+28h+var_4] +0x8D 83 C0 01 add eax, 1 +0x90 89 44 24 24 mov [rsp+28h+var_4], eax +0x94 E9 CB FF FF FF jmp loc_64 +0x99 loc_99: +0x99 48 83 C4 28 add rsp, 28h +0x9D C3 retn +0x9D ?LoopDemo@@YAXXZ endp +``` + +Uh oh, `jnb loc_99`?, thats RIP relative! In order to handle branching operations, a "jump table" is generated by `obfuscation::obfuscate` explicit default constructor. Instead of branching to the RIP relative code, it will instead branch to an inline jump (`JMP [RIP+0x0]`). As demonstrated below, the branching operation is altered to branch to an asbolute jump. + +``` +ffff998b`c5369e60 0f830e000000 jnb ffff998b`c5369e74 +ffff998b`c5369e66 ff2500000000 jmp qword ptr [ffff998b`c5369e6c] +... +ffff998b`c5369e74 ff2500000000 jmp qword ptr [ffff998b`c5369e7a] +``` + +The linker is able to get the address of the branching code by taking the rip relative virtual address of the branching operation, which is a signed number, and adding it to the current byte offset into the current routine, plus the size of the branching instruction. For example `LoopDemo@17` + size of the branching instruction, which is six bytes, then adding the signed relative virtual address (0x2A). The result of this simple calculation gives us `LoopDemo@65`, which is correct, the branch goes to `add rsp, 28h` in the above example. + # 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.