Skip to main content

Prerequisites

Before building Stardust, ensure you have the following tools installed on your Linux system:
1

MinGW-w64 Toolchain

Cross-compilation toolchain for building Windows executables from Linux.
# Debian/Ubuntu
sudo apt install mingw-w64 clang

# Arch Linux
sudo pacman -S mingw-w64-gcc clang

# Fedora
sudo dnf install mingw64-gcc mingw32-gcc clang
2

NASM Assembler

Required for assembling the position-independent entry stubs.
# Debian/Ubuntu
sudo apt install nasm

# Arch Linux
sudo pacman -S nasm

# Fedora
sudo dnf install nasm
3

GNU Make

Build automation tool (usually pre-installed).
# Debian/Ubuntu
sudo apt install make

# Arch Linux
sudo pacman -S make
4

Binutils

Includes objcopy for extracting the .text section.
# Usually included with gcc/binutils packages
sudo apt install binutils
Stardust uses Clang as the compiler with MinGW targets, not GCC directly. This provides better C++20 support and more consistent code generation.

Building Stardust

1

Clone the Repository

git clone https://github.com/yourusername/stardust.git
cd stardust
2

Build in Release Mode

Compile the shellcode for both x64 and x86 architectures:
make
Expected output:
-> compiling src/main.cc to main.x64.obj
-> compiling src/resolve.cc to resolve.x64.obj
compiling x64 project
/usr/bin/x86_64-w64-mingw32-ld: bin/stardust.x64.exe:.text: section below image base
-> compiling src/main.cc to main.x86.obj
-> compiling src/resolve.cc to resolve.x86.obj
compiling x86 project
/usr/bin/i686-w64-mingw32-ld: bin/stardust.x86.exe:.text: section below image base
The “section below image base” warnings are expected and indicate successful PIC generation. This is intentional behavior.
3

Verify Output Files

Check that the shellcode binaries were created:
ls -lh bin/
Expected files:
drwxr-xr-x  obj/
-rw-r--r--  stardust.x64.bin  (752 bytes)
-rw-r--r--  stardust.x86.bin  (672 bytes)
These .bin files contain pure position-independent shellcode extracted from the .text section.

Testing with Stomper

Stardust includes a test harness called stomper that executes shellcode by injecting it into a legitimate Windows DLL’s code section.
1

Build the Stomper Utility

make stomper
This creates test/stomper.x64.exe and test/stomper.x86.exe.
2

Transfer Files to Windows

Copy the following to a Windows test machine:
  • bin/stardust.x64.bin (or stardust.x86.bin)
  • test/stomper.x64.exe (or stomper.x86.exe)
Never test shellcode on production systems. Use an isolated VM or dedicated testing environment.
3

Run the Test

Execute stomper with the shellcode binary as an argument:
# For 64-bit shellcode
.\stomper.x64.exe stardust.x64.bin

# For 32-bit shellcode
.\stomper.x86.exe stardust.x86.bin
Expected output:
[*] shellcode file @ 0x000001A2B3C4D5E0 [752 bytes]
[*] loaded "chakra.dll" @ 7ffb2c8a0000
[*] target code section @ 7ffb2c8a1000 [1089536 bytes]
[*] entry point @ 0x00007FFB2C8A6B50
[*] wrote shellcode into target module
[*] press enter...
4

Observe the Result

Press Enter, and you should see a MessageBox appear with:
  • Title: “caption”
  • Message: “Hello world”
This confirms the shellcode successfully:
  1. Resolved ntdll.dll and kernel32.dll from the PEB
  2. Loaded user32.dll via LoadLibraryA
  3. Resolved MessageBoxA from the export table
  4. Executed the API call
// The default shellcode implementation
auto declfn instance::start( _In_ void* arg ) -> void {
    const auto user32 = kernel32.LoadLibraryA( 
        symbol<const char*>( "user32.dll" ) 
    );

    if ( user32 ) {
        DBG_PRINTF( "oh wow look we loaded user32.dll -> %p\n", user32 );
    }

    decltype( MessageBoxA ) * msgbox = RESOLVE_API( 
        reinterpret_cast<uintptr_t>( user32 ), 
        MessageBoxA 
    );

    msgbox( nullptr, 
            symbol<const char*>( "Hello world" ), 
            symbol<const char*>( "caption" ), 
            MB_OK );
}

Debug Build (Optional)

For troubleshooting or development, build in debug mode to enable DbgPrint output:
make debug
Debug builds:
  • Include DbgPrint calls for runtime diagnostics
  • Are larger (~1.2KB vs ~750 bytes for x64)
  • Require DebugView to see output
Viewing Debug Output:
  1. Run DebugView as Administrator on Windows
  2. Enable Capture Kernel and Capture Win32
  3. Execute stomper with the debug shellcode
Sample debug output:
[DEBUG::start::48] oh wow look we loaded user32.dll -> 00007FFB2C5A0000
[DEBUG::start::53] running from C:\Windows\System32\notepad.exe (Pid: 1234)
[DEBUG::start::57] shellcode @ 00007FFB2C8A6B50 [752 bytes]

Next Steps

Customize Your Shellcode

Modify src/main.cc to implement custom payload logic

Add New APIs

Learn how to extend the API resolution system

Understand the Build System

Deep dive into compiler flags and optimizations

Explore Examples

See advanced shellcode implementations

Troubleshooting

Possible causes:
  1. Antivirus interference: Disable Windows Defender or whitelist the directory
  2. Wrong architecture: Ensure x64 stomper is used with x64 shellcode (same for x86)
  3. Missing DLL: chakra.dll might not exist on your Windows version. Edit stomper.cc to use a different DLL like kernel32.dll
Solution:
test/stomper.cc
// Replace chakra.dll with a guaranteed module
image_base = reinterpret_cast<uintptr_t>( 
    LoadLibraryExA( "kernel32.dll", nullptr, DONT_RESOLVE_DLL_REFERENCES ) 
);
Error:
undefined reference to `LoadLibraryA'
Cause: Missing linking flags or incorrect toolchain.Solution:Ensure Clang is installed and the Makefile uses the correct target:
Makefile
CCX64 := clang -target x86_64-w64-mingw32
CCX86 := clang -target i686-w64-mingw32
Cause: Corrupted shellcode or incorrect section extraction.Debug steps:
  1. Verify .bin file sizes are reasonable (500-1500 bytes)
  2. Check hex dump for obvious corruption:
    hexdump -C bin/stardust.x64.bin | head -20
    
  3. Rebuild with make clean && make

Build docs developers (and LLMs) love