Article

Dynamic Hooking Techniques: User Mode

Hooking is the process of intercepting a program’s execution at a specific point in order to take another action.

This article is the first of two providing a basic overview of a number of dynamic hooking techniques. Part 1 covers techniques that can be used in user mode and part 2 will cover techniques that work in kernel mode.

Hooking is the process of intercepting a program’s execution at a specific point in order to take another action. This may be simply to trace execution at interesting points, or to redirect and modify execution. At the point at which you wish to intercept, you place your hook.

A hook can be placed by modifying a program’s code on disk or even building it in at compile time, but this article focuses on dynamic hooking, where hooks are placed at runtime in memory. This allows hooks to be applied to any software whether we have the source code or not and whether we are able to modify the program’s files or not.

This article assumes that you have sufficient access to modify a program’s memory to place a hook. Practically speaking, this could be through attaching a debugger, injecting code into a process’s memory space or by having compromised an application by exploiting a vulnerability.

Why hook?

Hooking can be useful for a wide range of purposes, including:

  • Dynamically tracing program flow to work out what the program is doing
  • System wide hooks can trace what is happening over an entire system for profiling, identifying misbehaving programs or uncovering malware
  • Hooks can modify a program’s behaviour or the behaviour of an entire API
  • The monitoring capability that hooking provides can sometimes identify the cause of misbehaving programs
  • Instrumenting a binary with hooks can be useful when reverse engineering software
  • HIDS/HIPS systems can use hooking to help identify malicious behaviour
  • Rootkits can make extensive use of hooking to monitor, modify or trigger actions on the system

Patch a specific call

The simplest way to visualise a hook is to consider a simple example. If you wish to hook a specific call of a function in a program, the target address of that call instruction can be changed to point to your own code which you have somehow injected into the program’s memory space. You can then choose whether to handle the call completely yourself, possibly providing a fake result, or you may choose to redirect execution to the original function, perhaps also changing the arguments or altering the return value.

So, while originally the call would look like this:

...
...
call func1
...
...
func1
...
return

It is altered to look like this:

...
...
call hook
...
...
hook
...
optional call to original
...
return
func1
...
return

If you wanted to use the same hook function for multiple hooks, you could create a lookup table of return addresses and check this at the start of the hook to work out where the hook call originated, and then take a different action depending on this information. Of course this assumes you are not on a platform with technologies like ASLR enabled, which may randomise addresses making this simplistic method impossible. Nevertheless, this simple example demonstrates what a hook is.

IAT hooking

The Import Address Table (IAT) is loaded into memory from PE executables. It allows the memory address of functions imported from DLLs to be located. By locating the IAT in memory, you can patch it to redirect certain API function calls to hooking code.

IAT hooking happens in user mode and is a relatively easy way to hook every call to a specific APIfunction or set of functions. Any time the program makes that API call, your hook code will run. However, DLLs can also be loaded dynamically at runtime and when this happens there will be noIAT for that DLL. Furthermore, while the fact that this is a user mode technique makes it easier to implement, it also makes it easier to detect. As such, IAT hooking is not without its limitations.

LD_PRELOAD

Under Unix-like operating systems (including Linux), calls to shared libraries can also be hooked by making use of the LD_PRELOAD environment variable. By writing your own shared library with the functions you wish to hook defined by name you can hook these functions by loading that library at runtime with the target program. The LD_PRELOAD environment variable specifies a list of libraries to load first when a program is executed, so if you put the path to your library in this variable your own function will run instead.

If you also wish to redirect execution to the original function you are hooking, you can do so with the dlsym() function call which resolves a function name in a module to a memory address. Using this, the address of the original function can be located and used to make a call to it.

Inline hooking

An inline hook overwrites the start of the function you want to hook to redirect execution. This allows you easily to catch every call to that function, no matter where or when the call happens. Inserting an inline hook obviously destroys some of the early logic of the original function, so if you wish to call the original function as well, the hook code must compensate for the instructions that were overwritten. An inline hooker should therefore save the instructions that were overwritten when placing a hook. This may not be trivial to do on architectures like x86 where instructions are variable length, and saving the bytes that were overwritten may not preserve the meaning of the code. In such cases, automated inline hookers may need to disassemble the start of the function properly to preserve the original function’s meaning.

Inline hooking can be used in user mode, although similar techniques can also work in kernel mode.

Detours

Microsoft released a framework to help in placing inline hooks on Win32 API functions called Detours. Microsoft actually places a two-byte dummy instruction that does nothing at the start of functions (the instruction is “MOV EDI, EDI”) to allow space to overwrite with a jump instruction harmlessly. The Detours package provides an API to enable custom hooks to be placed on APIfunctions in this way.

In fact, the dummy instruction is only big enough to replace with a short jump. A long jump (to code further away) would take up too many bytes and still overwrite part of the function. The intention is that a short jump is placed to jump to five bytes before the function, which is set aside as spare padding space. In these five bytes, the long jump can be placed to redirect to your hook code.

The advantage of using the short jump first is that whether in its “MOV EDI, EDI” form or its short jump form, those two bytes are always a single instruction. This means that, if multiple threads are executing the function as you are hooking it, a thread will never end up executing from the middle of an instruction you just inserted for your hook; rather it will either hit your new short jump, or already be beyond it, safely executing the rest of the function.

 

 

Accreditations

As members of CHECK we are measured against high standards set by CESG for the services we provide to Her Majesty's Government.
We are certified in the ISO 9001 quality management system (QMS) in the UK, ensuring reliable delivery of our products and services.
We are certified to comply with ISO 14001 in the UK, an internationally accepted standard that outlines how to put an effective environmental management system in place.
MWR is certified to comply with ISO 27001 to help ensure our client information is managed securely.
As an Approved Scanning Vendor MWR are approved by PCI SSC to conduct external vulnerability scanning services to PCI DSS Requirement 11.2.2.
We are members of the Council of Registered Ethical Security Testers (CREST), an organisation serving the needs of the information security sector.
MWR is a supplier to the Crown Commercial Service (CCS), which provides commercial and procurement services to the UK public sector.
MWR is a Qualified Security Assessor, meaning we have been qualified by PCI to validate other organisation's adherence to PCI DSS.