A proof-of-concept User-Defined Reflective Loader (UDRL) which aims to recreate, integrate, and enhance Cobalt Strike's evasion features!
Contributors:
Contributor
Twitter
Notable Contributions
Bobby Cooke
@0xBoku
Project original author and maintainer
Santiago Pecin
@s4ntiago_p
Reflective Loader major enhancements
Chris Spehn
@ConsciousHacker
Aggressor scripting
Joshua Magri
@passthehashbrwn
IAT hooking
Dylan Tran
@d_tranman
Reflective Call Stack Spoofing
James Yeung
@5cript1diot
Indirect System Calls
UDRL Usage Considerations
The built-in Cobalt Strike reflective loader is robust, handling all Malleable PE evasion features Cobalt Strike has to offer. The major disadvantage to using a custom UDRL is Malleable PE evasion features may or may not be supported out-of-the-box.
The objective of the public BokuLoader project is to assist red teams in creating their own in-house Cobalt Strike UDRL. The project aims to support all worthwhile CS Malleable PE evasion features. Some evasion features leverage CS integration, others have been recreated completely, and some are unsupported. Before using this project, in any form, you should properly test the evasion features are working as intended. Between the C code and the Aggressor script, compilation with different versions of operating systems, compilers, and Java may return different results.
Evasion Features
BokuLoader Specific Evasion Features
Reflective callstack spoofing via synthetic frames.
Custom ASM/C reflective loader code
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.
XGetProcAddress for resolving symbols
Does not use Kernel32.GetProcAddress
xLoadLibrary for resolving DLL's base address & DLL Loading
For loaded DLLs, gets DLL base address from TEB->PEB->PEB_LDR_DATA->InMemoryOrderModuleList
Does not use Kernel32.LoadLibraryA
Caesar Cipher for string obfuscation
100k UDRL Size
Import DLL names and import entry name strings are stomped in virtual beacon DLL.
Supported Malleable PE Evasion Features
Command
Option(s)
Supported
allocator
HeapAlloc, MapViewOfFile, VirtualAlloc
All supported via BokuLoader implementation
module_x64
string (DLL Name)
Supported via BokuLoader implementation. Same DLL stomping requirements as CS implementation apply
obfuscate
true/false
HTTP/S beacons supported via BokuLoader implementation. SMB/TCP is currently not supported for obfuscate true. Details in issue. Accepting help if you can fix
entry_point
RVA as decimal number
Supported via BokuLoader implementation
cleanup
true
Supported via CS integration
userwx
true/false
Supported via BokuLoader implementation
sleep_mask
(true/false) or (Sleepmask Kit+true)
Supported. When using default "sleepmask true" (without sleepmask kit) set "userwx true". When using sleepmask kit which supports RX beacon.text memory (src47/Ekko) set "sleepmask true" && "userwx false".
magic_mz_x64
4 char string
Supported via CS integration
magic_pe
2 char string
Supported via CS integration
transform-x64 prepend
escaped hex string
BokuLoader.cna Aggressor script modification
transform-x64 strrep
string string
BokuLoader.cna Aggressor script modification
stomppe
true/false
Unsupported. BokuLoader does not copy beacon DLL headers over. First 0x1000 bytes of virtual beacon DLL are 0x00
Initially created while working through Renz0h's Reflective DLL videos from the Sektor7 Malware Developer Intermediate (MDI) Course
Usage
Compile the BokuLoader Object file with make
Start your Cobalt Strike Team Server
Within Cobalt Strike, import the BokuLoader.cna Aggressor script
Generate the x64 beacon (Attacks -> Packages -> Windows Executable (S))
Use the Script Console to ensure BokuLoader was implemented in the beacon build
Does not support x86 option. The x86 bin is the original Reflective Loader object file.
Generating RAW beacons works out of the box. When using the Artifact Kit for the beacon loader, the stagesize variable must be larger than the default.
See the Cobalt Strike User-Defined Reflective Loader documenation for additional information
Detection Guidance
Hardcoded Strings
BokuLoader changes some commonly detected strings to new hardcoded values. These strings can be used to signature BokuLoader:
Original Cobalt Strike String
BokuLoader Cobalt Strike String
ReflectiveLoader
BokuLoader
Microsoft Base Cryptographic Provider v1.0
12367321236742382543232341241261363163151d
(admin)
(tomin)
beacon
bacons
Memory Allocators
DLL Module Stomping
The Kernel32.LoadLibraryExA is called to map the DLL from disk
The 3rd argument to Kernel32.LoadLibraryExA is DONT_RESOLVE_DLL_REFERENCES (0x00000001)
the system does not call DllMain
Does not resolve addresses in LDR PEB entry as detailed by MDSec here
Detectable by scanning process memory with pe-sieve tool
Heap Allocation
Executable RX or RWX memory will exist in the heap if sleepmask kit is not used.
Mapped Allocator
The Kernel32.CreateFileMappingA & Kernel32.MapViewOfFile is called to allocate memory for the virtual beacon DLL.
Sleepmask Detection
If sleepmask kit is used, there exists detection methods for this independent memory allocation as detailed by MDSec here
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.
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.
Source Code Available
The BokuLoader source code is provided within the repository and can be used to create memory signatures.
If you have additional detection guidance, please feel free to contribute by submitting a pull request.
Credits / References
Reflective Call Stack Spoofing
LoudSunRun: Call stack synthetic frame spoofer with indirect syscalls
SilentMoonwalk: PoC Implementation of a fully dynamic call stack spoofer
Vulcan Raven: PoC implementation for spoofing arbitrary call stacks when making syscalls
CallStackMasker: A PoC implementation for dynamically masking call stacks with timers
ThreadStackSpoofer: Thread Stack Spoofing PoC
Behind the Mask: Spoofing Call Stacks Dynamically with Timers