Not a long time ago I posted a article about how to hook ZwOpenProcess to protect your own process, but you may want to hook a Nt* function instead. Why? Well as you may know Zw* functions are wrappers for Nt* function , calling the Nt* API through the system service dispatcher. You may want to read this article to better understand the Native API. So like I was saying, there’s no way of calling an API without a Nt* API being executed.
In this example we are going to hook NtOpenProcess. The concept between hooking Zw* and Nt* API’s is pretty much the same, but while hooking Nt* API’s you must do something else. You need to use system call number. There’s also this macro:
#define SYSTEMSERVICE(_function)KeServiceDescriptorTable.ServiceTableBase[*(PULONG)((PUCHAR)_function+1)]
What is does is it takes a exported Zw* API and gets the Nt* equivalent. The only thing is that there’s a lot of API’s that are NOT exported. So thats why we are going to use system call numbers.
This is the site that shows you a full system call table. As you may of noticed, they change from OS to OS. Thats why we must determinate what operation system is running on the computer. I’m going to show you 2 way: PsGetVersion and NtBuildNumber.
Using PsGetVersion
ULONG majorVersion;
ULONG minorVersion;DRIVER_DATA* driverData;
// Get the operating system version
PsGetVersion( &majorVersion, &minorVersion, NULL, NULL );// Major = 4: Windows NT 4.0, Windows Me, Windows 98 or Windows 95
// Major = 5: Windows Server 2003, Windows XP or Windows 2000
// Minor = 0: Windows 2000, Windows NT 4.0 or Windows 95
// Minor = 1: Windows XP
// Minor = 2: Windows Server 2003if ( majorVersion == 5 && minorVersion == 1 )
{
DbgPrint(“Running on Windows XP”);
CallNumber = 0×07A;
}
else if ( majorVersion == 5 && minorVersion == 0 )
{
DbgPrint(“Running on Windows 2000″);
CallNumber = 0×06A;
}
else
{
DbgPrint(“Running on unknown system”);
}
Using NtBuildNumber
switch (*NtBuildNumber)
{
case 2195: //Microsoft Windows 2000
DbgPrint(“Microsoft Windows 2000 detected”);
CallNumber = 0×06A;
break;case 2600: //Microsoft Windows XP
DbgPrint(“Microsoft Windows XP detected”);
CallNumber = 0×07A;
break;default:
DbgPrint(“Unsupported OS detected”);
//As far as I know, this will never happen
return STATUS_NOT_IMPLEMENTED;
break;
}
Now that we determined what system call number to use, we must use a macro that will let use easily access the call number in the table:
#define SYSTEMSERVICE(_callnumber) KeServiceDescriptorTable->ServiceTable[_callnumber]
We are going to use this macro this way:
OldNtOpenProcess = SYSTEMSERVICE(CallNumber);
SYSTEMSERVICE(CallNumber) = NewNtOpenProcess;
You get the point.
I’m not going to explain how protecting our process work, just go to my previous post about hooking ZwOpenProcess, it’s going to be the same.
Heres a code snippet, the full source code can be downloaded at the end of the article.
switch (*NtBuildNumber)
{
case 2195: //Microsoft Windows 2000
DbgPrint(“Microsoft Windows 2000 detected”);
CallNumber = 0×06A;//NtOpenProcess Call number in Win2000
break;case 2600: //Microsoft Windows XP
DbgPrint(“Microsoft Windows XP detected”);
CallNumber = 0×07A;//NtOpenProcess Call number in WIN XP
break;default:
DbgPrint(“Unsupported OS detected”);
//As far as I know, this will never happen
return STATUS_NOT_IMPLEMENTED;
break;
}OldNtOpenProcess = SYSTEMSERVICE(CallNumber);//Our NtOpenProcess
__asm
{
push eax
mov eax, CR0
and eax, 0FFFEFFFFh
mov CR0, eax
pop eax}
SYSTEMSERVICE(CallNumber) = NewNtOpenProcess; //We change the real NtOpenProcess to the fake, the hook is activated.
__asm{
push eax
mov eax, CR0
or eax, NOT 0FFFEFFFFh
mov CR0, eax
pop eax
}
Notice that I used the CR0 to disable the memory protection, but you can also use the MDL method. I used that in my other article, just wanted to show another way of doing it.
Important!!! My example is not complete, it’s kinda of a “proof of concept” I hardcoded the PID but it shouldn’t be hard to pass the PID from the userland, even get the PID from the kernel if you want. The source code can be downloaded from the link below. If you find any errors or bug, please let me know.
Later.