Cobalt Strike User-Defined Reflective Loader (UDRL) in Rust, implementing Shellcode Reflective DLL Injection (sRDI). A ~65KB position-independent reflective loader with module stomping, synthetic call stack spoofing, sleep obfuscation, memory encryption, return address spoofing, IAT hooking, and heap isolation.
Named after DoublePulsar, an implant developed by the NSA's Equation Group, leaked by the Shadow Brokers in 2017.
- Raphael Mudge and Cobalt Strike - User-Defined Reflective Loader API
- Revisiting the UDRL Part 1 by Robert Bearsby / Cobalt Strike - Prepended loader architecture diagram
- Red Team Ops II by RastaMouse / Zero Point Security - CRTO II course and advanced Cobalt Strike training
- AceLdr by Kyle Avery - IAT hooking, return address spoofing, heap isolation
- TitanLdr by Austin Hudson - FOLIAGE sleep obfuscation, memory encryption
- FOLIAGE by Austin Hudson - FOLIAGE sleep obfuscation
- titanldr-ng by Austin Hudson - CNA integration, RC4 beacon encryption
- SilentMoonwalk by klezVirus, trickster0, and waldo-irc - Call stack spoofing
- Ekko by Cracked5pider - Ekko sleep obfuscation technique
- Crystal-Kit by RastaMouse - Cobalt Strike kit reference
- uwd and hypnus by Joao Victor - Original unwinder and sleep obfuscation crates, rewritten and converted to position-independent code (PIC)
- x64 return address spoofing by namazso - Original return address spoofing technique
- Gargoyle by J. Lospinoso - Timer-based code execution
- MalMemDetect by waldo-irc - Malicious memory detection
- Bypassing PE-sieve and Moneta by Arash Parsa
- Hook heaps and live free by Arash Parsa
- Masking malicious memory artifacts by Forrest Orr
- Hunting Gargoyle by F-Secure
- Detecting Cobalt Strike with memory signatures by Elastic
- MDSec Nighthawk study - Ekko sleep obfuscation research
- Equation Group / NSA - Original DoublePulsar implant concept
Unlike Stephen Fewer's original approach where the reflective loader lives inside the PE's .text section, DoublePulsar uses a prepended architecture where the ReflectiveLoader() is placed before the PE file. This allows the loader to be fully position-independent shellcode that decrypts and maps the beacon payload at runtime.
Diagram from Revisiting the UDRL Part 1 by Robert Bearsby / Cobalt Strike
- Position-independent Rust reflective loader for Cobalt Strike (prepended loader)
- Module stomping (loads beacon into a legitimate module's memory, enabled by default)
- Synthetic call stack spoofing (randomized per call, enabled by default via
spoof-uwd). Either module stomping or call stack spoofing is needed, but module stomping is preferred. Call stack spoofing serves as a fallback - Dynamic memory encryption (new heap for beacon allocations, encrypted during sleep)
- Code obfuscation and encryption (non-executable + encrypted during sleep)
- Return address spoofing (InternetConnectA, NtWaitForSingleObject, RtlAllocateHeap)
- IAT hooking
- Heap isolation
- RC4 encryption via SystemFunction032
- Optional syscall dispatch (cringe, but it's there 🙄) (
spoof-syscallfeature, requiresspoof-uwd). Uses Hell's Gate for direct syscalls when unhooked, falls back to Halo's Gate / Tartarus Gate for indirect syscalls when hooks are detected - Multiple sleep obfuscation techniques:
| Feature | Technique | Description |
|---|---|---|
sleep-ekko |
Ekko | Timer-based (TpAllocTimer/TpSetTimer) + RC4 + NtContinue chain + fiber support (default) |
sleep-foliage |
FOLIAGE | APC-based (NtQueueApcThread) + RC4 + NtContinue chain + fiber support |
sleep-zilean |
Zilean | Wait-based (TpAllocWait/TpSetWait) + RC4 + NtContinue chain + fiber support |
sleep-xor |
XOR | XOR section masking + plain Sleep (no CONTEXT chain, no fiber mode) |
Import the Titan.cna script before generating shellcode. The script:
- Takes your raw beacon payload
- RC4 encrypts it with a random 16-byte key
- Appends
[CONFIG (key + size)][Encrypted Beacon]to the loader - At runtime, the loader decrypts the beacon in-memory and executes it
x64 only. x86 is not supported.
Recommended: build on Ubuntu/WSL to avoid MinGW relocation issues on Windows.
- Rust nightly with
x86_64-pc-windows-gnutarget - MinGW-w64
- cargo-make
- nasm
# Install Rust nightly and add target
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
rustup toolchain install nightly
rustup default nightly
rustup target add x86_64-pc-windows-gnu
# Install MinGW-w64 and nasm
sudo apt update
sudo apt install -y mingw-w64 nasm
# Install cargo-make
cargo install cargo-make
# Build
cd udrl
cargo make x64cargo make x64 # x64 release
cargo make x64-debug # x64 with debug logging (DbgPrint)
cargo make clean # clean build artifactsOnly enable one sleep feature at a time. They are mutually exclusive. Use --no-default-features when selecting a non-default technique.
# Ekko (default)
cargo make x64
# FOLIAGE
cargo build --release --target x86_64-pc-windows-gnu --features sleep-foliage --no-default-features
# Zilean
cargo build --release --target x86_64-pc-windows-gnu --features sleep-zilean --no-default-features
# XOR (no ROP chain, no fiber)
cargo build --release --target x86_64-pc-windows-gnu --features sleep-xor --no-default-featuresbin/Titan.x64.bin - x64 shellcode
Tested on Windows 10 (Build 19045) and Windows 11 (Build 22631) against Elastic 9.0.1 (trial) in prevention mode with aggressive settings and the following integrations enabled: Elastic Defend, Elastic Agent, Fleet Server, Prebuilt Security Detection Rules, Elastic Synthetics, System, and Windows. Cobalt Strike settings: Stageless Windows Executable, Raw output, x64 payload, Process exit function, winhttp library. Lab environment: GOAD on Ludus.
YARA rules for detection are provided in doublepulsar.yar.
- Not compatible with loaders that rely on the shellcode thread staying alive
- Windows builds may encounter relocation errors with newer MinGW versions (use WSL)
- AllocConsole logging can cause crashes when spammed with too many log entries, use DbgPrint instead
License: MIT. See LICENSE
Disclaimer: This project is provided for authorized security testing, educational purposes, and legitimate security research only.
Permitted use includes:
- Authorized penetration testing and red team engagements
- Purple teaming, adversary simulation, and threat emulation
- Detection engineering, threat hunting, and security operations
- Blue team and SOC activities including malware reverse engineering
- CTF competitions and security research
- Educational and training purposes
Prohibited use includes:
- Unauthorized access to systems or networks
- Any activity that violates applicable laws or regulations
- Use against systems without explicit written authorization
Liability: The author assumes no responsibility for misuse, damages, or legal consequences arising from the use of this software. Users are solely responsible for ensuring compliance with all applicable laws, regulations, and organizational policies. By using this software, you agree that you have proper authorization for any systems you interact with.
