In this post I will be referencing information I’ve found through reversing and through waleedassars blog article titled SizeOfStackReserve Anti-Attaching Trick. It should be noted that the following was tested on Windows 10.
The routine RtlCreateUserStack in ntoskrnl.exe is called following a call to CreateRemoteThread, CreateThread, and/or of course NtCreateThreadEx.
The RtlCreateUserStack is called far later in a call chain through various internal kernel routines, however it is used “to allocate space for the new thread’s stack in the address space of the specified process.”[1]
To prevent a process from starting, or properly preventing the initial thread from being created, we leverage the SizeOfStackReserve field in the IMAGE_OPTIONAL_HEADER, and set it while the image is resting on disk to be an exceedingly high value. If you’re interested in learning how this discovery came to be, read the blog article referenced at the top.
In order to modify the IMAGE_OPTIONAL_HEADER of the file on disk we need to call CreateFile to get a handle to an existing file, CreateFileMapping to create a file mapping object, call MapViewOfFile to map a view of the file mapping to the process’ address space, and finally get a pointer to the IMAGE_NT_HEADER of the file mapping.
I have a routine to get the IMAGE_NT_HEADER from a specified base address, it looks as follows.
PIMAGE_NT_HEADERS GetNtHeader(
void *BaseAddress
)
/*++
Routine Description:
Gets the pointer to the NT header from the specified module base address.
Arguments:
BaseAddress --> Supplies the base address of a specific module to obtain
the NT header. If the base address' initial value is null, the function
returns a null pointer therefore it is important that the caller verifies
the return value of this routine.
Return Value:
If BaseAddress is null then the routine returns
a null pointer. Otherwise it returns a pointer
to the NT header, if it is a valid PE image.
--*/
{
if( BaseAddress == 0 )
return 0;
PIMAGE_DOS_HEADER idhDosHeader = reinterpret_cast< PIMAGE_DOS_HEADER >( reinterpret_cast< unsigned char * >( BaseAddress ) );
if ( idhDosHeader->e_magic != IMAGE_DOS_SIGNATURE )
{
return 0;
}
return reinterpret_cast< PIMAGE_NT_HEADERS >( idhDosHeader->e_lfanew + reinterpret_cast< unsigned char * >( BaseAddress ) );
}
Following the logic above, after getting the pointer to the NT header I simply set the SizeOfStackReserve to 0x7FFFFFFFFFFF.
//
// Set SizeOfStackReserve to the user mode addressing limit.
//
inhNtHeader->OptionalHeader.SizeOfStackReserve = 0x7FFFFFFFFFFF;
UnmapViewOfFile and now whatever process you have modified should fail to materialize with the error pictured below.
Any comments, ideas, feedback are certainly welcome.