Difficulty: Advanced

Module 10: Full Chain & Extending Stardust

Putting it all together, and building on top of the template.

The Big Picture

You've now studied every major subsystem of Stardust individually. This final module connects them into a complete execution chain, shows you how to extend the template with new capabilities, and provides a comprehensive comparison with AceLdr.

Complete Execution Chain

From source code to running implant, Stardust's lifecycle has four phases:

Stardust: 4-Phase Execution Chain

Phase 1: Build

C++ Source
MinGW Compiler
Linker Script
(.text$A, $B, .rdata*, $C)
objcopy
stardust.bin

Phase 2: Injection (Loader-Side)

LoadLibraryExA
DONT_RESOLVE_DLL_REFERENCES
Find .text section
VirtualProtect RW
memcpy shellcode
VirtualProtect RX
Call entry

(Module stomping shown here; any injection technique works)

Phase 3: Initialization (Inside Stardust)

RipStart
(.text$A, byte 0)
start()
PEB Walk
resolve::module()
RESOLVE_IMPORT
ntdll, kernel32, ...
APIs Ready

Phase 4: Implant Logic

Your Code Here
Call resolved APIs
Use symbol<T> for strings
Implant running

How to Extend Stardust

Stardust is designed as a template, not a finished product. Here's how to add new capabilities.

Adding New API Declarations

To call a new Windows API, you need two things in common.h:

C++// Step 1: Add a D_API declaration to your API struct
// D_API defines the function pointer type and its DJB2 hash
// Example: adding WSAStartup from ws2_32.dll

// In the ws2_32 API struct:
struct ws2_32_apis {
    D_API( void*, base );                    // Index 0: module base
    D_API( int, WSAStartup );               // Index 1: function pointer
    D_API( SOCKET, WSASocketW );            // Index 2: function pointer
    D_API( int, connect );                  // Index 3: function pointer
};

// Step 2: Add the RESOLVE_TYPE for the module hash
// This associates the struct with the DJB2 hash of "ws2_32.dll"
RESOLVE_TYPE( ws2_32_apis, H_MODULE_WS2_32 );

Using New APIs in start()

Once declared, resolve and call the APIs in the start() function:

C++// In start() - resolve all ws2_32 APIs in one call
ws2_32_apis ws2;
RESOLVE_IMPORT( ws2, H_MODULE_WS2_32 );

// Now call them like normal function pointers
WSADATA wsaData;
ws2.WSAStartup( MAKEWORD(2, 2), &wsaData );

SOCKET sock = ws2.WSASocketW(
    AF_INET, SOCK_STREAM, IPPROTO_TCP,
    NULL, 0, 0
);

// Use symbol<T> for any string data you need
auto target = G_SYM( target_host );  // position-independent string access

Adding a New Module (DLL)

To resolve APIs from a DLL that Stardust doesn't already use (e.g., ws2_32.dll for networking):

  1. Add the module hash: Define H_MODULE_WS2_32 as the DJB2 hash of the string "ws2_32.dll" in your hash constants.
  2. Create the API struct: Define a struct with D_API entries for each function you need (as shown above).
  3. Add RESOLVE_TYPE: Associate the struct with the module hash.
  4. Resolve in start(): Call RESOLVE_IMPORT with your struct and module hash.

Remember the Rules

Every string you use must go through symbol<T> or G_SYM for position-independent access. Every API call must go through the resolution system. No direct string literals, no import table — these are the constraints of PIC shellcode.

AceLdr vs Stardust: Final Comparison

FeatureAceLdrStardust
Purpose Cobalt Strike UDRL (loads Beacon DLL reflectively) Standalone implant template (shellcode framework)
Language C with assembly Modern C++ with assembly
Compiler MinGW toolchain MinGW toolchain
Hash Algorithm DJB2 DJB2
PE in Memory Yes (loads Beacon DLL) No (pure shellcode, no PE)
Sleep Evasion Yes (FOLIAGE sleep mask) No (template only, no sleep loop)
Return Address Spoofing Yes (JMP RBX gadget) No
Heap Redirection Yes (private heap + hooks) No
x86 Support No (x64 only) No (x64 only)
Test Harness Cobalt Strike integration stomper.cc (module stomping demo)
Base Size (x64) ~8–12 KB (loader + hooks + sleep chain) ~2–4 KB (minimal template)

The Key Difference

AceLdr is a complete loader with built-in evasion (sleep masking, heap redirection, return address spoofing). Stardust is a minimal template — it provides the scaffolding (PIC, API resolution, section layout) and expects you to build your implant logic on top. Stardust doesn't include sleep evasion, heap redirection, or return address spoofing because those are features you would add yourself based on your operational needs.

References & Further Study

Project Links

Related Projects

Topics for Further Study

Final Knowledge Check

Q1: What is the correct initialization order inside Stardust after RipStart executes?

Correct! RipStart calls start(), which then walks the PEB via resolve::module() to find DLL base addresses, uses RESOLVE_IMPORT to fill in function pointers, and finally runs the implant logic with the resolved APIs.

Q2: To add a new API from a new DLL, which files/locations need changes?

Correct! You define the API struct with D_API entries and associate it with a module hash via RESOLVE_TYPE in common.h. Then in start(), you call RESOLVE_IMPORT to fill in the function pointers and use them in your implant logic.

Q3: Which of the following does Stardust NOT include, compared to AceLdr?

Correct! AceLdr includes sleep evasion (FOLIAGE), heap redirection (private heap + hooks), and return address spoofing (JMP RBX gadget) as built-in features. Stardust is a minimal template that provides PIC scaffolding, API resolution, and section layout, but expects you to add evasion features yourself based on your needs.

Q4: Approximately how large is the base Stardust x64 shellcode (before adding custom logic)?

Correct! Stardust's minimal template compiles to approximately 2-4 KB of shellcode. This is much smaller than AceLdr (~8-12 KB) because Stardust doesn't include sleep evasion, heap redirection, or return address spoofing. The small size makes it practical to embed and inject.

Course Complete!

You've completed all 10 modules of the Stardust Deep Dive.

You now understand: position-independent code, compile-time hashing with DJB2, PEB walking and API resolution, the symbol<T> template for string access, linker scripts and section layout, module stomping as an injection technique, and how to extend the template with new capabilities.

Go build something.