Spawn Inject

Description

Spawns a new process and uses various techniques for injection.

Spawn-Inject

Overview

Spawn-Inject spawns a new host process in a suspended state and injects a payload into it before the process begins normal execution. Unlike remote-injection techniques that target an existing process, Spawn-Inject creates and controls the target process from the start, giving the operator full control over the injection window.

The payload can be sourced in three ways:

  • Pipeline — fetches shellcode from a named server pipeline (e.g. srdi_x64, http). The build identifier selects which implant configuration to embed.
  • Shellcode — injects caller-supplied raw shellcode bytes directly.
  • Migrate — fetches an sRDI payload automatically using the current agent’s build and architecture.

Architecture is detected automatically from the running agent: a 64-bit agent spawns and injects 64-bit targets; a 32-bit (WoW64) agent spawns and injects 32-bit targets. To target a 32-bit process from a 64-bit system, run the agent in 32-bit mode or pass the full path to the 32-bit executable (e.g. C:\Windows\SysWOW64\notepad.exe).

Parameters

Parameter Type Parameter Set Mandatory Default Description
FullPath string Pipeline, Specter Yes Full path to the executable to spawn (e.g. notepad.exe or C:\Windows\SysWOW64\notepad.exe).
Technique string Pipeline, Specter Yes The injection method to use. See the Techniques table below.
Pipeline string Pipeline Yes Name of the server payload pipeline to fetch shellcode from (e.g. srdi_x64, srdi_x86, http).
Build string Pipeline, Specter Yes Current agent build Implant build identifier. Determines the C2 configuration embedded in the fetched payload. Accepts the [Build] attribute for UI auto-complete.

Note: The Shellcode parameter set accepts a byte[] directly and does not require Pipeline or Build. It is not exposed in the script wrapper above but is available when calling the cmdlet directly.

Techniques

Technique Supported Architectures Description
EarlyCascadeInjection x64, x86 Abuses the Windows shim engine (g_pfnSE_DllLoaded / g_ShimsEnabled) in ntdll.dll to execute the payload during the very first DLL-load event in the suspended process — before EDR hooks have had a chance to initialize. See Technique Detail below.

Technique Detail

EarlyCascadeInjection

The technique exploits the Windows application compatibility shim engine callback registered in ntdll.dll. When a process loads its first DLL, ntdll fires the function pointer stored in g_pfnSE_DllLoaded if g_ShimsEnabled is non-zero. By planting a stub pointer here before the thread resumes, the payload executes at the earliest possible point in process initialization.

Execution sequence:

  1. Spawn the target process suspended via CreateProcessA(CREATE_SUSPENDED).
  2. Dynamically resolve g_ShimsEnabled and g_pfnSE_DllLoaded inside the in-process ntdll image using one of two strategies:
    • Strategy A (preferred): Disassemble the body of the exported LdrSetDllManifestProber function and extract the .data and .mrdata write addresses directly.
    • Strategy B (fallback): Scan the .text section for the cmp byte ptr [rip+disp], 0 / REX MOV / SharedUserData→Cookie access pattern.
  3. Allocate RWX regions in the target for the cascade stub and payload.
  4. Build a position-independent cascade stub:
    • x64: Disables g_ShimsEnabled, then calls NtQueueApcThread(-2, payload, context, 0) to queue the payload as an APC against the current thread.
    • x86: Same logic using 32-bit registers and the stdcall APC calling convention.
  5. Prepend a short trampoline (MOV RAX, stubAddr; JMP RAX) before the stub so g_pfnSE_DllLoaded can reach it regardless of encoding.
  6. Bypass Control Flow Guard (CFG):
    • x64: Overwrite guard_check_icall_fptr in the Load Config with a RET byte found in LdrSetDllManifestProber, and redirect guard_dispatch_icall_fptr to the trampoline.
    • x86: Call SetProcessValidCallTargets to register the stub as a valid indirect call destination.
  7. Write the patched stub and payload bytes to the remote process via WriteProcessMemory.
  8. Enable the shim engine in the target: WriteProcessMemory(hProcess, g_ShimsEnabled, 1).
  9. Plant the stub address in g_pfnSE_DllLoaded:
    • Windows 11: Encode the pointer with SysEncodeFnPointer (ROR64 with SharedUserData→Cookie as key) to match RtlEncodeSystemPointer semantics.
    • Windows 10 ≤ 19041: Write the raw pointer.
  10. Resume the main thread. The first DLL load fires g_pfnSE_DllLoaded, executing the stub, which queues the payload APC and clears g_ShimsEnabled before returning cleanly.

Dependencies

  • lateral module

Operating Systems

  • Windows (x64 and x86)

Example Usage

Inject a pipeline payload into a 64-bit notepad:

load lateral;
Spawn-Inject -SpawnTarget 'notepad.exe' -Technique 'EarlyCascadeInjection' -Pipeline 'srdi_x64' -Build $Build

Inject into a 32-bit process (from a 32-bit agent):

load lateral;
Spawn-Inject -SpawnTarget 'C:\Windows\SysWOW64\notepad.exe' -Technique 'EarlyCascadeInjection' -Pipeline 'srdi_x86' -Build $Build

Example Output

On success, the cmdlet writes a single PSObject to the pipeline:

ProcessName  : notepad.exe
Architecture : x64
SpawnTarget  : notepad.exe
Technique    : EarlyCascadeInjection
Property Type Description
ProcessName string The executable name or path that was spawned.
Architecture string Architecture of the spawned process (x64 or x86).
SpawnTarget string The value passed to -SpawnTarget.
Technique string The injection technique that was used.

On failure, a terminating exception is thrown with an NTSTATUS code, for example:

CascadeInject failed with NTSTATUS 0xC0000001.

Diagnostic output written to the console during execution:

[*] g_ShimsEnabled   : 0x00007FFE89A3C210
[*] g_pfnSE_DllLoaded: 0x00007FFE89B10048
[*] Pointer encoding : encoded (Win11)
Scroll to Top