A proof-of-concept User-Defined Reflective Loader (UDRL) which aims to recreate, integrate, and enhance Cobalt Strike's evasion features!
Contributor | 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 |
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.
- 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
- All memory protection changes for all allocation options are done via direct syscall to
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.
- Loader will not copy headers raw beacon DLL to virtual beacon DLL. First
XGetProcAddress
for resolving symbols- Does not use
Kernel32.GetProcAddress
- Does not use
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
- For loaded DLLs, gets DLL base address from
- Caesar Cipher for string obfuscation
- 100k UDRL Size
- Import DLL names and import entry name strings are stomped in virtual beacon DLL.
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 |
checksum |
number | Experimental. BokuLoader.cna Aggressor script modification |
compile_time |
date-time string | Experimental. BokuLoader.cna Aggressor script modification |
image_size_x64 |
decimal value | Unsupported |
name |
string | Experimental. BokuLoader.cna Aggressor script modification |
rich_header |
escaped hex string | Experimental. BokuLoader.cna Aggressor script modification |
stringw |
string | Unsupported |
string |
string | Unsupported |
- (2/22/23) All 4 allocator methods tested with threatexpress/malleable-c2/master/jquery-c2.4.7.profile
- Based on Stephen Fewer's incredible Reflective Loader project:
- Initially created while working through Renz0h's Reflective DLL videos from the Sektor7 Malware Developer Intermediate (MDI) Course
- 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, thestagesize
variable must be larger than the default.- See the Cobalt Strike User-Defined Reflective Loader documenation for additional information
- 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 |
- The
Kernel32.LoadLibraryExA
is called to map the DLL from disk - The 3rd argument to
Kernel32.LoadLibraryExA
isDONT_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
- Executable
RX
orRWX
memory will exist in the heap if sleepmask kit is not used.
- The
Kernel32.CreateFileMappingA
&Kernel32.MapViewOfFile
is called to allocate memory for the virtual beacon DLL.
- If sleepmask kit is used, there exists detection methods for this independent memory allocation as detailed by MDSec here
- 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.
- 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.
- The first
0x1000
bytes of the virtual beacon DLL are zeros.
- 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.
- https://github.com/stephenfewer/ReflectiveDLLInjection
- Checkout these videos if you're interested in Reflective DLL:
- TitanLdr
- AceLdr
- KaynLdr
- Reenz0h from @SEKTOR7net
- Checkout Reenz0h's awesome courses and blogs!
- Best classes for malware development I have taken.
- Creator of the halos gate technique. His work was initially the motivation for this work.
- Sektor7 HalosGate Blog
- @smelly__vx & @am0nsec ( Creators/Publishers of the Hells Gate technique )
- Could not have made my implementation of HellsGate without them :)
- Awesome work on this method, really enjoyed working through it myself. Thank you!
- https://github.com/am0nsec/HellsGate
- Link to the Hell's Gate paper: https://vxug.fakedoma.in/papers/VXUG/Exclusive/HellsGate.pdf
- @anthemtotheego inline-ExecuteAssembly
- @mariuszbit - for awesome idea to implement bypasses in reflective loader!
- @XPN Hiding Your .NET – ETW
- ajpc500/BOFs
- Offensive Security OSEP