Crystal Palace Quick Reference
Crystal Palace is a linker and linker script language specialized to the needs of writing tradecraft as position-independent code.
Requirements
Crystal Palace requires:
Crystal Palace assumes a Linux (or Windows Subsystem for Linux) development environment.
Command-line Usage
To use Crystal Palace on the command-line, use:
./link /path/to/loader.spec demo/test.x64.dll out.x64.bin
Crystal Palace includes a shellcode runner and a "Hello World" DLL in the demo/ folder. Try it with your position-independent DLL loader:
./demo/run.x64.exe out.x64.bin

Other CLI Options
-g "out.yar" generates a Yara rule file with out.x64.bin.
KEY=04030201 sets byte[] $KEY to 0x04, 0x03, 0x02, 0x01.
%var="value" sets template string %var to value.
-r %var="fileA, fileB" sets template string %var to /full/path/to/fileA, /full/path/to/fileB
@config.spec runs config.spec before loader.spec runs.
Specification Files
The Crystal Palace linker is driven by specification files. These files are Crystal Palace's linker script.
Here's an example specification file:
Each command works with the program stack and its contents, %string variables, and byte[] $content variables:

Command Reference
Below is a full list of Crystal Palace spec file commands and how they impact the Crystal Palace stack:
| Command | Pop | Push | Description |
|---|---|---|---|
| addhook "MOD$Func" | OBJECT | OBJECT | Register MOD$Func's attach "MOD$Func" "hook" chain with __resolve_hook() intrinsic. |
| addhook "MOD$Func" "hook" | OBJECT | OBJECT | Register MOD$Func hook for use with __resolve_hook() intrinsic. |
| attach "MOD$Func" "hook" | OBJECT | OBJECT | Rewrite calls and references to MODULE$Function to go through hook(). Preserves MODULE$Function in hook(). |
| before "cmd1": cmd2 %_ | Run cmd2 before cmd1 executes. %_ is set to the command+arguments of cmd1. %1 ... %n are set to the individual arguments | ||
| call "file.spec" "label" ... | Calls "label" from another .spec, using the same target, $VARs, and stack as the current script. Accepts positional arguments, passed as %1, %2, etc. | ||
| coffparse "file.txt" ["title"] | OBJECT | OBJECT | Parse object on stack and output a string representation to file.txt (or STDOUT). The COFF parsing will occur at export, after +options are applied, and before patched values are acted on. |
| dfr "resolver" "method" | OBJECT | OBJECT | (PIC only) Sets default dynamic function resolution resolver function. Rewrites MODULE$Function references in PIC to call resolver. ror13 method passes ror13 module and function hashes to resolver. strings method passes module and function stack strings to resolver. |
| dfr "res." "method" "M1, M2" | OBJECT | OBJECT | (PIC only) Set dynamic function resolution resolver function for Win32 APIs from MODULE1 and MODULE2. This resolver has priority over the default resolver. |
| disassemble "file.txt" ["title"] | OBJECT | OBJECT | Disassemble object on stack and write output to file.txt (or STDOUT). The disassemble will occur at export, after +options are applied, and before patched values are acted on. Add +forms option to show iced generic instruction forms in output. |
| echo ... | print arguments to STDOUT (CLI) or SpecLogger (Java API) | ||
| export | OBJECT | BYTES | Turn object on stack into bytes |
| exportfunc "fun" "__tag_fun" | OBJECT | OBJECT | (PICO only) Export function from PICO and generate __tag_function intrinsic (used with PicoGetExport to find func pointer) |
| filterhooks $DLL|$OBJECT | OBJECT | OBJECT | Walk imports of $DLL or $OBJECT and remove registered hooks for APIs not in import table |
| fixbss "getBSS" | OBJECT | OBJECT | (PIC only) Rewrites PIC .bss (uninitialized global variables) references to call getBSS(size of bss section) and reference global variables as an offset of the returned pointer. This restores uninitialized global variables in PIC programs. |
| fixptrs "_caller" | OBJECT | OBJECT | (x86 PIC only) Rewrite x86 PIC to turn partial pointers into full pointers with the help of _caller function. Allows access to strings and linked data without hacks. |
| foreach %var: cmd %_ | For each item in %var (comma separated list of strings), run cmd with %_ set to the current item. | ||
| generate $VAR ## | Generate ## random bytes and assign to $VAR | ||
| import "A, B, C, ..." | OBJECT | OBJECT | Import functions A, B, and C into COFF object. "A, B, C, ..." maps members of IMPORTFUNCS struct passed to PicoLoader to function symbols in COFF. First two values are always LoadLibraryA and GetProcAddress. Extend IMPORTFUNCS struct to pass the other pointers |
| ised verb pttrn $CODE +opts | OBJECT | OBJECT | Program rewriting tool. 'replace' or 'insert' $CODE where pattern matches. Pattern is one or more strings containing a disassembled instruction string, iced generic form (e.g., CALL rel32), or instruction mnemonics (e.g., CALL). Options include: +split (insert block break), +safe (attest $CODE is RFLAGS aware), +first / +last (which instruction to act on), and +before / +after (where to insert $CODE or +split) |
| load "file" | BYTES | Load contents of file onto stack | |
| load $VAR "file" | Load contents of file into $VAR | ||
| link "section" | BYTES, OBJECT | OBJECT | Link (data) bytes on the stack to section __attribute__((section("section"))) in object on the stack. |
| linkfunc "symbol" | BYTES, OBJECT | OBJECT | Link (code) bytes on the stack to function symbol in object on stack |
| magic "0x##, 0x##, ..." | Set magic values used by +mutate to break up constants | ||
| make coff [+options] | BYTES | OBJECT | Turn contents on stack into a COFF-exporter object.
Options are +optimize (Link-time optimization), +disco (randomize function order), +mutate (constants mutator), and others |
| make object [+options] | BYTES | OBJECT | Turn contents on stack into a PICO-exporter object.
Options are +optimize (Link-time optimization), +disco (randomize function order), +mutate (constants mutator), and others |
| make pic [+options] | BYTES | OBJECT | Turn contents on stack into PIC-exporter object.
Options are +optimize (Link-time optimization), +disco (randomize function order), +mutate (constants mutator), +gofirst (make go the first function), and others |
| merge | BYTES, OBJECT | OBJECT | Merge bytes on stack (COFF content) to object on stack |
| mergelib "lib.x##.zip" | OBJECT | OBJECT | Merges each COFF file within zip archive to object on stack |
| meta "verb" "value" | Update meta-information for current .spec file. Verbs: author, describe, license, name, and reference. |
||
| next "%var": cmd %_ | Remove first element from %var and run cmd with %_ set to the removed element. Do nothing if %var is empty. | ||
| options [+options] | OBJECT | OBJECT | Turn on more +options for this export configuration object.
Options are +optimize (Link-time optimization), +disco (randomize function order), +mutate (constants mutator), and others |
| optout "target" "h1, h2, ..." | OBJECT | OBJECT | Do not allow redirect or attachs hooks hook1, hook2, etc. (or hooks that call them) in target function |
| pack $VAR "template" ... | Marshal "string" arguments into $VAR with types specified in template. See Pack Reference. | ||
| patch "symbol" $VAR | OBJECT | OBJECT | Patch "symbol" within COFF/PIC with contents of $VAR |
| pop $VAR | BYTES | Pop content from stack and store in $VAR | |
| preplen | BYTES | BYTES | Prepend length (of content) to the content on the stack Length is a 4-byte integer in arch-native byte order. |
| prepsum | BYTES | BYTES | Calculate and prepend Adler32 checksum to content on the stack Checksum is a 4-byte integer in arch-native byte order. |
| preserve "target" "f1, f2, ..." | OBJECT | OBJECT | Prevent attach and redirect hooks on MODULE$Function or target within func1, func2, etc. |
| protect "func1, func2, etc." | OBJECT | OBJECT | Prevent all attach and redirect hooks within func1, func2, etc. |
| push $VAR | BYTES | Push $var onto stack | |
| rc4 $VAR | BYTES | BYTES | RC4 encrypt content on stack with $VAR as key |
| redirect "function" "hook" | OBJECT | OBJECT | Rewrite calls and references to function() to go through hook(). Preserves function() in hook(). |
| remap "old" "new" | OBJECT | OBJECT | Rename a symbol in the current COFF. (Use ./coffparse to see symbol names) |
| resolve "%var" | Resolves and updates comma-separated partial file paths in %var to full-paths relative to current .spec file location | ||
| rule "name" |
OBJECT | OBJECT | Configure Yara rule for object on stack. Full options are: rule "name" [maxSigs] [minAgree] [minSigLength-maxSigLength] ["func1, func2"]. The last parameter is a list of functions to generate signatures from. |
| run "foo.spec" ... | Run another .spec, using the same target, $VARs, and stack as the current script. Accepts positional arguments, passed as %1, %2, etc. | ||
| set "%var" "value" | Sets %var to value in the local scope (e.g., visible to the current running label context only) | ||
| setg "%var" "value" | Sets %var to value in the global scope (e.g., accessible globally through this linking session) | ||
| xor $VAR | BYTES | BYTES | Mask content on stack using $VAR as key |
Pack Reference
pack is Crystal Palace's command to marshal arguments into a byte array $VARIABLE. The syntax is:
pack $VARIABLE "template" arg1 arg2 arg3
Numerical and multi-byte ('Z') characters are packed in little-end byte order.
Here is the template reference:
| Template | Argument | Type | Size (b) | Notes |
|---|---|---|---|---|
| a | "string" | UTF-8 string | var | |
| b | number | byte | 1 | |
| h | "hex-pair string" | byte string | var | |
| i | number | int | 4 | |
| l | number | long | 8 | |
| p | number | pointer | 4, 8 | size is arch dependent |
| s | number | short | 2 | |
| v | $VAR | byte string | var | |
| x | No arg | NULL byte! | 1 | |
| w | "string" | UTF-16LE string | var | |
| z | "string" | UTF8 string | var | string is null-terminated |
| Z | "string" | UTF16-LE string | var | string is null-terminated |
| @4, @8, @n | No arg | NULL byte(s) | var | Align packed string to 4, 8, or architecture's natural boundary bytes. |
| #t | var | int | var | Process template t and prepend 4-byte length to it |
Java API
Use the following Java API to apply a .spec file from a Java program.