04 - ELF HookingΒΆ

The objective of this tutorial is to hook a library function

Scripts and materials are available here: materials


In the previous tutorial we saw how to swap symbols names from a shared library, we will now see the mechanism to hook a function in a shared library.

The targeted library is the standard math library (libm.so) and we will insert a hook on the exp function so that \(exp(x) = x + 1\). The source code of the sample that uses this function is given in the following listing:

#include <stdio.h>
#include <stdlib.h>
#include <math.h>

int main(int argc, char **argv) {
  if (argc != 2) {
    printf("Usage: %s <a> \n", argv[0]);
    exit(-1);
  }

  int a = atoi(argv[1]);
  printf("exp(%d) = %f\n", a, exp(a));
  return 0;
}

The hooking function is as simple as:

double hook(double x) {
  return x + 1;
}

Compiled with gcc -Os -nostdlib -nodefaultlibs -fPIC -Wl,-shared hook.c -o hook.

To inject this hook into the library, we use the insert_content() method

Binary.insert_content(self: lief.ELF.Binary, content: List[int]) → Tuple[int, int]

Add some data in the binary and return the (offset, size) of the inserted content

Warning

This method should be used only for libraries

This method will insert our stub into the library and returns a tuple (offset, size) where offset is the location of the stub in the library and size the stub’s size aligned. As a side effect, assembly code is shifted and various offsets are patched.

Once the stub is injected we just have to change the address of the exp symbol:

exp_symbol = next(filter(lambda e : e.name == "exp", libm.exported_symbols))
hook_symbol = next(filter(lambda e : e.name == "hook", hook.exported_symbols))

exp_symbol.value = offset + hook_symbol.value

To test the patched library:

./do_math.bin 1
exp(1) = 2.718282
LD_LIBRARY_PATH=. ./do_math.bin 1
exp(1) = 2.000000