Crystal Palace integration for the Starburst agent. Produces obfuscated position-independent shellcode by linking Starburst's raw PIC output through a Crystal Palace loader.
Starburst compiles to raw shellcode (.bin). When the output type is set to "Crystal Palace shellcode",
the builder wraps the raw shellcode in a minimal DLL stub (sc_stub.c), then passes it to Crystal
Palace's cpl link command with the loader's .spec file. The result is a fully self-contained PIC
blob with the loader's reflective capabilities baked in.
Raw Starburst shellcode (.bin)
↓
DLL stub wrapper (sc_stub.c)
↓ ld -r -b binary (embed shellcode as .data)
↓ gcc -shared (link stub + payload into DLL)
↓
Crystal Palace `cpl link`
↓ loader.spec defines the final PIC layout
↓
Final PIC shellcode with loader
Post-exploitation payloads (execute_assembly, execute_pic, shinject) follow the same flow using the
post-ex loader, which additionally accepts an arguments buffer (%ARGFILE).
This CrystalKit provides advanced evasion capabilities on top of Starburst's raw shellcode:
- Draugr call stack spoofing — forges synthetic N-frame call stacks during loader execution (x64 only; x86 builds omit spoofing due to unwind table differences)
- TCG library — merges the Tradecraft Garden TCG library (
libtcg.x64.zip/libtcg.x86.zip) for advanced API hooking and CFG bypass - API hooking — hooks
LoadLibraryA,VirtualAlloc,VirtualProtect,VirtualFreethrough Crystal Palace'sattachdirective - Sleep masking — XOR-masks the embedded DLL payload with a random 128-byte key during sleep
- CFG bypass — via TCG library integration, bypasses Control Flow Guard on modern Windows
- DFR (Dynamic Function Resolution) — ROR13-based function resolution for the loader itself
Starburst.CrystalKit/
Makefile Top-level delegator (cd loader && make $@, cd postex-loader && make $@)
libtcg.x64.zip TCG library for x64 builds
libtcg.x86.zip TCG library for x86 builds
crystalkit.cna Cobalt Strike integration script (legacy, not used by Mythic)
crystalkit.yar YARA rules for detection testing
loader/ Main loader (wraps Starburst shellcode)
Makefile Compiles all .c sources + NASM draugr.asm to COFF objects
loader.spec Crystal Palace linker script (cpl link mode)
local-loader.spec Local execution variant
pico.spec TCG PICO tradecraft spec
src/
loader.c Main loader entry — reflective DLL loading + execution
spoof.c / spoof.h Draugr call stack spoofing implementation
draugr.asm Draugr ASM stub (NASM, x64 only)
hooks.c API hooking via Crystal Palace attach
mask.c / mask.h Sleep masking (XOR payload during sleep)
cfg.c / cfg.h CFG bypass
cleanup.c / cleanup.h Post-load cleanup
services.c Service-related helpers
pico.c TCG PICO integration
tcg.h TCG library header
loader.h Shared loader types
memory.h Memory management helpers
postex-loader/ Post-exploitation loader (wraps BOFs, assemblies, PIC payloads)
Makefile
loader.spec Crystal Palace linker script (accepts %ARGFILE)
pico.spec
src/ Same structure as loader/ with post-ex specific entry
- Java 11+ (OpenJDK)
- Crystal Palace (
crystalpalace.jar) — placed in Starburst'sloaders/crystal-palace/crystal-linker/ - MinGW-w64 cross-compiler toolchain:
x86_64-w64-mingw32-gcc(x64 builds)i686-w64-mingw32-gcc(x86 builds)- On Windows: MSYS2 with
mingw-w64-x86_64-toolchainandmingw-w64-i686-toolchainpackages
- NASM (for draugr assembly stub)
Copy this kit's loader/ and postex-loader/ directories into Starburst's
Payload_Type/starburst/loaders/crystal-palace/ as default/ and post-ex/ respectively.
Pre-build the COFF objects:
cd loader && make x64 && make x86
cd ../postex-loader && make x64 && make x86
Then select "shellcode" as the output type in Mythic — the builder uses whatever is in
crystal-palace/default/ and crystal-palace/post-ex/ automatically.
ZIP the entire kit (or just the loader/ subdirectory) and upload via the Mythic build dialog:
- Set output type to shellcode
- Enable "Use custom Crystal Palace UDRL"
- Upload the ZIP file
- Optionally enable "Use custom post-ex UDRL" and upload the same or a separate ZIP
The builder auto-discovers the correct subdirectories, runs make, and links with cpl link.
Operators can upload a custom UDRL as a ZIP file when building a payload through the Mythic UI. Enable the "Use custom Crystal Palace UDRL" toggle in the UDRL build parameter group, then upload a ZIP archive.
The builder auto-discovers Makefile and loader.spec locations, so multiple archive structures
are supported:
Flat layout (loader.spec at archive root):
my-loader.zip
Makefile
loader.spec
src/
loader.c
Nested layout (subdirectories with their own Makefile and loader.spec):
my-kit.zip
Makefile ← top-level Makefile that delegates to subdirs
loader/
Makefile
loader.spec
src/
loader.c
postex-loader/
Makefile
loader.spec
src/
loader-postex.c
Single-loader archive (only one loader type present):
my-loader.zip
loader/
Makefile
loader.spec
src/
loader.c
When an archive contains multiple subdirectories with loader.spec files, the builder selects
the appropriate one based on the context:
- Loader role (payload build): prefers a directory named exactly
loader, otherwise picks the first non-postex directory - Post-ex role (post-exploitation operations): prefers directories containing
postex,post-ex, orpost_exin the name
- Archive is extracted to a temporary directory
- Builder finds the Makefile directory (top-level if present, otherwise first subdir with Makefile)
make {arch}is run (where arch isx64orx86)- Builder finds the
loader.specfor the appropriate role - Starburst shellcode is wrapped in a DLL stub and linked via
cpl linkwith the discovered spec - Temporary files are cleaned up
Your loader must:
- Compile to a COFF object via
make x64and/ormake x86 - Include a
loader.specCrystal Palace linker script - Be compatible with
cpl link(DLL input → PIC output)
The DLL stub (sc_stub.c) provides two symbols to your loader:
sc_payload— start of the embedded Starburst shellcodesc_payload_end— end of the embedded shellcode
Operators can also upload a custom post-ex UDRL. This loader is used for post-exploitation operations (execute_assembly, execute_pic, shinject) and receives an additional argument buffer.
Enable "Use custom post-ex UDRL" in the UDRL build parameter group and upload a ZIP archive.
The same archive layout rules apply — the builder will look for a directory with postex in the
name when selecting the spec file.
Custom post-ex UDRLs are stored per-payload and persist for the lifetime of the callback, so post-ex operations use your custom loader rather than the default.
Your post-ex loader.spec must accept %ARGFILE — a Crystal Palace variable pointing to the
arguments binary. The default post-ex loader demonstrates this pattern.
Both x64 and x86 are supported. The builder passes the target architecture to make and selects
the appropriate cross-compiler automatically:
| Architecture | Compiler | MSYS2 Package |
|---|---|---|
| x64 | x86_64-w64-mingw32-gcc |
mingw-w64-x86_64-toolchain |
| x86 | i686-w64-mingw32-gcc |
mingw-w64-i686-toolchain |
On Windows, the builder adds MSYS2 bin directories to PATH automatically. On Linux, the cross-compilers must be available on PATH (installed via package manager).
"Crystal Palace not installed" — crystalpalace.jar not found in crystal-linker/. Download
from https://tradecraftgarden.org and place it there.
"Custom UDRL compile failed" — make {arch} returned an error. Check that your Makefile
supports the x64 and x86 targets and that the cross-compiler is installed.
"No loader.spec found" — The builder couldn't locate a loader.spec in your archive. Verify
your ZIP structure matches one of the supported layouts above.
"DLL stub wrapping failed" — The shellcode-to-DLL wrapping step failed. Check that ld and
objcopy are available (part of the MinGW-w64 toolchain).
x86 build errors with __udivdi3 — 64-bit division in -nostdlib x86 builds requires
libgcc. Avoid 64-bit arithmetic in x86 loader code, or link against libgcc.