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 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 DLL 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.

The goal of Tradecraft Garden (and Crystal Palace) is to explore building load and run-time memory evasion tradecraft into DLL loaders that are separate and agnostic to the capability they are applied to.

1.3 Position-independent Code

DLL 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. For example, you can rely on compiler intrinsics (e.g., functions that translate directly to CPU instructions) to make up for some of the missing C runtime. You can follow some well-tread strategy to resolve and start using the Win32 API. You can rely on tricks like declaring strings in a way, where the value is placed onto the stack, vs. living in some other now-non-existent section of the program. Things like that.

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.

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 loaders and Crystal Palace specification files. Each of the "Simple Loader" projects demonstrates different Crystal Palace features.

1.6 The DLLs

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.

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] [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.

Crystal Palace will parse the specified DLL (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. 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 its 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 DLL 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.

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 DLL 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 DLL content 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.

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, for now, are x86 and x64. The goal of targets is to support different build resources and nuances for different architectures.

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
export OBJECT BYTES Turn object on stack into PIC
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 object BYTES OBJECT Turn contents on stack into a COFF object
make pic BYTES OBJECT Turn contents on stack into PIC object
make pic64 BYTES OBJECT (x64 only) Turn contents on stack into PIC object
This PIC includes the .rdata section; you can use strings with no hackery.
patch "symbol" $VAR OBJECT OBJECT Patch "symbol" within COFF/PIC with contents of $VAR
Limited to symbols in .text or .data sections (x86/x64 COFF). Or .text only (x64 PIC)
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
run "foo.spec" BYTES Run another .spec file, using the same target, same $VARs, and push results onto stack.
xor $VAR BYTES BYTES Mask content on stack using $VAR as key

⦿ 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 .spec file will transform a COFF, on the program stack, 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 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, make pic extracts the .text section from a COFF. But, the there's more part is this: Crystal Palace will try 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 on x64. If you use make pic64, Crystal Palace will append the .rdata section to the extracted .text section and resolve any relocations referencing it. This restores your ability to use strings, but from position-independent code. And, small things, like referencing a pointer to a function within your .text section work again, because Crystal Palace handles the relocations for these too.

For x86, things get messy. The x86 instruction set does not allow referencing data relative to the current execution instruction. Instead, Crystal Palace populates these references with thunks. Basically, incomplete pointers that require the addition of a base address at runtime to get usable pointer. The Tradecraft Garden examples demonstrate the various gymnastics to make x86 references work. It's not too bad, but if you don't need x86, I wouldn't bother.

Even with the above help, writing significant functionality as position-independent code is tedious and sometimes (e.g., due to a lack of globals) stupidly difficult. This is where PICOs come to help.

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 a convention for referencing Win32 APIs from the COFF. This is Cobalt Strike's LIBRARY$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 pico.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 WIN32FUNCS struct is defined in several of the Tradecraft Garden projects. It's a struct with multiple function pointers, passed around inside of the initial position-independent code that starts each project. This struct is always a superset of the IMPORTFUNCS struct, which the DLL and PICO loading header files both use. IMPORTFUNCS is:

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 WIN32FUNCS (passed to PicoLoad) is:

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 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.

The preplen prepends the length of the top-level data on the program stack, and prepends the length to it. 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.

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: