Page 1 of 2
API hooking
Posted: Thu Jul 13, 2006 12:29 am
by Inf0Byt3
Just a small process-wide API hooking example. This could be easily modified to support system-wide hooking

. Many thanks to Rings for translating it.
Code: Select all
;Translated from C to Pure by Siegfried Rings, 2006
;API Hooking example for PureBasic 4
;(c) Sigfried Rings and Inf0Byt3
;Version 0.1
;>------------------------------------------------------------
;License: Freeware but with some limits: By using this library you agree
;NOT use it for creating malware, viruses, spyware, worms or rootkits
;or any program of this kind. If you do this I will find you, I'll kick your sorry ass,
;and cut your arms off so you can't code such crap in the future ;)
;Now get back to coding!
Global Dim Backup.b(5)
Procedure MyMessagebox(lp0.l,lp1.l,lp2.l,lp3.l)
Debug "This one was hooked :D"
ProcedureReturn
EndProcedure
Procedure Hook(Libname.s,FuncName.s,NewFunctionAddress)
dwAddr =GetProcAddress_(GetModuleHandle_(LibName), FuncName)
OriginalAdress=dwAddr
Result=ReadProcessMemory_(GetCurrentProcess_(), dwAddr, @Backup(0), 6, @readbytes) ;save old Bytes
Dim a.b(6)
a(0)=$e9
a(5)=$C3
dwCalc = NewFunctionAddress - dwAddr - 5; //((to)-(from)-5)
CopyMemory(@dwCalc,@a(1),4)
Result = WriteProcessMemory_(GetCurrentProcess_(), dwAddr, @a(0), 6, @written);
EndProcedure
Procedure UnHook(Libname.s,FuncName.s)
dwAddr = GetProcAddress_(GetModuleHandle_(LibName), FuncName)
Result= WriteProcessMemory_(GetCurrentProcess_(), dwAddr, @Backup(0), 6, @written);
EndProcedure
;Beavis, the test!
MessageRequester("Info","Yes No Hook",0)
Hook("user32.dll", "MessageBoxA", @MyMessageBox());
MessageRequester("Info","Yes No Hook",0)
UnHook("user32.dll", "MessageBoxA")
MessageRequester("Info","This wasn't hooked",0)
Posted: Thu Jul 13, 2006 11:46 am
by thefool
Very nice!
Posted: Thu Jul 13, 2006 12:17 pm
by srod
Interesting...
How would a system wide hook differ? Would you need to place the code in a dll?
Posted: Thu Jul 13, 2006 1:04 pm
by thefool
Srod; for a system wide hook you need to inject the hook in every running process. You can do it using a dll that will hook the api in the process it gets injected to.
Posted: Thu Jul 13, 2006 1:14 pm
by srod
In which case, is it possible to inject into a process which you have no control over; e.g. an application which you did not write?
Just out of interest.
Posted: Thu Jul 13, 2006 5:06 pm
by Inf0Byt3
Yes, of course. I'll try to make an example.
Posted: Sat Aug 26, 2006 9:57 am
by newbie
Interesting piece of code, thanks for sharing

But I do not understand at all this snippet :
What are these values ? Where do they come from ?
Basically you backup the current real API address, and then you overwrite it with your custom procedure address, I don't see the need of these values.
Posted: Sat Aug 26, 2006 10:02 am
by Inf0Byt3
Well, i guess that they are the fist 2 bytes from the process's import table... If you wipe them out, the hooking doesn't work anymore. I am not sure this is the right explanation, because Rings made this code... I think he knows better.
Posted: Sat Aug 26, 2006 10:26 am
by Edwin Knoppert
If anyone is that clever, make me a way to reposition the file offset used by LoadLibrary() to obtain the dll from an exe or memory.
I'm aware of the loadfrommem code on this forum but i whould like to know if a simple modification to the LoadLibrary() process could work as well.
Meaning, embed a dll in an exe, know the fileoffset in the exe to the dll and instruct the LL() stuff to read it from there, not from the 1st byte (exe)
Posted: Mon Aug 28, 2006 8:36 am
by Rings
newbie wrote:But I do not understand at all this snippet :
What are these values ? Where do they come from ?
Basically you backup the current real API address, and then you overwrite it with your custom procedure address, I don't see the need of these values.
Inf0Byt3 wrote:Well, i guess that they are the fist 2 bytes from the process's import table... If you wipe them out, the hooking doesn't work anymore. I am not sure this is the right explanation, because Rings made this code... I think he knows better.
ok,
if a process calls the api-Procedure (for example MessageBoxEx@16 (same as Messagerequester(....) ), the first 5 Bytes in the Api-Procedure
are Codes to save some registers.
You can test severals Apis, and you get the same results:
Code: Select all
Api.s="MessageBoxA"
Lib.s="user32.dll"
l=LoadLibrary_(@Lib.s)
addr=GetProcAddress_(l,@Api)
If addr
Debug "found at : " + Hex(addr)
Debug "-----------------"
Debug "Get first bytes now:"
Debug ""
Pointer =addr
While p<5
Pointer= DisASMCommand(Pointer)
p=Pointer-addr
Debug GetDisASMString()
Wend
Debug p
FreeLibrary_(l)
EndIf
The trick to redirect is now to replace those 5 Bytes with a JMP- condition.
Regular, all JMP-Condition with FAR-Pointers have 6 Bytes.
Only the relative JMP-Condition has 5 Bytes.
The First Opcode for this relative JMP is then the magic $E9.
(see INTEL-x86 Books or just google for 'E9 and JMP'
the $C3 is only for saveness, its a Exception-Call. so if any error occurs,
your own exceptionhandler (maybe OnError) will be called.
This byte is not needed IMHO.
The Rest (not in the snippet described) is to make a Trampoline function, which then can also call the original function.....
@Edwin, Yes, way and idea seems not bad. Try OllyDebug and follow LoadLibraryA() and GetProcAddr(). (you will end in the kernel i guess)
Enough hacking for a monday then......all right ?
Posted: Mon Aug 28, 2006 10:34 am
by DarkDragon
I have just one problem: Why isn't the function hooked? I mean: why can't I control the calls myself like in the remoteAPI lib? Why does the Messagerequester appear even if I hooked it?
Posted: Mon Aug 28, 2006 10:51 am
by Rings
DarkDragon wrote:I have just one problem: Why isn't the function hooked? I mean: why can't I control the calls myself like in the remoteAPI lib? Why does the Messagerequester appear even if I hooked it?
what was wrong with that example ?
it works here as it should do.
Posted: Mon Aug 28, 2006 1:26 pm
by DarkDragon
Rings wrote:DarkDragon wrote:I have just one problem: Why isn't the function hooked? I mean: why can't I control the calls myself like in the remoteAPI lib? Why does the Messagerequester appear even if I hooked it?
what was wrong with that example ?
it works here as it should do.
Ohh I see

. I thought I have seen 3 MessageBoxes(The one which was hooked, too), but it were only 2. Sorry.
I need new glasses...
Posted: Mon Aug 28, 2006 1:41 pm
by Inf0Byt3
It really would be cool to make a system wide hook through a driver

. I must download the DDK and try it. BTW, to start a driver I must start it like a normal service right?
Posted: Mon Aug 28, 2006 1:52 pm
by DarkDragon
Inf0Byt3 wrote:It really would be cool to make a system wide hook through a driver

. I must download the DDK and try it. BTW, to start a driver I must start it like a normal service right?
Not the DDK, use assembler, like purefan did. Make a rootkit and call it pure-rootkit which replaces a system dll with someones own through only one PB command

.