Monday, May 4, 2015

How 32-bit applications make system calls in 64-bit Windows

First, I'll describe how 32-bit programs make system calls in 32-bit Windows, then I'll describe how it runs in the WOW64 environment and make system calls in 64-bit Windows.

In 32-bit windows:

Executable loads kernel32.dll and ntdll.dll 
Calling the win32 API, CreateFile, ends up calling kernel32.dll!CreateFileW


kernel32.dll!CreateFileW ends up calling ntdll.dll!ZwCreateFile
ntdll.dll!ZwCreateFile moves the system call number (0x42 for ZwCreateFile) into EAX, and...

...executes the "SYSENTER" instruction, which makes the transition into the Windows kernel.

For 32-bit programs on 64-bit Windows:

Upon starting the program:
CommandLine: "C:\Users\admin\Documents\Visual Studio 2013\Projects\test\Release\test.exe"

************* Symbol Path validation summary **************
Response                         Time (ms)     Location
Deferred                                       SRV*c:\symbols*http://msdl.microsoft.com/download/symbols
Symbol search path is: SRV*c:\symbols*http://msdl.microsoft.com/download/symbols
Executable search path is:
ModLoad: 00000000`00200000 00000000`00206000   test.exe

ModLoad: 00000000`775f0000 00000000`77798000   ntdll.dll
ModLoad: 00000000`777d0000 00000000`77950000   ntdll32.dll
ModLoad: 00000000`738c0000 00000000`738ff000   C:\Windows\SYSTEM32\wow64.dll
ModLoad: 00000000`73860000 00000000`738bc000   C:\Windows\SYSTEM32\wow64win.dll
ModLoad: 00000000`73850000 00000000`73858000   C:\Windows\SYSTEM32\wow64cpu.dll
ModLoad: 00000000`773d0000 00000000`774ef000   WOW64_IMAGE_SECTION
ModLoad: 00000000`75840000 00000000`75950000   WOW64_IMAGE_SECTION
ModLoad: 00000000`773d0000 00000000`774ef000   NOT_AN_IMAGE
ModLoad: 00000000`774f0000 00000000`775ea000   NOT_AN_IMAGE
ModLoad: 00000000`75840000 00000000`75950000   C:\Windows\syswow64\kernel32.dll
ModLoad: 00000000`77330000 00000000`77377000   C:\Windows\syswow64\KERNELBASE.dll
ModLoad: 00000000`74b70000 00000000`74c5e000   C:\Windows\SysWOW64\MSVCR120.dll

Note that there are 2 "ntdll" present in the loaded modules. "ntdll32.dll" is the 32-bit ntdll from c:\windows\syswow64\, and "ntdll.dll" is the 64-bit ntdll from c:\windows\system32.

Making a win32 api call, CreateFile, in WOW64 follows this path:

- API calls kernel32!CreateFileW

- kernel32!CreateFileW calls kernelbase.dll!CreateFileW:

0:000> bp kernel32!CreateFileW
0:000> g
Breakpoint 0 hit
kernel32!CreateFileW:
7585167f ff25d4098575    jmp     dword ptr [kernel32!_imp__CreateFileW (758509d4)] ds:002b:758509d4={KERNELBASE!CreateFileW (7734c299)}

- KERNELBASE!CreateFileW calls ntdll32.dll!ZwCreateFile:


KERNELBASE!CreateFileW+0x330:
7734c5c9 8b35ac103377    mov     esi,dword ptr [KERNELBASE!_imp__NtCreateFile (773310ac)] ds:002b:773310ac={ntdll32!ZwCreateFile (777f00b0)}

- ntdll32!ZwCreateFile sets the API number (0x52 for ZwCreateFile) into EAX, and insteading of executing the "SYSENTER" instruction, it calls wow64cpu.dll!X86SwitchTo64BitMode:

ntdll32!ZwCreateFile:
777f00b0 b852000000      mov     eax,52h
0:000:x86> t
ntdll32!ZwCreateFile+0x5:
777f00b5 33c9            xor     ecx,ecx
0:000:x86> t
ntdll32!ZwCreateFile+0x7:
777f00b7 8d542404        lea     edx,[esp+4]
0:000:x86> t
ntdll32!ZwCreateFile+0xb:
777f00bb 64ff15c0000000  call    dword ptr fs:[0C0h]  fs:0053:000000c0=00000000
0:000:x86> t
wow64cpu!X86SwitchTo64BitMode:
73852320 ea1e2785733300  jmp     0033:7385271E

wow64cpu!X86SwitchTo64BitMode makes a inter-segment jump into the the segment with selector 0x30 (the 3 at the end indicates that it is a ring 3 segment, a.k.a. user-land) Before this jmp, the code is running on segment 23. This segment is running in 32-bit mode (long mode set to 0):

0: kd> dt _KGDTENTRY64 0xfffff800`00b93000+20 /b
nt!_KGDTENTRY64
   +0x000 LimitLow         : 0xffff
   +0x002 BaseLow          : 0
   +0x004 Bytes            :
      +0x000 BaseMiddle       : 0 ''
      +0x001 Flags1           : 0xfb ''
      +0x002 Flags2           : 0xcf ''
      +0x003 BaseHigh         : 0 ''
   +0x004 Bits             :
      +0x000 BaseMiddle       : 0y00000000 (0)
      +0x000 Type             : 0y11011 (0x1b)
      +0x000 Dpl              : 0y11
      +0x000 Present          : 0y1
      +0x000 LimitHigh        : 0y1111
      +0x000 System           : 0y0
      +0x000 LongMode         : 0y0
      +0x000 DefaultBig       : 0y1
      +0x000 Granularity      : 0y1
      +0x000 BaseHigh         : 0y00000000 (0)
   +0x008 BaseUpper        : 0xffff
   +0x00c MustBeZero       : 0xcff300
   +0x000 Alignment        : 0x00cffb00`0000ffff

This jmp will jump to the segment 33, which is set to long-mode, a.k.a. 64 bit mode:

0: kd> dt _KGDTENTRY64 0xfffff800`00b93000+30 /b
nt!_KGDTENTRY64
   +0x000 LimitLow         : 0
   +0x002 BaseLow          : 0
   +0x004 Bytes            :
      +0x000 BaseMiddle       : 0 ''
      +0x001 Flags1           : 0xfb ''
      +0x002 Flags2           : 0x20 ' '
      +0x003 BaseHigh         : 0 ''
   +0x004 Bits             :
      +0x000 BaseMiddle       : 0y00000000 (0)
      +0x000 Type             : 0y11011 (0x1b)
      +0x000 Dpl              : 0y11
      +0x000 Present          : 0y1
      +0x000 LimitHigh        : 0y0000
      +0x000 System           : 0y0
      +0x000 LongMode         : 0y1
      +0x000 DefaultBig       : 0y0
      +0x000 Granularity      : 0y0
      +0x000 BaseHigh         : 0y00000000 (0)
   +0x008 BaseUpper        : 0
   +0x00c MustBeZero       : 0
   +0x000 Alignment        : 0x0020fb00`00000000

This inter-segment jump is the actual transition from 32-bit mode to 64-bit mode.

After this transition, the cpu lands at address 7385271E, which is wow64cpu!CpupReturnFromSimulatedCode. It calls wow64cpu!ServiceNoTurbo:

wow64cpu!CpupReturnFromSimulatedCode:
00000000`7385271e 67448b0424      mov     r8d,dword ptr [esp] ds:00000000`0014fc9c=777f00c2
00000000`73852723 458985bc000000  mov     dword ptr [r13+0BCh],r8d ds:00000000`001bfddc=777eface
00000000`73852723 458985bc000000  mov     dword ptr [r13+0BCh],r8d ds:00000000`001bfddc=777eface
00000000`7385272a 4189a5c8000000  mov     dword ptr [r13+0C8h],esp ds:00000000`001bfde8=0014f98c
00000000`73852731 498ba42480140000 mov     rsp,qword ptr [r12+1480h] ds:00000000`7efdc480=00000000001be840
00000000`73852739 4983a4248014000000 and   qword ptr [r12+1480h],0 ds:00000000`7efdc480=00000000001be840
00000000`73852742 448bda          mov     r11d,edx
wow64cpu!TurboDispatchJumpAddressStart:
00000000`73852745 41ff24cf        jmp     qword ptr [r15+rcx*8] ds:00000000`73852450={wow64cpu!ServiceNoTurbo (00000000`73852749)}

Which calls wow64.dll!Wow64SystemServiceEx:

wow64cpu!ServiceNoTurbo+0x27:
00000000`73852770 ff150ae9ffff    call    qword ptr [wow64cpu!_imp_Wow64SystemServiceEx (00000000`73851080)] ds:00000000`73851080={wow64!Wow64SystemServiceEx (00000000`738cd0b8)}

Which calls whNtCreateFile in wow64.dll:

wow64!Wow64SystemServiceEx+0xd4:
00000000`73bad18c 41ffd4          call    r12 {wow64!whNtCreateFile (00000000`73bbc0f0)}

Which calls NtCreateFile in the 64-bit ntdll.dll:

wow64!whNtCreateFile+0x109:
00000000`73bbc1f9 ff154958feff    call    qword ptr [wow64!_imp_NtCreateFile (00000000`73ba1a48)] ds:00000000`73ba1a48={ntdll!NtCreateFile (00000000`7791e120)}

Which finally calls the "SYSCALL" instruction to transition to the kernel.

ntdll!NtCreateFile:
00000000`7791e120 4c8bd1          mov     r10,rcx
00000000`7791e123 b852000000      mov     eax,52h
00000000`7791e128 0f05            syscall
00000000`7791e12a c3              ret

Wednesday, March 4, 2015

Disabling Ctrl Alt Del in Windows 7 32-bit and Windows 8.1 32-bit

I'm surprised there is such scarce documentation on this topic, and even more surprised that I can't find a working implementation to disable Ctrl+Alt+Del. So I reverse engineered and found it out!

TLDR: Here's the executable. Note: you have to run it as the user nt authority\system. The easiest way is to run the command psexec -i -s -d DisableCtrlAltDelPatchWinlogon.exe in an elevated command prompt.

TDLR programmers: here's the code.

If you like to read about my process:

First, I read up the background information on Special Attention Sequences, which include Ctrl+Alt+Del (CAD). I found that 'When Winlogon encounters a SAS event or when a SAS is delivered to Winlogon by the GINA, Winlogon sets the state accordingly, changes to the Winlogon desktop, and calls one of the SAS processing functions of the GINA.' My first thoughts are, maybe I should reverse engineer the GINA, but then I found out the GINAs only exist for Windows XP and below. 'In Windows Vista, the GINA scheme has been replaced with a system of Credential Providers, which moves some of that functionality into WINLOGON itself...'

So now I know that Winlogon.exe is in charge of CAD, and it switches to the Winlogon desktop whenever it encounters a CAD, if I place a breakpoint at the time that it does a desktop switch, I could potentially see all the preceding functions and stack calls. So I took a look at the imports of Winlogon.exe, and sure enough, I found user32!SwitchDesktop. Its time for WinDbg!

I kernel debugged my Win 7 x86 machine and broke into the context of Winlogon.exe:

kd> !process 0 0
**** NT ACTIVE PROCESS DUMP ****

PROCESS 8520f530  SessionId: 1  Cid: 018c    Peb: 7ffd7000  ParentCid: 0158
    DirBase: 197a4000  ObjectTable: 9506ead0  HandleCount: 123.
    Image: winlogon.exe


kd> .process /i 8520f530  
You need to continue execution (press 'g' ) for the context
to be switched. When the debugger breaks in again, you will be in
the new process context.
kd> g
Break instruction exception - code 80000003 (first chance)
nt!RtlpBreakWithStatusInstruction:
82893d00 cc              int     3

Then I placed a breakpoint on SwitchDesktop:

kd> bp user32!SwitchDesktop
kd> g

Then I triggered CAD:

Breakpoint 0 hit
USER32!SwitchDesktop:
001b:77d1476b 8bff            mov     edi,edi
kd> kv
ChildEBP RetAddr  Args to Child              
0023fcec 01002147 000000b8 0103c144 002b1ff8 USER32!SwitchDesktop (FPO: [Non-Fpo])
0023fd04 01002d04 000000b8 00000001 00000000 winlogon!ResilientSwitchDesktopWithFade+0x2a (FPO: [Non-Fpo])
0023fd60 01014387 00000000 0023fd88 00000000 winlogon!CSession::SwitchDesktop+0x1c0 (FPO: [Non-Fpo])
0023fd78 010266c8 0103c378 00000000 00000000 winlogon!WlAccessibilitySwitchDesktop+0x1b (FPO: [Non-Fpo])
0023fdd8 01028f8a 0006fd98 000003ff 0103c144 winlogon!HandleSecurityOptions+0x48 (FPO: [Non-Fpo])
0023fdec 0100222f 0006fd98 77f32ba4 000a1a90 winlogon!WLGeneric_CAD_Execute+0x5e (FPO: [Non-Fpo])
0023fe04 77ed2661 0023fe64 0006fd88 000a1a90 winlogon!StateMachineWorkerCallback+0x67 (FPO: [Non-Fpo])
0023fe28 77ef0842 0023fe64 000a1af0 77dbb0c4 ntdll!TppWorkpExecuteCallback+0x10f (FPO: [Non-Fpo])
0023ff88 77e33c45 00092250 0023ffd4 77f237f5 ntdll!TppWorkerThread+0x572 (FPO: [Non-Fpo])
0023ff94 77f237f5 00092250 77dbb098 00000000 kernel32!BaseThreadInitThunk+0xe (FPO: [Non-Fpo])
0023ffd4 77f237c8 77ef03e7 00092250 00000000 ntdll!__RtlUserThreadStart+0x70 (FPO: [Non-Fpo])
0023ffec 00000000 77ef03e7 00092250 00000000 ntdll!_RtlUserThreadStart+0x1b (FPO: [Non-Fpo])

So here's a list of all the functions I should investigate. WLGeneric_CAD_Execute turns out to be the function that I was looking for, so all I had to do is the patch the starting code in that function to get it to return immediately, and CAD has been disabled!

Wednesday, February 25, 2015

Enabling SMEP in VMware Windows 8.1 guest

I have many VMs on my Windows 8.1 64-bit host. I have both Windows 8.1 32-bit and Windows 8.1 64-bit as guests. I noticed that SMEP is enabled on my 32-bit guest, but not my 64-bit one.

SMEP is not enabled.

So I tried something: I checked the box under VM settings -> Hardware -> Processors -> Disable acceleration for binary translation.

Disabling acceleration for binary translation

And SMEP now works on my 64-bit Win 8.1 guest!


SMEP enabled after disabling acceleration.