Crystal Palace Documentation

1. Overview

1.1 What is Crystal Palace?

Crystal Palace is a linker and linker script language specialized to the needs of writing position-independent DLL and COFF loaders.

The name is inspired by The Crystal Palace, a former cast-iron and glass structure built in London for the Great Exhibition of 1851. At the time, it was the world's largest building. The Crystal Palace adopted a standard size and thread for screws and demonstrated the efficiency gains from building with a standard.

Like The Crystal Palace, this project aims to solve common problems turning tradecraft ideas into position-independent capability capability loaders.

Features include:

1.2 Bespoke DLL Loaders

Many Windows offensive security tools and research POCs are compiled as Windows DLLs and rely on bespoke DLL loaders, usually packaged with the capability, to parse the DLL, set it up in memory, and pass execution to it.

The benefit of a bespoke DLL loader is to make the capability less observable to the operating system and security products. For a long time, this common practice did just that. Capabilities loaded this way were virtually invisible.

Post-2016, significant industry effort has gone into detection and mitigation ideas that target this practice. Memory injection with a DLL loader is a classic example of a former evasion, becoming the source of tells to identify weird on a compromised host AND to flag benign behavior happening from a weird context.

Similarly, much effort has gone into playing with the tells related to memory injection, finding new ways to achieve the same outcomes (without the same visibility), and pushing back on the instrumentation providing the visibility. When this happens in the public, it's a good thing, as it informs better security solutions and ideas, and takes the low hanging fruit "offense wins" off of the table.

⦿ COFF Loaders

Crystal Palace also supports loading capability written as PICOs (Crystal Palace COFF) as an alternative to DLLs. The benefits of PICOs over DLLs:

Whether a capability is written as a PICO or DLL, the goal of Tradecraft Garden (and Crystal Palace) is to explore building load and run-time memory evasion tradecraft into position-independent loaders that are separate and agnostic to the capability they are applied to.

1.3 Position-independent Code

Capability loaders are often written as position-independent code. That is, a blob of data one can load into memory, start execution from position 0, and the right things will happen.

In the distant past position-independent code was often written as hand-optimized assembly.

Today, it's more common to write code in C, compile it into some form (e.g., a DLL or a COFF), and use a program like objcopy to extract the .text section from the built file. This .text section is where the executable code lives.

Writing code this way requires a lot of special care, because the compiler and linker do not know you intend to sever the executable stuff from the linker and loader-populated function references, data, and other stuff expected by the compiler's output.

When you extract a .text section, what you have is a series of things for the CPU to do. You don't have access to any APIs, C runtime functions, or embedded data (e.g., string constants). You also don't have access to global variables.

Each of the above can be overcome with special care. Later in this document, we'll go over Crystal Palace features that can help with Position Independent Code. This document will also cover some aspects of how to write code without Crystal Palace's "magic".

1.4 Linking

The purpose of a linker is to parse compiler output (object files) and put them together to meet the expected contract of whatever loader will execute the final program. For Windows, this is usually a DLL or executable.

Crystal Palace is different. While it does combine object files and merge them into something to run, the end goal of Crystal Palace is to generate outputs that execute as position-independent code without the aid of the operating system's loader.

The Crystal Palace specification language aims to give precise control over how object files are combined, transformed (aka, used as PIC, executed from COFF), and packaged.

The expected parts of a Crystal Palace project is a bootstrap position-independent code that starts the process, one or more single-use OR persistent COFFs implementing tradecraft logic, and finally dll loading logic that loads and passes execution to a user-specified DLL. The bootstrap PIC and COFFs precisely control how the DLL is loaded and take steps to intercept and modify its runtime behavior in interesting ways.

While DLL capabilities are still popular today, Crystal Palace also supports projects that bootstrap with position-independent code, use one or more COFFs to implement tradecraft logic, etc. to pair with a capability written as a COFF. Crystal Palace has features to output merged COFFs to build these kinds of capabilities.

1.5 Specification Files

The Crystal Palace linker is driven by specification files. These files are Crystal Palace's linker script.

There is no default specification file or script. Every Crystal Palace project has a specification to describe how to assemble, transform, and link resources into a ready-to-run position-independent code blob.

The Tradecraft Garden has multiple examples of DLL and Object (COFF) loaders and Crystal Palace specification files. Each of the "Simple Loader" projects demonstrates different Crystal Palace features.

1.6 The DLLs and COFFs

Crystal Palace is agnostic to any contract between a DLL capability and any specific loader. That said, here are the DLL assumptions of the Tradecraft Garden loaders:

A C2 framework may export DLLs that (likely) do not adhere to the above assumptions. Compatibility with any specific C2 is not a goal of the Tradecraft Garden projects.

COFFs passed to Crystal Palace, as capabilities, are expected to adhere to PICO conventions.

2. Install and Build

2.1 Requirements

Crystal Palace is written in Java and requires a modern-ish Java runtime environment. OpenJDK 11 or later is likely OK.

The Tradecraft Garden examples have Makefiles for the MinGW-w64 compiler environment.

The Crystal Palace demonstration programs also build with MinGW-w64.

Crystal Palace's included scripts and the Tradecraft Garden Makefiles assume a Linux environment.

Fortunately, Windows Subsystem for Linux is an excellent host for these dependencies and workflows. Follow the setup guide to create a Crystal Garden/TCG WSL environment that meets these requirements.

While it's possible these projects are workable with other compilers and environments, no accommodation is made for these other environments. Beware.

2.2 Installation

To install Crystal Palace, extract the Crystal Palace distribution to its preferred home:

tar zxvf cpdistYYYYMMDD.tgz

That's it. There are no other steps.

2.3 Building Crystal Palace

Crystal Palace is built with Apache Ant. To build Crystal Palace, use:

ant clean ; ant

The above will produce a crystalpalace.jar file. The other needed scripts (e.g., link) are included in the source and pre-built distributions of Crystal Palace.

2.4 Building Crystal Palace Demonstration Tools

The demo/ folder of Crystal Palace includes a few C programs to aid working with the Tradecraft Garden examples.

Change to the demo/ folder.

cd demo

And, run make to build the demonstration programs:

make clean ; make

3. Usage

3.1 Command-line Use

The Crystal Palace linker is usable from the command-line via the link command (Linux) and java -jar crystalpalace.jar. Run either command with no arguments to see the latest help message:

The most typical use of Crystal Palace is:

./link [/path/to/loader.spec] [file.dll|.o] [out.bin]

This use will parse and apply the commands in loader.spec to build a position-independent code package, saved as out.bin, that loads and executes the specified Win32 DLL (or PICO COFF).

Crystal Palace will parse the specified DLL (e.g., file.dll) and use its architecture to determine which target label to call within the specification file. These will come up later. For now, target labels are commands specific to an architecture (e.g., x86, x64, etc.).

⦿ Passing other arguments

When Crystal Palace is run via the command-line interface, the DLL file is made available within the execution environment as the $DLL variable. COFF are made available within the execution environment as the $OBJECT variable. It's possible to add KEY=[value] arguments via the command-line too. These values are usable within specification files as $KEY and allow passing arguments, context, and other situation-dependent configuration information to a DLL loader build.

The syntax for passing these arguments is:

./link [/path/to/loader.spec] [file.dll] [out.bin] [KEY=value] [KEY2=value] [...]

When you pass variables to Crystal Palace via the command-line, do not prefix KEY with $. Crystal Palace will do this for you.

Crystal Palace expects that each $KEY in its execution environment is a byte[] array. Specify this on the command-line as a string of hex digits.

Crystal Palace does not have awareness of the C type of these bytes. If you use the KEY mechanism to pass a pointer or DWORD, you are responsible for specifying the bytes in the right order for the target architecture. In practice, x86 and x64 targets are little-endian byte order.

As an example:

./link loader.spec file.dll out.bin NUMBER=04030201

The above populates $NUMBER with the value of 0x01020304, assuming it's used as a DWORD from your C code.

⦿ Argument passing examples

The Tradecraft Garden has two examples that highlight the benefit of argument passing:

3.2 Demonstration Programs

Crystal Palace ships with demonstration programs in the demo/ folder.

The demonstration programs include:

run.x86.exe and run.x64.exe. These projects inject a position-independent capability loader package into memory and pass execution to it. When either program is run by itself, they will display their arguments, and KEY=value output needed by some of the Tradecraft Garden Simple Loaders.

test.x86.dll and test.x64.dll are simple Windows DLLs that show a "Hello World" message box.

test.x86.o and test.x64.o are simple PICO COFFs that show a "Hello World" message box.

The x86 and x64 variations of the run and test programs denote the architecture each was built for. Do not mix an x86 DLL with an x64 runner.

The run.exe programs are not a test environment for position-independent capability loaders. That's outside the scope of this project. Further, the test DLLs are not a stress test or simulation of things a follow-on DLL might do.

The purpose of these demonstration programs is to quickly show that something can run with a tradecraft applied to it. In this way, these programs are like the vulnerability proof-of-concept convention of "popping calc" to demonstrate successful code execution.

⦿ A demonstration of the demonstration programs

Here's a quick walk-through of using the demonstration programs with a Tradecraft Garden project:

1. Pair test.x64.dll with a DLL loader

./link /path/to/loader.spec demo/test.x64.dll out.x64.bin

2. Run out.x64.bin with run.x64.exe

demo/run.x64.exe out.x64.bin

That's it.

3.3 Java API

Java applications may embed the Crystal Palace linker via its Java API.

The Java API is the most ergonomic way to use Crystal Palace. A program that embeds this technology can standardize the $KEY arguments that are available, document them, and take care to marshal them to well-defined types with the correct byte order.

The API is relatively simple. Use the Parse static method of the LinkSpec class to parse a Crystal Palace specification file. If there's an error, this method will throw a SpecParseException with detailed information about the parsing errors. The Parse method returns a LinkSpec object.

Call run on the LinkSpec object with your capability content (DLL or COFF) and a java.util.Map argument, specifying variables as (java.lang.String)$KEY to (byte[])value. Unlike the command-line, you are responsible for specifying the $ sigil here. If there's an error during the linking process, this method will throw either a SpecParseException or a SpecPorgramException. Both of these methods have sane toString methods that provide a user-friendly representation of the error(s) and their context.

The return value of run is your ready-to-go position-independent code blob.

JavaDoc Generated API documents are available for these classes too.

⦿ Limitations

The current Java API has limitations.

When Crystal Palace specifications reference a file (e.g., load, run, etc.)--there's no API accommodation to intercept that reference and resolve it with an application-internal resource.

Also, there is no Crystal Palace API to extend the specification language with new commands specific to the embedding application.

3.4 Other Commands

The Crystal Palace distribution includes a few other utilities.

The coffparse command parses a .o file and print out information about it. This is a good way to understand how Crystal Palace sees your program.

The disassemble command disassembles the code in a .o file and prints it as plaintext.

piclink is similar to link, but it doesn't accept a COFF or DLL argument. It assembles a PIC project, based on what's in a specification file.

4. Specification Files

4.1 Walk-through

The specification file is interpreted by Crystal Palace to create a ready-to-run position-independent code from one or more COFF and DLL files.

Here's an example Package Specification file:

Comments begin with the # symbol and go to the end of the line.

Targets are written as label:. Valid targets are x86.o and x64.o for COFF. And, x86.dll and x64.dll for DLLs. x86 and x64 are valid targets if a more specific target (e.g., x86.o, x86.dll) is not defined.

The goal of targets is to support different build resources and nuances for different architectures (and capability types).

Within a target are commands. Each spec command manipulates the Crystal Palace program stack or a global variable.

The load command, for example, places the contents of bin/loader.x86.o onto the stack.

The make pic command, pops those contents off of the stack, and interprets those contents as a COFF-which is re-interpreted as position-independent code. In Crystal Palace parlance, position-independent code is a .text section extracted from the COFF that we can link follow-on objects into. These re-interpreted contents are pushed back onto the Crystal Palace stack.

The push command pushes the contents of a global variable onto the Crystal Palace stack. Here, we are pushing the contents of $DLL, which is a container for the DLL passed into Crystal Palace. The Crystal Palace API allows passing other data as $VARIABLES to a spec file for action.

The link command pops the last contents from the Crystal Palace stack, appends it to the PIC object (next on the stack), and patches a hint to find that appended content into our PIC using the specified symbol. For x64 packages, the hint is an offset to address the appended resource easily. This is made possible by relative addressing, a feature of the x64 instruction set. x86 packages require a light hack to address this same data, but it's nothing too bad.

The export command pops the position-independent code object and appended resources from the top of the stack and turns it back into a byte array. If this is the last command within a label, this byte array at the top of the stack is what's written out to a file (Crystal Palace CLI Use) or returned as a result to the Crystal Palace API. This is our ready-to-run position-independent DLL loader and resources.

The above is a relatively simple set of options, but they give us a lot. For example, with Crystal Palace, we can combine multiple PIC objects-each with their own linked resources, into one package. But, that's not all... the rest of this documentation will fill you in on the other specifics and possibilities.

4.2 Command Reference

Below is a full list of Crystal Palace spec file commands and how they impact the Crystal Palace stack. Note that any files paths are resolved relative to the current .spec file.

Command Pop Push Description
coffparse "file.txt" OBJECT OBJECT Parse object on stack and output a string representation to file.txt. 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" OBJECT OBJECT Disassemble object on stack and write output to file.txt. The disassemble will occur at export, after +options are applied, and before patched values are acted on.
export OBJECT BYTES Turn object on stack into bytes
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.
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
load "file" BYTES Load contents of file onto stack
load $VAR "file" Load contents of file into $VAR
link "section" BYTES, OBJECT OBJECT Link bytes on the stack to object on stack
make coff [+options] BYTES OBJECT Turn contents on stack into a COFF-exporter object.

Options are +optimize (Link-time optimization), +disco (randomize function order), and +mutate (code mutator)
make object [+options] BYTES OBJECT Turn contents on stack into a PICO-exporter object.

Options are +optimize (Link-time optimization), +disco (randomize function order), and +mutate (code mutator)
make pic [+options] BYTES OBJECT Turn contents on stack into PIC-exporter object.

Options are +optimize (Link-time optimization), +disco (randomize function order), +mutate (code mutator), and +gofirst (make go the first function)
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
patch "symbol" $VAR OBJECT OBJECT Patch "symbol" within COFF/PIC with contents of $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.
push $VAR BYTES Push $var onto stack
rc4 $VAR BYTES BYTES RC4 encrypt content on stack with $VAR as key
reladdr "_symbol" OBJECT OBJECT (x86 PIC only) Allow linker to resolve _symbol with a partial pointer.
remap "old" "new" OBJECT OBJECT Rename a symbol in the current COFF. (Use ./coffparse to see symbol names)
run "foo.spec" Run another .spec, using the same target, $VARs, and stack as the current script.
xor $VAR BYTES BYTES Mask content on stack using $VAR as key

⦿ Binary Transformation Options

Crystal Palace's make coff, make pic, make pic64, and make object commands support several binary transformations. These are features that disassemble your program, transform it in some way, and put it back together into something that (usually) works.

The tools:

+optimize is link-time optimization. This transform walks your program, finds function calls (and other references to the function), and cuts unused functions from your program. This is a great tool if you're reusing a library of headers between projects and want to get rid of the stuff the current program doesn't need.

+disco is function disco! This feature randomizes the order of functions in your program. If it's used with make pic or make pic64, the first function is not randomized.

+mutate is Crystal Palace's code mutator. This feature replaces certain instructions with one or more instructions that do the same thing. This mutator breaks up constants, stack strings, and introduces noise to make program code resilient to some content signature techniques. This transform will increase your eXecutable code size 20-90%.

+gofirst makes sure go() function is at position 0 of your PIC.

You may specify one or more of these options with the make command. The order doesn't matter.

To understand how these transform affect your program, use disassemble "out.txt". This command disassembles a PIC or PICO on the program stack and writes the output to out.txt (or another file you specify).

⦿ Descriptive Commands

Crystal Palace includes a few descriptive commands to set information about the tradecraft in a file. This information is usable from the Java API for any applications that embed this technology. These commands should run before your target labels.

Use name "Tradecraft Name" to give a descriptive short name to the tradecraft in the file.

describe "This is a description of the tradecraft" is a longer, about one sentence, description of the tradecraft.

And, author "Mr. Big" sets the author information for this tradecraft implementation.

4.3 Position-independent Code

The make pic command within a .spec file will transform a COFF into position-independent code. And there's more. But, this "there's more" requires some explanation.

A COFF file is not meant as an executable. A COFF is code generated by the compiler, data referenced by that code (e.g., string literals), and a bunch of records--called relocations--that describe the places in the executable code where outside stuff is referenced or called upon, but where in memory that outside stuff lives is currently unknown. It's the job of the linker and the operating system loader to handle these relocations. Some things the linker can handle. Others (e.g., calls to exported functions in other libraries) normally require the help of the operating system loader.

At its simplest, the make pic command extracts the .text (your code) and .rdata (string constants) sections from a COFF and appends them together. Crystal Palace will, on its own, attempt to resolve a bunch of those relocations for you and report as errors the relocations it can't resolve.

For x64, the linker can do a lot without knowing anything about the execution environment of the final program. The x64 instruction set allows referencing data relative to the current executing instruction. In practice, this means relocations referencing appended data (e.g., the link command) just work. References to the .rdata section (where your strings live) will just work too. And, small things, like referencing a function pointer within your .text section works as well--because Crystal Palace handles these relocations too.

For x86, things get messy. The x86 instruction set does not allow referencing data relative to the current execution instruction. This means attempts to reference certain symbols (e.g., a pointer for a function) won't work. Crystal Palace has the option to resolve these symbol relocations with partial pointers. But, this means at runtime some sort of special care is needed to turn these partial pointers into full pointers.

Crystal Palace has several PIC development ergonomic features. They're opt-in, but they solve a lot of problems.

⦿ Pointer Fixing (x86)

The fixptrs command opts x86 PIC into Crystal Palace's pointer fixing feature. This feature walks your program, finds any data references, and dynamically rewrites the program to create a full pointer. This is made possible by a _caller helper function that you provide. The _caller function is responsible for returning its return address. Every example in the Tradecraft Garden opts into this feature. The fixptrs feature also works with references to .rdata--giving you the use of strings in x86 PIC programs. And, pointers to local functions work too.

Without fixptrs, you will need to calculate the full address for any linked symbols on x86. This involves adding the return address from caller, the partial pointer to your data, and an offset to account for the distance between the caller() return address and the end of the assembly instruction loading the data. This is what that looks like:

A common Tradecraft Garden convention is to reference the address of go() as the beginning of the x86 position-independent code in memory. Crystal Palace requires permission to populate symbols like this with a partial pointer (Crystal Palace assumes implicit permission to use partial pointers for link'd data). Use reladdr "symbol" to give Crystal Palace permission to populate symbols with partial pointers. Again, with fixptrs you don't have to worry about any of this stuff. It'll just work.

Without fixptrs you will not have access to "string" constants in x86 PIC. In these situations, use a stack string (e.g., char foo[] { 'b', 'a', 'r', 0 };) to push a string constant onto the stack as you need it.

The end lesson: you're better off with fixptrs.

⦿ Resolving Win32 APIs

Position-independnet code, initially, has no access to or idea about the Win32 API. A common strategy to find the Win32 API is to walk the export address table of modules loaded in memory and compare their exported function string hashes with a list of hashes in the PIC program. This is the method most Tradecraft Garden examples use. And, Crystal Palace has tools to help with this.

Use dfr "resolver" "ror13" to enable Dynamic Function Resolution (DFR) with the ror13 method. ror13 here is the hashing algorithm and call contract for the resolver. When DFR is setup this way, Crystal Palace will walk your PIC program (x86 and x64), find references to MODULE$Function, calculate the ror13 hash of MODULE, and the ror13 hash of Function, and insert code to call your resolver with these values as arguments. Most Tradecraft Garden PIC programs use this convention.

The variant of this is dfr "resolver" "strings" which inserts code to push MODULE and Function strings onto the stack and call your resolver with pointer arguments to each. This is handy for situations where GetProcAddress and GetModuleHandle are known before your PIC is run. Simple Loader (Pointer Patching) demonstrates this variant.

The exception to the MODULE$Function convention is GetProcAddress and LoadLibraryA. Crystal Palace's DFR will handle these without KERNEL32$ prefixed.

Crystal Palace allows multiple resolvers. Use dfr "resolver" "method" "mod1, mod2, ..." to set a DFR resolver for specific Win32 modules. This resolver will take priority over the default DFR resolver.

If your PIC may need to load libraries, consider dfr "resolver" "ror13" "KERNEL32" to bootstrap needed functions from Kernel32 and use a default resolver dfr "resolver_ext" "strings" to handle everything else. The default resolver with strings is an opportunity to load any missing libraries. Simple PIC demonstrates this.

DFR works fine with function pointers and direct calls.

You can resolve Win32 APIs without DFR. The manual way is to define constants for the function/module hashes you wish to look up, and early-on in your program--populate a struct with the function pointers your program will need. Here's what that looks like:

Tradecraft Garden's 20250910 release contains working examples of resolving Win32 APIs, handling x86 partial pointers, etc. Consult this old release if you're interested in these manual techniques.

⦿ Global Variables

Without hacks, global variables are not available in position-independent code. Crystal Palace has a tool to restore some global variables to PIC, if it's needed.

Use fixbss "getBSS" to opt into Crystal Palace's .bss restoration feature. .bss is the COFF section for uninitialized global variables.

When fixbss is setup, Crystal Palace will rewrite each .bss instruction reference to call the specified getBSS function and use its return value as the base .bss address in memory.

The getBSS function accepts one DWORD argument (the length of the .bss section) and returns a pointer to the .bss data. The getBSS function must return the same pointer each call. fixbss expects that the .bss space is initialized to zeroes and large enough to accommodate the .bss section.

The Simple PIC project demonstrates fixbss.

⦿ Avoiding Common PIC-falls

The entry point for your position-independent code is the function at the top of your C program. For compatability with Crystal Palace features (e.g., link-time optimization, function disco, and error checks), name this function go.

Don't use switch statements in your programs. These often generate a jump table that lives in read-only constants (.rdata) memory with relocations of their own. Jump tables are not supported by Crystal Palace.

Beware of compiler optimizations. You can turn these on, but... the optimizations may move functions around, insert jump tables, and make other changes that impact position-independent code negatively. Even if your PIC is OK, optimizations may not interact well with Crystal Palace's function disco, link-time optimization, and code mutation features.

If you do turn on optimizations, here are some of the GCC flags I found most helpful: -fno-jump-tables -fno-toplevel-reorder -fno-exceptions -f no-stack-protector. If needed, decorate troublesome functions with __attribute__((optimize("O0"))) to disable optimizations for that function.

SEHs are not supported by Crystal Palace. Don't use them.

Beware that your compiler may add "sneaky function calls" to your code. For example, with Microsoft's compiler, if you use too much stack space for local variables, the compiler will insert a function call to probe the next pages of the stack. If this happens, identify the compiler feature associated with the unresolved function, and use a command-line switch to turn it off.

If Crystal Palace reports a relocation error, it means your compiler generated code that references data Crystal Palace can't resolve without the aid of the operating system loader. In these situations, your best bet is to revise that code.

4.4 Crystal Palace PICOs (COFFs)

Position-independent Code Objects, aka PICOs, are a Crystal Palace convention to embed and run COFFs in a simple and flexible way. PICOs are similar to Cobalt Strike's Beacon Object Files but without the API.

PICOs are an abstraction above position-independent code with a lot of conveniences restored. You regain the ability to use strings and other constants. PICOs support initialized and uninitialized global variables. And, the PICO loader also supports dynamic function resolution for referencing Win32 APIs from the COFF. This is Cobalt Strike's MODULE$function convention from Beacon Object Files. Writing PICOs targeting x86 and x64 CPUs is virtually the same.

A resource is designated as a PICO with the make object command within a .spec file. This command directs Crystal Palace to parse the object file, pre-resolve various sections for global variables and built-in strings, extract the .text section, and generate "loading directives" which are simple instructions to assist with loading and processing relocations of this amalgamation that started as a COFF.

The entry point of a PICO is the go function.

⦿ PICO Example

Here is a simple PICO example that prints "Hello World" via OutputDebugStringA.

⦿ How to run a PICO

To run a Crystal Palace PICO (COFF), include tcg.h into your code, and use a function that looks something like this:

This API gives you control over where your PICO is located in memory and whether or not the code and data are in the same contiguous memory. The default PICO entry point accepts a char * argument. But, that's just a definition. You can cast it to something else.

The IMPORTFUNCS struct is defined in tcg.h. It's used to pass GetProcAddress and LoadLibraryA pointers (or your chosen substitutes) to PICO and DLL loaders.

The IMPORTFUNCS struct provides the function pointers the DLL and PICO loading code use to resolve imported APIs.

The function pointers from IMPORTFUNCS are also mapped into COFFs loaded via pico.h as LoadLibraryA and GetProcAddress. If you pass a struct with extra pointers in it, you can bring those functions into COFFs as well. Use the import command to do this. For example, if we pass a populated WIN32FUNCS to PicoLoader:

Then import "LoadLibraryA, GetProcAddress, VirtualAlloc, VirtualFree" in the .spec file will map the LoadLibraryA function to the first entry of that struct, GetProcAddress to the second, VirtualAlloc to the third, and VirtualFree to the fourth.

4.5 Shared Libraries

Crystal Palace has a concept of shared libraries. A shared library is a .zip archive of x86 or x64 COFF objects. Use mergelib "path/to/lib.x64.zip" to merge each of the objects in the library with the current PICO/PIC/COFF on the stack.

Crystal Palace PIC (with fixptrs and dfr opted-into) and PICOs share the same conventions. This means a COFF that uses MODULE$Function for Win32 APIs, avoids global variables, etc. is suitable as a shared library for use in PIC or PICO programs.

One downside to share libraries is they may import stuff you don't need. Use the +optimize option with the make command to enable link-time optimization. This will remove functions that are not called or referenced from your final program.

The Tradecraft Garden Library (LibTCG) is Tradecraft Garden's default library. It provides functions for DLL loading, PICO running, walking the export address table, and even printf()-style debugging. LibTCG is also a good example of how to build a library. It's API is described in tcg.h. All Tradecraft Garden examples use this library.

4.6 COFF Exporter

The make coff command will turn COFF bytes on the program stack into a COFF exporter. The output of the export command, when it's reached, is a COFF file.

Crystal Palace exports COFFs to allow for situations where a .spec file assembles a capability (e.g., via merging) and that output is later paired with tradecraft via another Crystal Palace .spec file.

4.7 C Patterns

Below are several patterns to interact with data and results from the Crystal Palace specification commands above. The Tradecraft Garden has full working samples that demonstrate each of the above in context. For simplicity's sake, each of the below patterns is x64 only. The x86-compatibility steps are left out.

⦿ Appending resources

The link command creates a section within a COFF or PIC and places a resource within it. This data is then easily reachable from a C program:

The above is from Simple Loader. This C code declares a global variable, in this case a character array of some length, and places it in the my_data section of the program. The link "my_data" command within the .spec file places the resource, at the top of the Crystal Palace stack, into this section.

This pattern works with resources linked to COFF and PIC.

You can create as many of these sections for different resources as you like.

⦿ Mask, Encrypt, and calculate embeddable checksums for resources

Several specification commands are meant to transform or add information to data before you link it.

preplen prepends the length of data on the program stack to itself. Here is a C struct to interact with that length value and follow-on data:

The Simple Loader (Masking) project demonstrates preplen used with xor to unmask resources and work with an arbitrary (e.g., specified in the .spec file) length XOR mask.

The prepsum command calculates the Adler-32 checksum of the top-level data on the program stack, and prepends this value to it. Here is a C struct to interact with that data:

And, here is C code to calculate the Adler-32 checksum of a resource:

The Simple Loader (Execution Guardrails) project demonstrates the use of prepsum and rc4 to encrypt and post-decrypt validate resources.

⦿ Assign user-supplied data to global symbols

The patch "symbol" $VAR command patches the contents of $VAR into the specified symbol. This works for both PIC and COFF, but with caveats.

For COFF, declare a global variable, and initialize it to some value. Congratulations, this value is now a candidate to get updated with the patch command from a .spec file. This works on both x86 and x64. The Page Streaming Loader uses this to set a XOR key, created from the .spec file's generate command, to a random value.

You can use patch with x64 position-independent code, BUT you must declare the global variable as existing within the .text section of your code:

The above code declares two pointers, pGetModuleHandle and pGetProcAddress, as global variables. The __attribute__((section(".text"))); decorator tells the compiler to allocate these globals into the .text section (aka our executable code). The Simple Loader (Pointer Patching) example demonstrates using patch from a .spec file to set these globals.

5. Next steps

That's it for the documentation. The next step is to try some things out, modify some code, and have fun with this stuff.

As an easy next step, visit the The Amphitheater for videos on how to setup your Windows Subsystem for Linux environment and a demonstration of using Crystal Palace and building the Tradecraft Garden files.

I recommend trying to reproduce what's in the videos first. Prove to yourself that you can compile the samples, run the linker, and get the "Hello World" message box via the included demonstration programs.

A good step after this is to try and load a DLL other than the DLL that comes with Crystal Palace. Maybe something custom. Maybe something from a favorite C2.

Do note that some C2s (Cobalt Strike, for example) have a startup convention that differs from just calling DllMain((HANDLE)hDll, DLL_PROCESS_ATTACH, NULL). You will likely need to modify a Tradecraft Garden example to work with that specific convention. Fortunately, if you're interested in Cobalt Strike--you're not on your own. Daniel Duggan has written Harvesting the Tradecraft Garden parts 1 and 2. These blog posts demonstrate how to use Crystal Palace with Cobalt Strike's Beacon and post-ex DLLs.

Once you're convinced you can make these examples work with a DLL that interests you--the next fun is in studying the TCG code, modifying it to do new things, and getting familiar with what's possible.

To help with this, there are several "Simple Loaders". I encourage you to study these to get an idea of how to use the Crystal Palace linker features and do cool things you may want in your loaders: