Skip to main content

Build System Overview

Stardust uses a GNU Make-based build system that orchestrates compilation across multiple architectures and toolchains. The build process involves:
  1. Assembly compilation (NASM) for entry stubs
  2. C++ compilation (Clang) for main logic
  3. Linking with custom linker script for PIC
  4. Section extraction (objcopy) to produce raw shellcode

Makefile Targets

Primary Targets

# Build both x64 and x86 in release mode (optimized)
make
# Equivalent to: make release

Architecture-Specific Targets

# Build only x64
make x64

# Build only x86
make x86

# Build x64 with debug symbols
make x64-debug

# Build x86 with debug symbols
make x86-debug

Compiler Configuration

Toolchain Selection

Stardust uses Clang with MinGW targets for cross-platform Windows compilation:
Makefile
CCX64  := clang -target x86_64-w64-mingw32
CCX86  := clang -target i686-w64-mingw32
ASMCC  := nasm
Clang provides better C++20 support (particularly consteval) and more predictable optimization behavior compared to GCC for shellcode development.

Core Compiler Flags

Makefile
CFLAGS := -Os -nostdlib -fno-asynchronous-unwind-tables -std=c++20
CFLAGS += -fno-ident -fpack-struct=8 -falign-functions=1 -s -w -mno-sse
CFLAGS += -ffunction-sections -falign-jumps=1 -falign-labels=1
CFLAGS += -Wl,-s,--no-seh,--enable-stdcall-fixup -masm=intel -fno-exceptions
CFLAGS += -fms-extensions -fPIC -Iinclude -Wl,-Tscripts/linker.ld

Optimization Flags

FlagPurpose
-OsOptimize for size (critical for shellcode)
-ffunction-sectionsPlace each function in its own section for better dead code elimination
-falign-functions=1Minimize function alignment padding (save bytes)
-falign-jumps=1Minimize jump target alignment
-falign-labels=1Minimize label alignment

Position Independence Flags

FlagPurpose
-fPICGenerate position-independent code
-nostdlibDon’t link standard library (avoid dependencies)
-fno-asynchronous-unwind-tablesRemove unwind tables (not needed for shellcode)
-fno-identRemove compiler identification strings

Windows-Specific Flags

FlagPurpose
-fms-extensionsEnable Microsoft C extensions
-masm=intelUse Intel assembly syntax
-fpack-struct=8Pack structures to 8-byte alignment
-Wl,--enable-stdcall-fixupFix stdcall symbol mangling
-Wl,--no-sehDisable structured exception handling

Security/Cleanup Flags

FlagPurpose
-sStrip symbol table
-Wl,-sStrip symbols during linking
-wSuppress all warnings (for clean build output)
-mno-sseDisable SSE instructions (reduces complexity)
-fno-exceptionsDisable C++ exceptions

Build Modes

Release Mode

Command: make or make release Characteristics:
  • Maximum size optimization
  • No debug symbols
  • DBG_PRINTF macros compile to no-ops
  • Typical output: ~750 bytes (x64), ~670 bytes (x86)
Use case: Production payloads requiring minimal footprint
include/common.h
#if defined( DEBUG )
#define DBG_PRINTF( format, ... ) { 
    ntdll.DbgPrint( symbol<PCH>( "[DEBUG::%s::%d] " format ), 
                    symbol<PCH>( __FUNCTION__ ), 
                    __LINE__, 
                    ##__VA_ARGS__ ); 
}
#else
#define DBG_PRINTF( format, ... ) { ; }  // No-op in release
#endif

Debug Mode

Command: make debug Characteristics:
  • Adds -D DEBUG preprocessor flag
  • Includes ntdll.DbgPrint for kernel debugging
  • Resolves DbgPrint API from ntdll
  • Typical output: ~1.2KB (x64), ~1.1KB (x86)
Use case: Development, troubleshooting, and reverse engineering analysis Viewing debug output:
1

Download DebugView

Get DebugView from Sysinternals.
2

Run as Administrator

# Right-click -> Run as administrator
.\Dbgview.exe
3

Enable Capture Options

  • Check Capture -> Capture Kernel
  • Check Capture -> Capture Win32
  • Uncheck Capture -> Capture Events (reduces noise)
4

Execute Shellcode

.\stomper.x64.exe stardust.x64.bin
Debug output will appear in DebugView in real-time.
Sample debug session:
[DEBUG::start::48] oh wow look we loaded user32.dll -> 00007FFB2C5A0000
[DEBUG::start::53] running from C:\Windows\System32\svchost.exe (Pid: 4128)
[DEBUG::start::57] shellcode @ 00007FFB2C8A6B50 [752 bytes]

Linker Script

The custom linker script (scripts/linker.ld) controls section layout to ensure proper PIC generation:
scripts/linker.ld
SECTIONS
{
    .text :
    {
        *( .text$A );  /* Assembly entry stubs */
        *( .text$B );  /* C++ compiled code */
        *( .rdata* );  /* Read-only data (strings, constants) */
        *( .text$C );  /* Data end marker */
    }
}

Section Purposes

.text$A

Assembly entry point with stack alignment. Contains the stardust symbol and RipStart helper.

.text$B

All C++ compiled code marked with declfn attribute. This includes instance::instance() and instance::start().

.rdata*

Read-only data including compile-time hashes and string literals used by symbol<T>().

.text$C

End-of-data marker provided by RipData(). Used for calculating shellcode size at runtime.

Custom Section Placement

Code can be placed in specific sections using the declfn macro:
include/macros.h
#define declfn __attribute__( (section( ".text$B" )) )
Usage:
src/main.cc
// This function is placed in .text$B
auto declfn instance::start( _In_ void* arg ) -> void {
    // Your shellcode logic
}

Build Process Deep Dive

Step 1: Assembly Compilation

Makefile
nasm64:
	@ $(ASMCC) -f win64 src/asm/entry.x64.asm -o bin/obj/entry.x64.obj
	@ $(ASMCC) -f win64 src/asm/utils.x64.asm -o bin/obj/utils.x64.obj

nasm86:
	@ $(ASMCC) -f win32 src/asm/entry.x86.asm -o bin/obj/entry.x86.obj
	@ $(ASMCC) -f win32 src/asm/utils.x86.asm -o bin/obj/utils.x86.obj
NASM generates object files for:
  • entry.*.asm: Entry point with stack alignment
  • utils.*.asm: Position calculation helpers (RipStart, RipData)
Key assembly features:
src/asm/entry.x64.asm
RipStart:
    call RipPtr  ; Push return address to stack
ret

RipPtr:
    mov rax, [rsp]  ; Get return address (our current position)
    sub rax, 0x1b   ; Calculate shellcode base
ret

Step 2: C++ Compilation

Makefile
%.x64.obj: %.cc
	@ echo "-> compiling $< to $(notdir $@)"
	@ $(CCX64) -o bin/obj/$(notdir $@) -c $< $(CFLAGS)
Each .cc file is compiled to an object file with all optimization flags applied.

Step 3: Linking

Makefile
x64: nasm64 $(OBJ64)
	@ echo "compiling x64 project"
	@ $(CCX64) bin/obj/*.x64.obj -o bin/$(NAME).x64.exe $(CFLAGS)
All object files are linked together using the custom linker script. The warning:
/usr/bin/x86_64-w64-mingw32-ld: bin/stardust.x64.exe:.text: section below image base
This warning is expected and confirms the .text section is not tied to a specific base address (PIC requirement).

Step 4: Section Extraction

Makefile
@ objcopy --dump-section .text=bin/$(NAME).x64.bin bin/$(NAME).x64.exe
@ rm bin/$(NAME).x64.exe
objcopy extracts only the .text section, producing a raw binary file containing pure shellcode with no PE headers or metadata.

Output Files

Directory Structure

bin/
├── obj/                    # Intermediate object files
│   ├── entry.x64.obj
│   ├── entry.x86.obj
│   ├── main.x64.obj
│   ├── main.x86.obj
│   ├── resolve.x64.obj
│   ├── resolve.x86.obj
│   ├── utils.x64.obj
│   └── utils.x86.obj
├── stardust.x64.bin        # Final x64 shellcode (752 bytes)
└── stardust.x86.bin        # Final x86 shellcode (672 bytes)

Binary Analysis

Inspect with hexdump:
hexdump -C bin/stardust.x64.bin | head -20
Expected header (x64):
00000000  56 48 89 e6 48 83 e4 f0  48 83 ec 20 e8 ... |VH..H...H.. ...|
  • 56: push rsi (entry stub)
  • 48 89 e6: mov rsi, rsp
  • 48 83 e4 f0: and rsp, 0xFFFFFFFFFFFFFFF0 (stack alignment)
Check size:
wc -c bin/stardust.x64.bin

Customizing the Build

Adding Source Files

The Makefile automatically compiles all .cc files in src/:
Makefile
SRC := $(wildcard src/*.cc)
OBJ64 := $(SRC:%.cc=%.x64.obj)
OBJ86 := $(SRC:%.cc=%.x86.obj)
To add new functionality:
  1. Create src/mycode.cc
  2. Run make (automatically detected)

Adjusting Optimization

For smaller binaries:
CFLAGS := -Oz  # More aggressive size optimization (Clang only)
For debugging compiler issues:
CFLAGS := -O0 -g  # No optimization, include debug symbols

Enabling Additional Warnings

CFLAGS += -Wall -Wextra -Wpedantic

Troubleshooting

Cause: The consteval function is not being evaluated at compile-time.Solution:
  1. Ensure you’re using Clang (not GCC)
  2. Verify C++20 is enabled: -std=c++20
  3. Check that arguments to expr::hash_string are compile-time constants:
// Correct: string literal is constexpr
auto hash = expr::hash_string( "ntdll.dll" );

// Incorrect: runtime variable
const char* name = "ntdll.dll";
auto hash = expr::hash_string( name );  // ERROR
Causes:
  1. Debug mode enabled: Check if -D DEBUG is in CFLAGS
  2. Unused code not eliminated: Ensure -ffunction-sections is set
  3. Large string literals: Use symbol<T>() for all strings
Debug:
# Check section sizes
objdump -h bin/stardust.x64.exe

# Disassemble to find bloat
objdump -d -M intel bin/stardust.x64.exe | less
Cause: C++ name mangling prevents assembly from finding C++ functions.Solution:Ensure functions called from assembly use extern "C":
src/main.cc
extern "C" auto declfn entry( _In_ void* args ) -> void {
    stardust::instance().start( args );
}
Cause: Makefile is trying to link Windows libraries (not needed for shellcode).Solution:Verify -nostdlib is in CFLAGS and no -l flags are specified:
# Correct
CFLAGS := -Os -nostdlib ...

# Incorrect
CFLAGS := -Os -lkernel32 -luser32  # Don't link libraries

Advanced Techniques

Analyzing Generated Assembly

Review the assembly output to verify optimization:
# Disassemble object file
objdump -d -M intel bin/obj/main.x64.obj

# Check symbol table
nm bin/obj/main.x64.obj

# View section headers
objdump -h bin/obj/main.x64.obj

Profiling Shellcode Size

Track size changes across builds:
#!/bin/bash
echo "Build,x64,x86" > sizes.csv
for commit in $(git rev-list HEAD); do
    git checkout $commit
    make clean && make
    x64=$(wc -c < bin/stardust.x64.bin)
    x86=$(wc -c < bin/stardust.x86.bin)
    echo "$commit,$x64,$x86" >> sizes.csv
done

Cross-Compilation from macOS

Install LLVM and MinGW:
brew install llvm mingw-w64

# Update Makefile paths
CCX64 := /usr/local/opt/llvm/bin/clang -target x86_64-w64-mingw32
CCX86 := /usr/local/opt/llvm/bin/clang -target i686-w64-mingw32

Next Steps

API Reference

Explore available functions and macros

Examples

See real-world shellcode implementations

Advanced Topics

Position calculation, string handling, and more

Core Concepts

Understand the Stardust architecture

Build docs developers (and LLMs) love