📚
OpenRCE
is preserved as a read-only archive. Launched at RECon Montreal in 2005. Registration and posting are disabled.
About
Articles
Book Store
Distributed RCE
Downloads
Event Calendar
Forums
Live Discussion
Reference Library
RSS Feeds
Search
Users
What's New
Customize Theme
bluegrey
blackgreen
metal
simple
Flag:
Tornado!
Hurricane!
Login:
Password:
Remember Me
Register
Blogs
>>
Dreg
's Blog
Created: Wednesday, August 5 2009 08:43.14 CDT
Printer Friendly ...
One safe hook handler - E8 Method, paper
Author:
Dreg
# Views:
8732
There exist different libraries to set hooks, lot of them in Windows, but
time ago we faced a specific problem for which no solution nor documentation
were found about. The problem is: how to setup hooks for several APIs in runtime,
reading from a configuration file that gives the APIs and prototypes? When
discussing about this idea I got another question in response: why do you want to
do that? My answer was: I don't want to develop a different handler for every hooked API
and compile every time for it to work, and I don't want to build a run time Handler creator.
We cam sum up in two requisites:
1.- Use some kind of technology that does not require previous compiling.
2.- Develop some kind of macro to simplify the coding and reduce compile errors.
As I was not convinced of these solutions, I started to think about this problem
and about what I really want, so the right question appeared: What do I need to
do what I want? And the answer is simple: Having one handler for every hook, just
know when it is called, which API/hook is the caller and then take proper decissions.
That's it!, I need and "API ID". Or best expressed, I need a "hook_caller ID"
This is the point where I need to mention that the hook method I need is "Detours"
[R.9] [R.6], said, insert a JMP, PUSH + RET ... in the address where we want
to place the hook. I selected this method [R.9] taking care about that
some of the other methods have a problem when you call directly the memory address where the
hook lies, so the handler it is not executed, i.e. IAT HOOKING. In the methods that
insert JMP, PUSH + RET... in reserved memory or padding bytes, direct calls don't
execute the handler. As my first priority was to intercept every call to the hooked APIs,
the "Detours" method [R.9] [R.6] that overwrites instructions where we want our hook
placed, looked the best. Though this method implies the use of some kind of LDE
(Length-Disassembler Engine) [R.7], among other things, there exist libraries in the
web that allow us to use this method in Windows without any trouble.
Now, we just need only to answer the question: how can I know which hook
is calling the handler in runtime? After some serious thinking about the problem
I got an "Eureka!": I will replace the JMP method by a CALL-style method, and
I will check from the hanlder the return address that CALL places in the stack,
using this return address as the "hook_caller ID". As every hook is in a different
memory position, every CALL will place a different value in the stack, so it can
be used as an identificator. Then, we need only to modify the normal method so
the handler will process this "hook_caller ID" and will remove it from the stack.
Problem solved. Now the last thing left was to find a name, this name appeared
when coding the problem: "E8 Method". As a JMP (no SHORT) in the address
XXXXXXXX to YYYYYYYY, will be coded as: "E9 ZZZZZZZZ", and a CALL from the same
address to the other address will be coded as: "E8 ZZZZZZZZ". Eureka! (again).
The part that changed was the opcode for the instruction, as it was opcode for CALL, E8, so
I decided to call the method "E8 Method". But "E8 Method" it is not only to replace
the JMP type hook by the CALL type, it is the concept and/or the style of implementing
a global handler ("One hook handler") that could obtain the "hook_caller ID" in runtime.
After the development of the first proof of concept (POC) I had some problems, like stack
buffer overflows when the hooked APIs where called directly and indirectly from the hooh
handler, Microsoft Visual Studio checks to detect when the stack is corrupted using the
EDI value my hook handler was modifying internally, etc. So it was not only to create a
hook handler; I have had to create a safe hook handler taking care of most of there problems.
As long as the project grew it was neccesary to code some pieces in C/C++
resulting a problematic hybrid code between ASM/C/C++, so I developed a low-level layer
that allowed me to code everything in C/C++ without further troubles. There appeared some stack
buffer overflows too when calling the hooked API, but I found an ellegant solution in the
easy hook called Threat Deadlock Barrier (TDB) [R.8].
This documento is about how to use and implement the "E8 Method" with only one
hook handler for every hook that will be safe and will be implemented in C/C++: "One safe Hook Handler".
Two public libraries, where a hack has been applied, will be used:
1.- Microsoft Detours Library [R.6]
2.- Easy-Hook [R.8]
Download in English:
http://fr33project.org/papers/One%20safe%20hook%20handler%20-%20E8%20Method.txt
Download in Spanish:
http://fr33project.org/spanish/papers/One%20safe%20hook%20handler%20-%20E8%20Method.txt
Blog Comments
oleavr
Posted: Friday, August 14 2009 05:21.42 CDT
Cool stuff! This reminds me of a library of mine called Intercept++, which allows you to hook API based on an XML config file, where you also define types and argument lists, and it does recursive marshaling to log everything automatically. (It also supports all of this programmatically.) I remember having the exact same E8-eureka -- funny :) Think this will serve as an example of how to use it:
http://oleandre.wordpress.com/2008/06/23/ospy-and-jit-x86-machine-code-generation/
(The source code is in oSpy's SVN repository, was meant to be the engine of a future oSpy, but I haven't had time to write a new UI / port the old one.)
Binary snapshot:
http://people.collabora.co.uk/~oleavr/oSpy2/oSpy2-20080109.zip
And another one with a config.xml demonstrating how to intercept calls to Google Talk Video Plugin's internal logging infrastructure through function signature fingerprinting:
http://people.collabora.co.uk/~oleavr/oSpy2/oSpy2-20081114-GTalkPluginLog-r2.rar
Sirmabus
Posted: Thursday, August 20 2009 07:39.38 CDT
Seems to me you don't have to do it that way.
You still should be able to do a "JMP" as well.
Just make your detour/stub a bit more complex.
Think of it as an object, rather then just a block of code bytes.
It could have a static code offset to your manager, or even a C++ class in it, etc.
And you could have all the functions arguments in the same block too. You'll have one set of complete data.
Sure it takes more memory (maybe not because of your tree/list structure), but talking only tens of kilobytes at the most.
Example:
struct __declspec(novtable) tDETOUROBJ
{
// Override new/delete to make block at least align 16 (need to turn off DEP someplace still)
static PVOID __cdecl operator new(size_t size) { return(_aligned_malloc(size, 16)); };
static void __cdecl operator delete(PVOID _Ptr){ _aligned_free(_Ptr); }
// Ctor if needed
void tDETOUROBJ()
{
memset(this, 0, sizeof(tDETOUROBJ));
..
.. etc.
}
// Data.. the hook detour entry point here..
BYTE aCode[64]; // [00] Space for hook system generated detour code (and hook entry point)
PVOID pHandler; // [64] Address of handler function
cFuncDefClass cFuncDef; // [68] Can have a C++ class in here et al
};
Maybe your "CALL" system good for a monitor type project, but you loose some performance doing it this way. So not as good as a general hooking method IMHO.
You de-link the hook from the detour, and you have to go through your data list/tree to find where it belongs plus some other code.
FYI If you make detour/object blocks align 16 or 32, there is very few clock cycles to JMP to the detour.
Sirmabus
Posted: Thursday, August 20 2009 08:28.40 CDT
Dreg
Posted: Friday, August 21 2009 00:00.04 CDT
interesting :-). I also implemented a hash table based on the EP of the function hooked (hook caller id (CALL)) for logging using my method. Anything like this:
hooking system with call instead of jmp. The hook caller id is the return address of the CALL.
global hook handler:
LogApi( table[HashI(return_of_the_call)] );
The table have the type of the arguments, the calling convention .... all you need to restore stack, logging...
All is dynamic, you can hook a new API only reading aa config file (for example) and updating the hash table.
Sincerely, Dreg.
Add New Comment
Comment:
There are
31,328
total registered users.
Recently Created Topics
[help] Unpacking VMP...
Mar/12
Reverse Engineering ...
Jul/06
let 'IDAPython' impo...
Sep/24
set 'IDAPython' as t...
Sep/24
GuessType return une...
Sep/20
About retrieving the...
Sep/07
How to find specific...
Aug/15
How to get data depe...
Jul/07
Identify RVA data in...
May/06
Question about memor...
Dec/12
Recent Forum Posts
Finding the procedur...
rolEYder
Question about debbu...
rolEYder
Identify RVA data in...
sohlow
let 'IDAPython' impo...
sohlow
How to find specific...
hackgreti
Problem with ollydbg
sh3dow
How can I write olly...
sh3dow
New LoadMAP plugin v...
mefisto...
Intel pin in loaded ...
djnemo
OOP_RE tool available?
Bl4ckm4n
Recent Blog Entries
halsten
Mar/14
Breaking IonCUBE VM
oleavr
Oct/24
Anatomy of a code tracer
hasherezade
Sep/24
IAT Patcher - new tool for ...
oleavr
Aug/27
CryptoShark: code tracer ba...
oleavr
Jun/25
Build a debugger in 5 minutes
More ...
Recent Blog Comments
nieo
on:
Mar/22
IAT Patcher - new tool for ...
djnemo
on:
Nov/17
Kernel debugger vs user mod...
acel
on:
Nov/14
Kernel debugger vs user mod...
pedram
on:
Dec/21
frida.github.io: scriptable...
capadleman
on:
Jun/19
Using NtCreateThreadEx for ...
More ...
Imagery
SoySauce Blueprint
Jun 6, 2008
[+] expand
View Gallery
(11) /
Submit