I have a callgate function for Windows 7 that I use to directly call NT functions:
//Windows 7 syscall __declspec(naked) NTSTATUS __fastcall wow64 ( DWORD ecxId, char *edxArgs ) { __asm { mov eax, ecx; mov ecx, m_param; call DWORD ptr fs:[0xc0]; add esp, 0x4; retn; }; } NTSTATUS callGate ( DWORD id, ... ) { va_list valist; va_start(valist,id); return wow64(id,valist); } //Example NTClose function NTSTATUS closeHandle ( void *object ) { m_param = 0; return callGate ( 0xc, object ); }
I am trying to do the same for Windows 8.1. I updated all function call indices; however, I noticed that the actual callgate function is completely different in Windows 8.1:
This is what the actual call column (located in ntdll.dll) looks like for the ZwCreateThreadEx function
mov eax, 0xA5 //the call index xor ecx, ecx //(m_param) lea edx, dword ptr ss:[esp + 0x4] //this causes an sp-analysis failure in IDA call dword ptr fs:[0xC0] add esp, 0x4 retn 0x2C
Now here is the EXACT same NT function (ZwCreateThreadEx) on windows 8.1
mov eax, 0xB0 //the call index call dword ptr fs:[0xC0] retn 0x2C //2c/4 = 11 parameters
I tried all kinds of things to get this working on Windows 8.1, but to no avail. I canβt explain what the problem is or what is happening, all I know is that I am doing it right in Windows 7.
From the looks of the W8.1 function, I tried to come up with this single function (doesn't work):
DWORD dwebp,dwret,dwparams; //for saving stuff NTSTATUS __cdecl callGate ( DWORD id, DWORD numparams, ... ) { _asm { pop dwebp; //save ebp off stack pop dwret; //save return address pop eax; //save id pop dwparams; //save param count push dwret; //push return addy back onto stack cuz thats how windows has it JMP DWORD ptr fs:[0xc0]; //call with correct stackframe (i think) mov ecx, numparams; //store num params imul ecx, 4; //multiply numparams by sizeof(int) add esp, ecx; //add to esp ret; }; }
Any help would be greatly appreciated.