Protecting by hooking ZwOpenProcess

Today I’m going to explain to you how you could protect your process by hooking ZwOpenProcess. It may be easy, but damn it took me sometime to figure it out! I would assume that you guys know the basics of kernel driver development and know the basics of hooking. If not, go get yourself Rootkits: Subverting the Windows Kernel orProfessional Rootkits But of course if you don’t want to spend money on them, search the internet =) Both books helped me a lot, also you may want to take a look to the Rootkit website Rootkit

ZwOpenProcess opens a handle to a desired process. With a handle you can do many things, but in this post we are going to talk about how to deny access when someone is trying to terminate your protected process. You have probably encounter such a hook since almost every anti-virus/firewall uses them to prevent malicious software from terminating them.

Let’s take a look at ZwOpenProcess:

ZwOpenProcess (
OUT PHANDLE ProcessHandle,
IN ACCESS_MASK DesiredAccess,
IN POBJECT_ATTRIBUTES ObjectAttributes,
IN PCLIENT_ID ClientId OPTIONAL);

What we want here is ClientsId since that’s a pointer to the Client ID, we could use it to check if a application is trying to get a handle to our protected process PID. Here’s a code snippet:

NTSTATUS NewZwOpenProcess(
OUT PHANDLE ProcessHandle,
IN ACCESS_MASK DesiredAccess,
IN POBJECT_ATTRIBUTES ObjectAttributes,
IN PCLIENT_ID ClientId OPTIONAL)
{
HANDLE ProcessId;

__try /*we do this to avoid crashes*/
{

ProcessId = ClientId->UniqueProcess;

}
__except(EXCEPTION_EXECUTE_HANDLER) /*we do this to avoid crashes*/
{
/*DbgPrint(“Exception”)*/
return STATUS_INVALID_PARAMETER;

}

if (ProcessId == (HANDLE)2816) /*Check if the PID matches our protected process PID*/
{

/*DbgPrint(“Access Denied!”);*/
return STATUS_ACCESS_DENIED; /*What we want, access denied.*/
}

else /*Important, if you don’t do this your system will and and crash/BSOD*/
return OldZwOpenProcess(ProcessHandle, DesiredAccess,ObjectAttributes, ClientId);
}

Here’s the result:

Free Image Hosting at www.ImageShack.us

In my example I use “firefox.exe”, as you can see I got Access Denied and also notice that Process Explorer was unable to list the loaded modules in our process.

Now try to kill your protected process, it most probably failed. Why most probably? Because your process is not invisible. There’s some tools that can still terminate your process. Also, a user can simply check if ZwOpenProcess is hooked in the SDT, and recover it, therefor your hook is dead.

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.

Advertisements