I started by looking at the bypass address used in Metasploit’s English XPsp2 attack over the MS08-067 attack in acgeneral.dll. The code looks like this:
[acgeneral.dll]The function is setting up the arguments to NTSeteInformationProcess, which are:
.text:6F8916E2 push 4
.text:6F8916E4 lea eax, [ebp+arg_0]
.text:6F8916E7 push eax
.text:6F8916E8 push 22h
.text:6F8916EA push 0FFFFFFFFh
.text:6F8916EC mov [ebp+arg_0], 2
.text:6F8916F3 call ds:__imp__NtSetInformationProcess@16 ;NtSetInformationProcess(x,x,x,x)
[ntdll.dll]Here is the code for the SetInformationProcess call:
0x4 (Length of the arguments field)
*ptr args (Pointer to the arguments for the ProcessInformationClass, in this case “ExecuteFlags”)
0x22h (ProcessInformationClass, with 0x22 meaning “ProcessExecuteFlags”)
0xFFFFFFFF (Handle, with FFFFFFFF meaning “This Thread”)
[ntdll.dll]7FFE0300 is a pointer to a data structure that contains the address of the KiFastSystemCall (syscall) function. 0E4 is the offset in the System Service Dispatch Table (SSDT) which contains the address for the system call handler for NtSetInformationProcess calls. The SSDT is in kernel land, which means you need to feed the call to Ring0. For completeness, here is the code that ntdll.dll uses to call SSDT entries:
.text:7C90E62D mov eax, 0E4h ; NtSetInformationProcess
.text:7C90E632 mov edx, 7FFE0300h
.text:7C90E637 call dword ptr [edx]
.text:7C90E639 retn 10h
[ntdll.dll]By definition, EDX holds a pointer to the arguments to syscalls, in this case ESP, but it doesn’t have to be, the address just needs to be in EDX when the sysenter call is made.
.text:7C90EB8B mov edx, esp
So at this point, I know that from userland, one major way to turn off DEP ends up with a call to the SSDT at offset 0xe4h, with the “ProcessExecuteFlags” opnum. Now I needed to find a description of these flags; which I found in, of all places, the source code for Chrome. Here is their enumeration for ExecuteFlags:
const int MEM_EXECUTE_OPTION_ENABLE = 1;So my idea was this…if I can trap the SSDT call to NtSetInformationProcess, then I should be able to watch for calls to ProcessExecuteFlags, check the ExecuteFlags field and then call them out in an attached debugger (or a userland app that grabs DbgPrint calls). My end hope was that we could use this at some of our test points to try and catch exploits that used the syscall method (either through DLL or through custom stack creation and passing control to NtSetInformation process in ntdll, or if they are mighty clever directly calling the KiFastSystemCall function directly, you’d need control of EDX, or have it point to a place you can control) to bypass DEP.
const int MEM_EXECUTE_OPTION_DISABLE = 2;
const int MEM_EXECUTE_OPTION_ATL7_THUNK_EMULATION = 4;
const int MEM_EXECUTE_OPTION_PERMANENT = 8;
So I wrote a hook into the SSDT that would call a function of my choosing when the NtSetInformationProcess call was made. For the moment, all the hook does is check to see if the call is a ProcessExecuteFlags call (0x22) and then if the flags field attempts to turn off DEP. If it matches these parameters, a DbgPrint call is made, and I check on the client side to see what process is called. Note: In kernel land it is possible, but not straightforward to get the process name, so it was just quicker this way.
The test box is a VMWare install of Windows XP at SP2. The processor I’m on doesn’t support NX, so for the moment, I just have to trust what I’m seeing and not monkey with the calls to prevent DEP from changing. While more testing is required, here is a list of things I’ve seen turn off the DEP bit:
Hit us up with some comments, information, testing thoughts etc...