The Universal Hooker tries to create very simple abstractions that allow a user of the tool to write hooks for different API and non-API functions using an interpreted language (python), without the need to compile anything, and with the possibility of changing the code that gets executed whent the hooked function is called in run-time. The Universal Hooker builds on the idea that the function handling the hook is the one with the knowledge about the parameters type of the function it is handling. The Universal Hooker only knows the number of parameters of the function, and obtains them from the stack (all DWORDS). The hook handler is the one that will interpret those DWORDS as the types received by the function. The hook handlers are written in python, what eliminates the need for recompiling the handlers when a modification is required. And also, the hook handlers (executed by the server) are reloaded from disk every time a hook handler is called, this means that one can change the behavior of the hook handler without the need to recompile the code, or having to restart the application being analyzed.
The basic components of the Universal Hooker are:
A configuration file is loaded from Ollydbg that defines what functions/addresses to hook, after parsing the configuration file the uhooker core connects to the server and sends the hook information. Every time a function hook is triggered, the uhooker core communicates with the server sending information about the function/address hooked, and the server executes the corresponding hook handler as defined in the configuration files.
There are 3 different types of hooks:
To intercept functions exported from a DLL the syntax is:
name_of_dll:function_name:number_of_parametes:python_module.hook_handler_name:hook_type
kernel32.dll:CreateFileA:7:mymodule.CreateFileA_handler:B
field_not_used:address_to_hook_in_hex:field_not_used:python_module.hook_handler_name:hook_type
dummy.dll:0x401000:0:mymodule.anybp:*
Next is a sample of how a configuration file look like:
# B = hook before entering function # A = hook AFTER function returns # * = hook when an address is executed kernel32.dll:CreateFileA:7:mymodule.CreateFileA_handler:B dummy.dll:0x401000:0:mymodule.anybp:*
A file dialog will be displayed from which a .cfg file (in fact any name can be used) can be loaded.
After parsing the configuration file, the uhooker core will try to set breakpoints on the functions/addresses indicated in the configuration file, for that reason before loading the configuration file the process to intercept should be loaded in the debugger or the debugger should be attached to the process.
Next is a sample hook handler:
def CreateFileA_handler(hookcall): myproxy = proxy.Proxy() print "bughandler running..." print "esp = %X" % hookcall.regs['esp'] print "retaddr = %X" % hookcall.retaddr print "arg0 = %X" % hookcall.params[0] buffer = myproxy.readasciiz( hookcall.params[0] ) print buffer hookcall.sendack() return
Here is a hook handler for sendto() that does what I just described.
When the packet is bigger than the original packet, this script allocates a new buffer and modifies (overwrites) the frame of the called function so the length is now correct and the ptr to the buffer points to the new data. In some ocassiones, this overwriting of the frame causes the program to crash or do weird things, I don't really know why yet (I did not try to establish the reason yet :)), so one thing I usually do is hook connect(), and make the program connect to a different port number and IP addresses.
Then I have a "proxy_hooker" that is basically a "tcp proxy" written in python, when a packet arrives to the proxy, it knows where to forward it, and also, every time a packet arrives, it calls a 'hook handler' in python, just like the universal hooker. In this way, I only need to mess with the connect() function, and I make all the changes to the packet with a hooker handler in the "proxy hooker" using the hex editor thing I mentioned above for example, outside the process.
This is the very simple proxy_hooker.
And here is the hooks.py sample hook that loads an hex editor to edit packets.