- Status
- Offline
- Joined
- Mar 3, 2026
- Messages
- 644
- Reaction score
- 457
Anyone digging into manual mapping in Rust knows the headache of porting C++ logic over to a memory-safe language without losing the raw control needed for PE manipulation. Found this implementation of a Rust-based injector—it's got the bones for a decent loader, but it's hitting some classic hurdles with WriteProcessMemory and remote execution.
The Injection Logic
This snippet handles the heavy lifting: reading the payload, allocating target memory via VirtualAllocEx, and mapping sections manually based on the NT headers. It attempts to rebase the image if the preferred base is occupied, which is standard procedure, but the shellcode execution is where things get messy for most dev builds.
Shellcode & Relocation
The shellcode is designed to run in the target process's context. It handles relocation fixing by iterating through the IMAGE_DIRECTORY_ENTRY_BASERELOC and resolves imports via LoadLibraryA and GetProcAddress.
Troubleshooting the Crash
If you're getting WriteProcessMemory errors or target crashes during redirection:
— Check SeDebugPrivilege. Even with a handle, some processes will deny write access to specific segments.
— Verify the context size. Passing LoaderContext into memory needs to be byte-perfect; misalignment will cause the shellcode to read garbage.
— AddressOfEntryPoint check. If the DLL you're mapping is packed or has weird protections, the entry point might lead to uninitialized memory.
— Nuke any Anti-Cheat (EAC/BE) if you are testing on a live game; they trap CreateRemoteThread instantly.
Anyone tested this specific Rust implementation on the latest patch? Let's discuss the crash logs below.
The Injection Logic
This snippet handles the heavy lifting: reading the payload, allocating target memory via VirtualAllocEx, and mapping sections manually based on the NT headers. It attempts to rebase the image if the preferred base is occupied, which is standard procedure, but the shellcode execution is where things get messy for most dev builds.
Code:
pub unsafe fn inject(
payload_path: &str,
wpinf: &WindowedProcessInformation,
) -> Result<InjectedModule> {
let payload_data = fs::read(payload_path)?;
let h_process = handle::open_handle(wpinf.pid())?;
let (p_dos_header, p_nt_headers) = dll::get_dll_headers(&payload_data)?;
let image_base = (*p_nt_headers).OptionalHeader.ImageBase as *mut u64 as _;
let mut p_base_alloc = VirtualAllocEx(
h_process,
image_base,
payload_data.len(),
MEM_COMMIT | MEM_RESERVE,
PAGE_EXECUTE_READWRITE,
);
if p_base_alloc.is_null() {
p_base_alloc = VirtualAllocEx(
h_process,
null_mut(),
0x1000,
MEM_COMMIT | MEM_RESERVE,
PAGE_EXECUTE_READWRITE,
);
}
for section in get_sections(p_nt_headers) {
if section.raw_data_size == 0 { continue; }
let rebase_addr = p_base_alloc.add(section.virtual_address as usize);
WriteProcessMemory(
h_process,
rebase_addr,
payload_data.as_ptr().add(section.ptr_to_raw_data as usize) as _,
section.raw_data_size,
&mut 0,
);
}
// Remote thread logic follows...
}
Shellcode & Relocation
The shellcode is designed to run in the target process's context. It handles relocation fixing by iterating through the IMAGE_DIRECTORY_ENTRY_BASERELOC and resolves imports via LoadLibraryA and GetProcAddress.
- Relocation Fixing: It calculates the delta between the allocated base and the ImageBase from the headers.
- Import Resolution: Hits the IAT to swap original thunks with real function pointers.
- TLS Callbacks: Invokes any established TLS callbacks before hitting the Entry Point.
- EntryPoint: Finally calls DllMain with DLL_PROCESS_ATTACH.
Code:
unsafe fn shellcode(ctx: &mut LoaderContext) {
let nt_headers = *ctx.nt_headers;
let opt_header = nt_headers.OptionalHeader;
let p_base: LPVOID = ctx as *mut LoaderContext as _;
let dll_main = p_base.add(opt_header.AddressOfEntryPoint as usize) as *mut _DllMain;
let location_delta: *mut u8 = (p_base as u64 - opt_header.ImageBase) as *mut _;
if !location_delta.is_null() {
let reloc_data = opt_header.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC as usize];
// Reloc logic loop here...
}
(*dll_main)(p_base as _, DLL_PROCESS_ATTACH, null_mut());
ctx.h_mod = p_base as _;
}
Troubleshooting the Crash
If you're getting WriteProcessMemory errors or target crashes during redirection:
— Check SeDebugPrivilege. Even with a handle, some processes will deny write access to specific segments.
— Verify the context size. Passing LoaderContext into memory needs to be byte-perfect; misalignment will cause the shellcode to read garbage.
— AddressOfEntryPoint check. If the DLL you're mapping is packed or has weird protections, the entry point might lead to uninitialized memory.
— Nuke any Anti-Cheat (EAC/BE) if you are testing on a live game; they trap CreateRemoteThread instantly.
Anyone tested this specific Rust implementation on the latest patch? Let's discuss the crash logs below.