您的位置:首页 > 其它

Let’s Hook a Library Function

2015-11-24 15:52 344 查看
If you are a developer, and want to change the way a library function works, this article will give you a basic idea of how to get started — just enough knowledge to be able to experiment with your library functions. All code here is in C, and tested with GCC
on Linux.

According to Wikipedia, “In computer programming,
the term hooking covers a range of techniques used to alter or augment the behaviour of an operating system, applications, or other software components, by intercepting function calls or messages or events passed between software components. Code that handles
such intercepted function calls, events or messages is called a hook.”

Intercepting a library call, and calling your own wrapper code, is also called Function Interposition.

Hooking has two benefits:

You don’t have to search for the function definition in the library, such as
libc
(
glibc
is
the GNU C Library, and
libc
is almost half of the size of
glibc
)
and change it. Seriously, this is a very nasty technical task (at least for me!).

You don’t need to recompile the library’s source code.


Library functions and system calls

Please look at Figures 1 and 2 for a graphical representation of what happens when a library function is hooked.





Figure 1: Library function





Figure 2: Library function with hook

Now let’s look at hooking a library function. The simple
prog1.c
program below just allocates
10 bytes of memory from the heap, and frees it:

When we compile and run the above program, the output is as shown below:

The next program, called
prog2.c
, is a simple hook for the
malloc()
function:

Compiling and running the above, goes like this:

So, let’s take a closer look at our first hook. The
dlsym()
function takes two parameters: the
first is a handle returned by
dlopen()
. Here, we must use
RTLD_NEXT
for
function interposition.

This tells the dynamic linker to find the next reference to the specified function, not the one that is calling
dlsym()
.
The second parameter is the symbol name (
malloc
, in this case), as a character string.
dlsym()
returns
the address of the symbol specified as the second parameter. While compiling,
fPIC
is used to
create a position-independent object.

The
LD_PRELOAD
environment variable gives the loader a list of libraries to load before anything
else. Our use of it will load
libprog2.so
and dynamically link it with the
prog1
binary.
Don’t forget to provide an absolute path to the
.so
, in
LD_PRELOAD
.
And, of course, include
_GNU_SOURCE
if you want to use certain extensions while using the GNU
C library, because some extensions may not be available on other non-GNU systems and adding this
#define
will
increase portability.


Can we hook every function with dlsym()?

The above hook method will not work if you want to wrap
dlsym()
itself, or wrap any library functions
that internally call
dlsym()
. So, is there any way to interpose
dlsym()
?
Yes, but you can’t use the same hook procedure — check the output if you try that. First, create a shared object
libfile.so
from
file1.c
and
file2.c
(below).
Then compile it with
gcc -rdynamic -o dl_prog1 dl_prog1.c -ldl
. Yes, the output is obvious:

The following
dl_prog1.c
is a simple program to show the functionality of
dlopen()
and
dlsym()
.
The functions
file1()
and
file2()
are
defined in
file1.c
and
file2.c
.

Now try to hook
dlsym()
, and you will get a segmentation fault, due to recursive calls (
dlsym()
will
call itself). The following
dl_prog2.c
will be a recursive
dlsym()
call
to itself, which causes a stack overflow and segmentation fault:

Output:

Here is the code (
dl_prog3.c
) that successfully interposes
dlsym()
:

Output:


What else can we do?

I have already interposed other functions like
getaddrinfo()
,
open()
,
etc, so you can intercept any function you want. But there are a few limitations:

Do beware of functions that themselves call
dlsym()
, when you need to call
__libc_dlsym
(handle,
symbol) in the hook.

Ensure that the SUID bit is not set, otherwise you can’t use
LD_PRELOAD
.

Also, internal library function calls are resolved before runtime — say, if some function in
libc
calls
getaddrinfo()
or
malloc()
,
it will never call the hook from a different library.


References


Tutorial: Function Interposition in
Linux by Jay Conrod

Linux man pages:
dlopen()
,
dlsym()
,
dlerror()
,
dlclose()



Related Posts:

Dangling
Pointers Avoid them Strictly!

Write
Your Own conio.h for GNU/Linux

CodeSport

Analyse
Your Network Packets with LibPCAP

File
Systems A Semester Project-II, Part-19

Tags: C
program, C
standard library, computer
programming, Dynamic
memory allocation, GCC, glibc, GNU
C Library, heap, hooking, LFY
August 2011, Library
(computing), library
functions, malloc, stdio, stdlib, wrapper
code

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: