Showing posts with label RtlCreateUserStack. Show all posts
Showing posts with label RtlCreateUserStack. Show all posts

Thursday, January 17, 2013

A Real Random VirtualAlloc

In this post i will discuss one disadvantage of using the "VirtualAlloc" function to allocate memory and also suggest a trick to play around this disadvantage.

If you ever used the "VirtualAlloc" function  to allocate memory, you must have noticed that addresses returned are almost the same over instances of the same process. This is due to the "ZwAllocateVirtualMemory" function doing nothing to ensure the randomness of the base address returned, at least in Windows 7.

N.B. VirtualAlloc is just a wrap up of the "VirtualAllocEx" function which is a wrap up of the ntdll "ZwAllocateVirtualMemory" function.

To test that fact, we will create a small application that does almost nothing but calling the "ZwAllocateVirtualMemory" function and printing the base address at which memory has been allocated.
The source code looks like below.

N.B. Even though the ASLR has nothing to do with randomizing the base address of memory returned by ZwAllocateVirtualMemory, we just set the "IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE" bit field for testing purposes.

Compile the above source code and run the application several times. See image below.

As you can see in the image above, the base address is the same (0x30000) across all instances of the process and this poses a security issue.

It seems that Microsoft has taken care of this issue while allocating stack memory for threads. Now in later versions of Windows e.g. Windows 7, the "RtlCreateUserStack" function which is responsible for reserving and committing the memory for threads is calling the "NtSetInformationProcess" function with a new information class to reserve the stack memory at a random address. The new process information class is ProcessThreadStackAllocation 0x29.

Now let's see how this new information class reserves memory.

Looking at the disassembly we can see that the function checks the "StackRandomizationDisabled" flag of the "_EPROCESS" structure. We can also see the function trying to randomize some variable by using the "SystemTime" field of the "SharedUserData" page, and the "RDTSC" instruction.

The function then calls the "MiScanUserAddressSpace" and "ZwAllocateVirtualMemory" functions to reserve memory at a random base address.


Now let's try to test the "ZwSetInformationProcess" function and see if addresses returned are really random. So, we compile the code in the image below and see.
N.B. Setting the "IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE" bit field is necessary for the "StackRandomizationDisabled" bit flag of the "_EPROCESS" structure to be unset.



As you can see in the two images above, in each time we invoked the application we got a random address for the memory allocated.


Conclusion:
using the "ProcessThreadStackAllocation" class of the "ZwSetInformationProcess" function, we can guarantee a random address for memory we allocate which can be considered a security enhancement.

Code and examples for this post can be found here.

You can follow me on Twitter @waleedassar