Windows 10 System Call Stub Changes
Recently I installed Windows 10 RTM and while I was digging around I happened to notice some changes to the user mode portion of the system call stub: these changes appear to break the current methods of user mode system call hooking on x86 and WOW64 (Recap: here). ## Windows 10 x86
Native functions no longer make a call to ntdll!KiFastSystemCall via the pointer at SharedUserData!SystemCallStub (0x7FFE0300), in fact SharedUserData!SystemCallStub don’t seem to point to anything anymore (This change was originally made in Windows 8, but like most people I’d rather just pretend that OS doesn’t exist).
Now the system call stub is inline with one below each native function (I’m not really sure of the reason for the change but it is now impossible to hook all system calls with a single modification).
|Windows 10 x86|
Windows 10 x64 (WOW64)
Native function no longer call FS:[0xC0], instead they call a pointer in the same way x86 used to call KiFastSystemCall.
|Windows 10 x64 (WOW64)|
Wow64SystemServiceCall is not a fixed address like SharedUserData!SystemCallStub, instead it’s the absolute address of a function within the wow64 ntdll.dll.
The code simply checks a flag in the PEB to decide if to use int 2Eh or normal system call, then as before it calls wow64cpu!CpupReturnFromSystemCallStub; however, this is now done by a pointer in the table pointed to by R15, instead of directly.
FS:[0xC0] is still usable for compatibility reasons, by it doesn’t point to Wow64SystemServiceCall, nor does it point to the old code, instead it points to some more complicated version (wow64cpu!KiFastSystemCall) which does the same thing.
|x86SwitchTo64BitMode (Pointed to by FS:[0xC0] on pre-Windows 10 systems)|
As you can see the original method was just executing a single instruction which did a far jump to wow64cpu!CpupReturnFromSimulatedCode; The new method does exactly the same thing but with more instructions.
|wow64cpu!KiFastSystemCall (Pointed to by FS:[0xC0] on Windows 10 x64)|
It’s hard to gauge exactly why the old code was replaces, but it may have something to do with the fact there is no longer any pointers to wow64cpu!CpupReturnFromSimulatedCode which can be accessed from 32-bit code, now the only way is to switch into 64-bit mode and retrieve the pointer from r15+0xF8.