00:00
00:00
Newgrounds Background Image Theme

novaruah just joined the crew!

We need you on the team, too.

Support Newgrounds and get tons of perks for just $2.99!

Create a Free Account and then..

Become a Supporter!

C++: Everything about hooking.

5,196 Views | 7 Replies
New Topic Respond to this Topic

C++: Everything about hooking. 2006-03-11 20:23:03


C++ Main!

Author: OsGB

Tutorial:

In essence there are only 2 types of hooks;

1) User Level Hooking

2) Kernel Level Hooking

of course there are so many things that fall into place between those 2 things that the remaining types of 'sub' hooks are just gravy.

Win32 API Hooking falls under User Level hooking (user level, application level, os level -- et al)
API Hijacking is the easiest to do although very complex for a newcomer

here are a few things you can do at User Level Hooking:

Window subclassing.

One of the most simplistic hooking methods is sublcassing a window, after this is done a user can do a lot of things such as modify keyboard and mouse input/output, do events when certain input is given, etc...

A HWND Proc Hook is an example of a way to subclass a windows application and grab all of the input that a user sends it (keyevents, mouse, et al)

The only thing bad about Subclassing is that you are constricted to that single application and it is therefore not a system wide at all

Proxying

You find this to be common in wrappers, basically its when a user replaces a dll with their own that has the same amount of names and exports all of the functions/symbols that the original would

Function fowarding and hooking the exports of a dll is a simple process and is something that you saw me explain earlier in my first post, a simple example of proxying code used in a GL Wrapper:

[php]
// Global Defines:
typedef void ( *glBegin_typedef) (GLenum mode); // glBegin Typedef
glBegin_typedef original_glBegin; // original_glBegin define
PHP Code:
// opengl32.cpp
void Hooked_glBegin (GLenum mode)
{
//dotheshit();
(*original_glBegin) (mode);
}

PHP Code:
// opengl32.def
// defines of DLL Exports and their Indexes are as follows:
LIBRARY opengl32
EXPORTS
...
glBegin = Hooked_glBegin @11
...

Since the opengl32.dll is loaded automatically (as a proxied dll - a wrapper) that in essence 'wraps' the render device of opengl, it will do everything you tell it to do.
as you can see in the Hooked_glBegin function it does everything you tell it to do and THEN calls back to the original function so as to not **** things up :]

proxying is one of the easier ways to hook functions and can even be system wide if done in certain modules.

Code Overwritting / Detouring

Oh this is fun! this requires asm > Code overwritting can be a very complicated and messy concept but if it works, it works good. (although its buggy and prone to error out A LOT so... its not a fun process, and its not garunteed to work since its not static like function forwarding through a lib or subclassing can be)
There are a lot of ways you can overwrite code or detour, all are very powerful, all are very 'hacky' but efficient. A simple example of code overwritting is what we used to do long ago with Bytehacking of uscript packages.

PHP Code:
if(you == hax0r)
PP.Destroy();

overwritting is as simple as bytehacking in that case where you can change Destroy to - Firealt, or == to !=, or you to him, or hax0r to l3git...

Just as there are a lot of possibilities in a simple bytehack there are also a lot of possiblities in API hooking using overwritting.

1 way of overwritting is to replace the address of the function when it is "CALL"ed

PHP Code:
; example of a call in ASM - taken straight from Engine.dll
PUSH EBX
PUSH ESI
PUSH DWORD PTR SS:[EBP+8]
CALL Engine._DllMain@12

lets take a crash course in Reverse Engineering 101:

as we can plainly see thats a call to DllMain which every dll prog needs, and since im a super leet hax0r i know what DllMain is composed of;
BOOL APIENTRY DllMain(HMODULE hDll, DWORD Reason, PVOID lpReserved)

now let me get back to what i was saying each one of the above asm instructions has an 'address' in memory
the first instruction of:
PUSH EBX is located at 0x105E189F in Engine.dll
PUSH ESI is 0x105E18A0
PUSH DWORD PTR SS:[EBP+8] is 0x105E18A1
and the call to DllMain is 0x105E18A4

now your probably wondering why is it that it was incremental from 0x105E189F + 1 =
to 0x105E18A0 + 1 =
to 0x105E18A1 + 3????? =
that makes sense right? thats just going up by 1 each time.... but whats this?
the call to DllMain is at 0x105E18A4???
why did it jump 3 entire bytes, did it **** up some how?

no it didnt heres why:

In order to call a function one must first push all of its params (registers) to the stack, params are pushed backwards (DONT EVER FORGET THIS):

so in the case of DllMain, you have 3 params:
DllMain(HMODULE hDll, DWORD Reason, PVOID lpReserved)
1) lpReserved = DWORD PTR SS:[EBP+8]
2) Reason = ESI
3) hDll = EBX

now look:

// remember backwards ->
PUSH lpReserved;
PUSH Reason;
(PUSH hDll); - [and prepare to call DllMain]
Call DllMain;

each of the above look like this in Hex:
0x53
0x56
0xFF75 0x08
0xE8 0xF796DBFF

translate that back to english:
0x(5)PUSH (3)EBX
0x(5)PUSH (6)ESI
0x(5)PUSH (FF7)DWORD PTR SS:[EBP (08)+8]
0x(E8)CALL (F796DBFF)Engine._DllMain@12

now to explain why it jumps 3 bytes from 0x105E18A1 to ( +3 = ) 0x105E18A4

0x105E18A1 = FF75 08

0xFF = 1 byte
0x75 = 1 byte
0x08 = 1 byte

1 + 1 + 1 = 3

0x105E18A1 + 3 = 0x105E18A4

makes sense now? I hope so.

Onward again to how one actually HOOKS that "CALL" of DllMain (this isnt a smart idea, but just a proof of concept, dont go trying to hook the programs entry point......)

remember how:
0xE8 0xF796DBFF
=
(F796DBFF)Engine._DllMain@12

well what if we wanted to call "MyHax0rDllMain" instead

well thats easy, we would do this:
0xE8 0xOFFSETOFOURFUNCTION


I'm your average Afro-American fetus. For example: I enjoy basketball, I'm rather good when I play too, but I'm much too busy scratching my horrific cracked skin these days.

BBS Signature

Response to C++: Everything about hooking. 2006-03-11 20:25:55


You can do this one of 2 ways, if your just hacking the dll itself with its own code (ie bytehacking) - fyi; you CAN bytehack a dll/exe, its very possible, you need to know asm.

1) Bytehacking the File: you could tell it to JMP to another area in the dll instead of Calling DllMain, of course it would crash but if you knew what you were doing it wouldnt crash you could make it do what you want.

2) Editing Memory: Remember the old md5 hacks for 2k4 that Clockwize released? Welcome back to the hell of trying to read over that source, but maybe this time you'll understand what it was doing.

it's doing exactly what i showed above^- just its doing it on the fly so it has to protect the memory and protect the registers otherwise the computer will freak out and scream "WTF ARE YOU TRYING TO DO, YOU CAN NOT VIOLATE ME WHEN I AM TRYING TO RUN A PROGRAM! OMG RAPE"

code snippets;

HMODULE hEng = GetModuleHandle("Engine.dll"); // Open Engine.dll for reading
DWORD TheSuperDuperHax0rOffset = (DWORD)GetProcAddress(hEng, "_DllMain@12"); // Our Hax0r Offset = where DllMain is in Engine.dll (0x105E18A4 - you could hard code this of course)

Now that you have the Location loaded into a Pointer you can use in your source you can VirtualProtect the next 5 bytes in memory

why 5?

0xE8 0xF796DBFF
0xE8 = 1
0xF7 = 1
0x96 = 1
0xDB = 1
0xFF = 1

1 + 1 + 1 + 1 + 1 = 5

fill all 5 bytes with NOPS:
PHP Code:
__asm nop;
__asm nop;
__asm nop;
__asm nop;
__asm nop;

Protect your registers so you dont fuck up the stack!!!
__asm pushad ; push all registers
// do what you want here:
// in our case we shall:
__asm call MyHax0rDllMain

reset the registers again!

__asm popad

TADA YOUR DONE

thats several methods of Code Overwritting and 1 example of Detouring!
/me whipes sweat off forehead

Breakpoints via Debugger

breakpoints own! ok well sorta... they are great in so many ways but not (in my opinion) for hooking
debuggers give you an easy way to make use of them

A breakpoint stops (pauses) a program for an extended amount of time to give you the user time to do whatever you wish with the memory that you broke at without ****ing up the program

There are a few drawbacks to using this approach though as debugging a prog will suspend all application threads (will ... physically pause the program)
uh not the best hax0r method...

can also be done through code, too much of a waste to explain

Altering the IAT (Import Address Table)

This is a very clean and efficient way to hook almost anything, if you saw my Unreal Engine Hook tutorial you will see an example of Import Address Table hooking.

In order to make good use of IAT hooking you need to know a good deal about the Portable Executable (PE) Windows File Format and Common Object File Format (COFF)

The most important of the 2 however is the PE File Format, the PE file format is composed of 7 sections, just like our unreal file format is composed of certain things (Header, Name Table, Imports, Exports)

the most important part of the PE File Format is ".idata" .idata is in essence the Import Table and all of the data within it. When a program/module is made it has a lot of 'dependancies' just as our hacks have dependancies in say; 'engine' and 'core' -

Each dependancy in a Win32 application is called an Import (same as uscript)

The best way to determine all of the Imports of a application is to grab information (in an infinite loop) out of .idata - one would think that scanning through all of the imports of an application would bog down the hooking process and take considerable system resources, but thats what is so lovely about IAT, every import of said win32 application is located neatly and cleanly within the Import Address Table! Because it's just that, a Table, with offsets Imports and data, each one composed of nothing more than an indirect call to an import that is 'written' into the IAT with a simple JMP

Scan through .idata, find the function (offset, thunk, et al) that you want ->
and VirtualProtect it again - initalize your typedef and fill it with all the information from what the IAT points to and TADA you just hooked a win32 API Function in the most clean and efficient manner to date (imo)

heres a code snippet for ya'll who havent looked at my source:

PHP Code:
// Globals:
typedef void (WINAPI *ProcessEvent_typedef)(class UFunction*,void*,void*);
ProcessEvent_typedef orgProcessEvent;

// IAT MAJIC
void ReDirectFunction (char* strDllName, char* strFunctionName, DWORD newFuncAddy)
{
DWORD dwBackup;
DWORD dwIndex;
DWORD dwOffset;
HMODULE hEng;
PIMAGE_DATA_DIRECTORY pDataDirectory;
PIMAGE_DOS_HEADER pDosHeader;
PDWORD pdwIAT;
PDWORD pdwINT;
PIMAGE_IMPORT_DESCRIPTOR pImportDescriptor;
PIMAGE_IMPORT_BY_NAME pImportName;
PIMAGE_OPTIONAL_HEADER pOptionalHeader;
PIMAGE_NT_HEADERS pPeHeader;
PSTR strCurrent;

hEng = GetModuleHandleA("Engine.dll");

if(!hEng) return;

pDosHeader = PIMAGE_DOS_HEADER(hEng);
dwOffset = pDosHeader->e_lfanew;
pPeHeader = PIMAGE_NT_HEADERS(long(hEng) + dwOffset);
pOptionalHeader = &pPeHeader->OptionalHeader;
pDataDirectory = pOptionalHeader->DataDirectory;
dwOffset = pDataDirectory[IMAGE_DIRECTORY_ENTRY_IMPOR
T].VirtualAddress;
pImportDescriptor = PIMAGE_IMPORT_DESCRIPTOR(long(hEng) + dwOffset);

for(dwIndex = 0; true; dwIndex++)
{
dwOffset = pImportDescriptor[dwIndex].Name;
strCurrent = PSTR(long(hEng) + dwOffset);
if(stricmp(strCurrent, strDllName) == 0) break;
}

dwOffset = pImportDescriptor[dwIndex].FirstThunk;
pdwIAT = PDWORD(long(hEng) + dwOffset);
dwOffset = pImportDescriptor[dwIndex].OriginalFirstTh
unk;
pdwINT = PDWORD(long(hEng) + dwOffset);

for(dwIndex = 0; true; dwIndex++)
{
dwOffset = pdwINT[dwIndex];
pImportName = PIMAGE_IMPORT_BY_NAME(long(hEng) + dwOffset);
strCurrent = PSTR(pImportName->Name);
if(stricmp(strCurrent, strFunctionName) == 0) break;
}

VirtualProtect(&pdwIAT[dwIndex], sizeof(DWORD), PAGE_READWRITE, &dwBackup);

orgProcessEvent = (PrEv)pdwIAT[dwIndex];

pdwIAT[dwIndex] = PtrToUlong(newFuncAddy);
VirtualProtect(&pdwIAT[dwIndex], sizeof(DWORD), dwBackup, &dwOffset);

}

called with:
ReDirectFunction("Core.dll", "?ProcessEvent@UObject@@UAEXPAVUFunction@@
PAX1@Z", (DWORD)&xProcessEvent);

:]


I'm your average Afro-American fetus. For example: I enjoy basketball, I'm rather good when I play too, but I'm much too busy scratching my horrific cracked skin these days.

BBS Signature

Response to C++: Everything about hooking. 2006-03-11 21:05:34


whats hooking

Response to C++: Everything about hooking. 2006-03-11 21:58:31


At 3/11/06 08:23 PM, dave wrote: Author: OsGB

OsGB from G-D?

Response to C++: Everything about hooking. 2006-03-12 15:07:34


I hope you and the guy who posted this tutorial on here a few weeks back are the same people, otherwise you just ripped a tutorial.

Response to C++: Everything about hooking. 2006-03-12 17:23:01


At 3/12/06 03:07 PM, 0x41 wrote: I hope you and the guy who posted this tutorial on here a few weeks back are the same people, otherwise you just ripped a tutorial.

Erm I didn't rip this tutorial. I gave credit to the author. I'm positive he is the author, so I think the one you just linked me to is ripped.

Response to C++: Everything about hooking. 2006-03-12 17:26:02


I thought C++ Main was for people to post their own self made tutorials and code though?

Response to C++: Everything about hooking. 2006-05-22 22:27:42


At 3/11/06 09:05 PM, Glaiel_Gamer wrote: whats hooking

It is telling windows to pass controll to your program when an event happens, such as a keyboard button being pressed. (Basic definition)