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.