Tuesday, February 12, 2013

Kernel Bug #1 ProcessIoPriority

In this post i will show you the second kernel bug that i found in the  Kernel of Windows 7 SP1 (64-bit). This one is in the "nt!NtSetInformationProcess" function.

Description:
With the "ProcessInformationClass" parameter set to ProcessIoPriority 0x21, passing certain signed values e.g.  0xFFFFFFFF or 0x8000F129 in the variable pointed to by the "ProcessInformation" parameter to the ntdll "ZwSetInformationProcess" function can be abused to arbitrarily set certain bit flags of the corresponding "_EPROCESS" structure e.g. DefaultIoPriority: Pos 27, ProcessSelfDelete : Pos 30, or SetTimerResolutionLink: Pos 31.

Bug Type:
This is due to a signedness error in the "nt!NtSetInformationProcess" function.


32-Bit kernel:


64-bit kernel:

 Impact:
1) The signed value leads to bypassing the check for the "SeIncreaseBasePriorityPrivilege" privilege that is required to set the process's IO priority to HIGH.


2) The signed value leads to bypassing the check for disallowed values for the process's IO priority e.g. the bug can be abused to set the process's IO priority to CRITICAL.

3) Setting the "ProcessSelfDelete" flag, which makes the target process non-killable by conventional methods.

4) Setting the "SetTimerResolutionLink" flag, which causes a BSOD (Bug check code of 0x3B)  if we terminate the process due to a null pointer dereference bug.

Poc:

Non-Killable Process

BSOD

Code:
http://pastebin.com/QejGQXib

Status:
Reported to the vendor.

Any comments or ideas are very welcome. You can also follow me on Twitter @waleedassar

Kernel Bug #0 ThreadIoPriority

This post is the first in a series of posts that will discuss several kernel bugs that i find in Windows Kernel. This post is about a bug found in the kernel of Windows 7 SP1 (64-bit).

Description:
With the "ThreadInformationClass" parameter set to ThreadIoPriority 0x16, passing certain signed values e.g.  0xFF3FFF3C or  0xFF3FFFFC in the variable pointed to by the "ThreadInformation" parameter to the ntdll "ZwSetInformationThread" function can be abused to arbitrarily set certain bit flags of the corresponding "_ETHREAD" structure e.g. ThreadIoPriority:3, ThreadPagePriority:3, RundownFail:1, or NeedsWorkingSetAging:1.

Bug Type:
This is due to a signedness error in the "nt!NtSetInformationThread" function.

32-Bit kernel:
64-bit kernel:


Impact:
1) The signed value leads to bypassing the check for the "SeIncreaseBasePriorityPrivilege" privilege that is required to set the thread's IO priority to HIGH.

2) An unprivileged thread can use certain calculated signed values to escalate its IO priority and memory priority to maximum values e.g. Raise IO priority to CRITICAL or Page priority to 7.

3) Also, certain bit flags of the corresponding "_ETHREAD" structure can be set e.g. RundownFail and NeedsWorkingSetAging.


POC:
https://www.dropbox.com/s/x7zzx5r62h0k4uz/PriorityCheckBypass.exe

Code:
http://pastebin.com/TanNzkn9

Status:
Reported to the vendor and rejected for not being a security issue.

Any comments or ideas are very welcome. You can also follow me on Twitter @waleedassar

Monday, January 28, 2013

Wow64-Specific Anti-Debug Trick

In this post i will show you an anti-debug trick that i have recently found. The trick is specific to Wow64 processes. It rely on the fact that 32-bit debuggers e.g. OllyDbg, IDA Pro Debugger, and WinDbg_x86 don't receive debug events for certain exceptions originating from 64-bit code. One example of these exceptions is EXCEPTION_BREAKPOINT 0x80000003.

N.B. In a Wow64 process in Windows 7, its 32-bit code is executing in CS=0x23, while its 64-bit code is executing in CS=0x33.

Let's take for example the ntdll "DbgPrompt" function in Windows 7 64-bit.  I chose DbgPrompt for two reasons:
1) Calls to it end up with executing the INT 0x2D instruction, which raises an EXCEPTION_BREAKPOINT.
2) The 32-bit version of it (in 32-bit version of ntdll.dll) calls the 64-bit version of it (in 64-bit version of ntdll.dll).

N.B. The ntdll "DbgPrompt" function wraps up calls to the non-exported "DebugPrompt" function.

So, now if we call the "DbgPrompt" function from within our 32-bit code, we know that the call will end up with an EXCEPTION_BREAKPOINT raised from 64-bit mode.

The interesting thing here is that if you call the function without a debugger, the exception will be raised and its exception handler will be called. One the other hand, if a debugger is present, no exceptions are raised and the instruction following INT 2D will be executed.

Given the above knowledge, i wrote a simple demo for that Wow64-specific anti-debug trick. You can download the demo from here and its source code from here.







To bypass this trick, you have to use a 64-bit debugger where the exception will be raised and seen by the debugger.

Any comments or ideas are very welcome.

You can follow me on Twitter @waleedassar

Saturday, January 26, 2013

Wow64Log

In this post i will discuss an interesting functionality that i discovered while reversing Wow64.dll and specifically the "wow64!ProcessInit" function. Now let's take the function into assembly and see how it looks like.

The first thing the function does is open a registry key by calling the "ZwOpenKey" function with the "ObjectAttributes" parameter having the "ObjectName" member set to "REGISTRY\MACHINE\SOFTWARE\Microsoft\WOW64". So our first conclusion here is that the function tries to open the registry key "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Wow64" to retrieve specific information that may affect the Wow64 process throughout its lifetime. Usually, the key does not exist, at least on my machine (Windows 7 SP1 64-bit).


Next, if the key was successfully opened, the "Wow64GetWow64ImageOption" function is then called with the first parameter set to the opened key handle, the second parameter pointing at the wide string "Wow64ExecuteFlags", the third parameter set to 0x4 (REG_DWORD), the fourth parameter pointing at the variable that will receive the returned value, and the fifth parameter set to 0x4 (output size).

The "Wow64GetWow64ImageOption" function opens the IFEO registry key and queries the registry value whose name is the string pointed to by the second parameter and on error, it queries the same registry value under the registry key whose handle was given in the first parameter.

The extracted flags are then used to initialize three Wow64 global variables, Wow64!Wow64CommittedStackSize, Wow64!Wow64MaximumStackSize, and Wow64InfoPtr.


Whether the registry key was successfully opened or not and whether the "Wow64ExecuteFlags" value was successfully extracted or not, the "ProcessInit" function then directly jumps to the code you see in the image below.


As you can see it is trying to load a library called "Wow64Log.dll" residing in the "System32" directory by calling the ntdll "LdrLoadDll" function. Usually, this module does not exist.

N.B. Since this code is x64, the library Wow64Log.dll must be 64-bit.

Then comes some code that tries to resolve certain function addresses from Wow64Log.Dll by calling the "LdrGetProcedureAddress" function.

N.B. The kernel32 "GetProcAddress" function is just a wrap up of the ntdll "LdrGetProcedureAddress" function.

The code we see in the image above tries to resolve addresses of the "Wow64LogInitialize", "Wow64LogSystemService", "Wow64LogMessageArgList", and "Wow64LogTerminate"  functions from the Wow64Log.dll.  If any of the functions' addresses could not be resolved, the function fails and Wow64Log.dll is unloaded from the address space by calling the ntdll "LdrUnloadDll" function.

Assuming Wow64Log.dll was found in NtSystemRoot\\System32 and the above mentioned functions were found to be exported from it, we will have the global wow64.dll function pointers, "pfnWow64LogInitialize", "pfnWow64LogSystemService", "pfnWow64LogMessageArgList", and "pfnWow64LogTerminate" holding the address of the "Wow64LogInitialize", "Wow64LogSystemService", "Wow64LogMessageArgList", and "Wow64LogTerminate" functions respectively. The "Wow64LogInitialize" function will then be immediately called.

The "Wow64LogSystemService" function will be called every time the "Wow64!Wow64SystemServiceEx" function is called i.e. called with every system call being issued. This can be used for system call logging.

The "Wow64LogMessageArgList" function is called by the "Wow64!Wow64LogPrint" function to log certain events, more likely errors.

The "Wow64LogTerminate" function is called upon process termination by the "Wow64!whNtTerminateProcess" function.


The above mentioned topic can be used as a simple method for injecting 64-bit Dll's into Wow64 (32-Bit) processes by dropping Wow64Log.dll into system32.

Here is a simple Wow64Log.dll that i wrote as a demo.


You can follow me on Twitter @waleedassar

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

Monday, January 14, 2013

Call64, Bypassing Wow64 Emulation Layer

In this post i will discuss a piece of code that i wrote to ease the process of issuing 64-bit system calls without passing through the Wow64 emulation layer implemented in Wow64cpu.dll, Wow64.dll, and Wow64win.dll.


I implemented it in a function called "Call64()". Since some arguments in 64-bit system calls are 64 bits long, the "Call64()" function expects its arguments in the form of pointers to LARGE_INTEGER structures. Also, the return value is in the form of a pointer to a LARGE_INTEGER structure.


Let's take the implementation of this function step by step.

The first argument Call64 takes is a pointer to a LARGE_INTEGER structure which will receive the return value (RAX) of this system call. It is the caller's responsibility to allocate this structure. Also, it is the caller's responsibility to type-cast the value returned in it.

The second argument the function takes is the system call number or ordinal e.g. The "ZwWaitForSingleObject" function in Windows 7 has a system call number of 0x1.

This argument is later used to formulate the shellcode used to issue the 64-bit system call.


Since this function is supposed to make 64-bit system calls with different number of arguments, the function is implemented as variadic (A function with an indefinite number of arguments) with the third argument being the number of arguments the system call expects. The next arguments are all in the form of pointers to LARGE_INTEGER structures.

The function prototype is like below:

After we have looked at how the arguments look like, let's see how the function works.

First, given the number of arguments, it calculated the stack space needed and commits it using the "_alloca" function. The newly-allocated stack space is initialized to zero.

The function takes the first four arguments and stores them in RCX, RDX, R8, and R9 respectively. Extra arguments are stored on stack. Also, shadow space is taken care of.

Using the value of the 64-bit mode Code Segment selector, the function makes a Far Call to a 64-bit shellcode responsible for issuing the system call.


Suppose that we want to make a call to the "ZwClose" function using the "Call64" function, what you should do is allocate two LARGE_INTEGER structure, one to hold the value of the "Handle" parameter and the other to receive the return value (RAX). It looks like below.

Other example is the "ProcessConsoleHostProcess" class of the "ZwSetInformationProcess" function. If we trace into this call, we will find that the Wow64 emulation layer implemented in Wow64.dll prevents Wow64 processes from making such call and thus preventing them from changing their console host processes. See implementation of the "wow64!whNtSetInformationProcess" function.

The sole solution to this is to directly make the system call without passing through the Wow64 emulation layer. The call using the "Call64" function is like below.


N.B. You should bear in mind that some system calls expect pointer arguments to be aligned by 8 and this is why we should align them by using e.g. the "_aligned_malloc" function.


Source code and examples can be found here. The function has also been implemented in a Dynamic Link Library, you can find it and its header and .lib files here.

GitHub project from here.

Any comments, ideas, or bug reports are more than welcome.

You can follow me on Twitter @waleedassar