Hook library calls linux

jona.t4

woensdag 27 november 2013

Hooking explained: detouring library calls and vtable patching in Windows/Linux/MAC-OSX

§ 1 Shared Libraries & Injection/Loading

Shared libraries are code objects that may be loaded during execution into the memory space associated with a process. Library code may be shared in memory by multiple processes as well as on disk. If virtual memory is used, processes execute the same physical page of RAM, mapped into the different address spaces of each process. This has advantages. For instance on some systems, applications were often only a few hundred kilobytes in size and loaded quickly; the majority of their code was located in libraries that had already been loaded for other purposes by the operating system.

To change code in another process we must load our own shared library in the address space of the other process. On UNIX platforms (Linux/MAC-OSX) this can be achieved using the LD_PRELOAD environment variable, which instructs the loader to load the specific shared libraries. Function and other symbol definitions in the specified libraries will be used instead of the original ones.
However on Windows systems there is no such thing as LD_PRELOAD, to achieve the same result we must use a little exploit called DLL Injection (On Windows shared libraries are .DLL’s, on Linux .so‘s and on MAC-OSX .dylib‘s). See Appendix A below for more information.

§ 2 Hooking/Detouring function calls

§ 2.1 UNIX/Linux

UNIX offers a simple way to override functions in a shared library with the LD_PRELOAD environment variable. When you make a twin brother of a function that is defined in an existing shared library, put it in your shared library, and you register your shared library name in DYLD_INSERT_LIBRARIES, your function is used instead of the original one. It is exactly the same as MAC-OSX (see below) but use LD_PRELOAD instead of DYLD_INSERT_LIBRARIES .

Since MAC-OSX is also UNIX based it’s almost exactly the same as in Linux, only they have renamed LD_PRELOAD to DYLD_INSERT_LIBRARIES and .so to .dylib. In this example I’ve detoured fopen from a test program. In 2003 Jonathan Rentzsch showed ways of detouring in MAC-OSX and released mach_star, but this method is way easier.

Compiling the library:

Running the program with DYLD_INSERT_LIBRARIES.
You also need to define DYLD_FORCE_FLAT_NAMESPACE (doesn’t matter what value it has).You can use the same technique to override a method in a class. Say there’s a method named «libfff» in a class AAA.

To override it, you first need to know the mangled symbol name of the method.

This is the framework of a standard API hook. All of this resides in a DLL that will be injected into a process. For this example, I chose to hook the MessageBoxW function. Once this DLL is injected, it will get the address of the MessageBoXW function from user32.dll, and then the hooking begins. In the BeginRedirect function, an unconditional relative jump (JMP) opcode (0xE9) instruction will contain the distance to jump to. The source is fully commented.

Appendix A: Windows DLL injection

NOTE: the easy way is at the end of this appendix, i will start with the hardcore method first.
Welcome to appendix A, here i will explain how to make another process load our DLL. What we do is allocate a chunk of memory in the target process with our assembly function which calls LoadLibrary, we also need to allocate space for our DLL path name. Next we suspend the main thread of our target and modify the register that holds the next instruction to be executed. Than we patch our allocated function to return/call the right addresses. When we are done we resume the main thread.

To continue we’ll need a handle to a thread in the process, to achieve this one can use this function show in block A-2.

This is a prototype for the function we are going to allocate in the target process which will call loadlibrary, the addresses are left blank because we patch them later on when we have the right values.

Now, we need to pause the thread in order to get it’s «context». The context of a thread is the current state of all of it’s registers, as well as other peripheral information. However, we’re mostly concerned with the EIP register, which points to the next instruction to be executed. So, if we don’t suspend the thread before retrieving its context information, it’ll continue executing and by the time we get the information, it’ll be invalid. Once we’ve paused the thread, we’ll retrieve it’s context information using the GetThreadContext() function. We’ll grab the value of the current next instruction to be executed, so that we know where our function should return to. Then it’s just a matter of patching up the function to have all of the proper pointers, and forcing the thread to execute it. (A-3)

Читайте также:  Перезапуск всех служб windows 2003

There is another way using the CreateRemoteThread call. It is extremely easy, and relatively efficient. Before starting though, it is important to actually find the process to inject into. The Windows API provides a great function for doing this – CreateToolhelp32Snapshot.

I didn’t bother storing the value after I called Process32First because that will always be “[System Process]”, so there’s really no need. Process32Next returns TRUE on success, so just simply putting it in a loop and pushing the name of the process it received in a vector is what is needed. Once the loop is finished, every single process should be stored in processNames. This is great and all, but where does the DLL injection come in? Well, the PROCESSENTRY32 structure also has a member that holds the Process ID. Inside that loop, while we’re pushing the process names in our vector, we’re also going to inject the DLL.

The code above is pretty straightforward, we first get the current directory and append our dll name to it so we can later allocate it in the target process memory. Then we create a new thread which calls loadlibrary with our dll path as parameter.

Appendix B: Import Address Table (IAT) Hooking

Before we jump in the Import Address Table you first need to know a bit background information, I’ll start with the PE format. The Portable Executable (PE) format is a file format for executables, object code, DLLs, FON Font files, and others used in 32-bit and 64-bit versions of Windows operating systems. The PE format is a data structure that encapsulates the information necessary for the Windows OS loader to manage the wrapped executable code. This includes dynamic library references for linking, API export and import tables, resource management data and thread-local storage (TLS) data.

One section of note is the import address table (IAT), which is used as a lookup table when the application is calling a function in a different module. It can be in the form of both import by ordinal and import by name. Because a compiled program cannot know the memory location of the libraries it depends upon, an indirect jump is required whenever an API call is made. As the dynamic linker loads modules and joins them together, it writes actual addresses into the IAT slots, so that they point to the memory locations of the corresponding library functions. Though this adds an extra jump over the cost of an intra-module call resulting in a performance penalty, it provides a key benefit: The number of memory pages that need to be copy-on-write changed by the loader is minimized, saving memory and disk I/O time. If the compiler knows ahead of time that a call will be inter-module (via a dllimport attribute) it can produce more optimized code that simply results in an indirect call opcode.

IAT hooking has pros and cons:
Cons:
— The method you are hooking must be imported from another module, you can’t just hook a certain address in memory. This is not optimal for directx hooks, since you will only find createdevice (you can use that to get the device tho) but for Opengl and such this is handy.
Pros:
— Less detectable, you can make this into a fully external hook, that should be undetected for any antivirus/cheat because it also doesn’t use any malicious calls.

Источник

Let’s Hook a Library Function

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:

Читайте также:  Копирование файлов windows долго

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:

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

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.

Источник

Interarticle

During this week, I made my first attempt to intercept and rewrite linux library API calls. In the process, I found documentation for this process to be woefully lacking (and inaccurate). Therefore, I’ve decided to share some experience on writing linux API hooks.

Background

API hooks, or rather, hooking, is a technique of intercepting function calls of programs, monitoring these function calls and potentially modifying them, thereby changing the behavior of a program or operating system transparently. Though certain platforms and applications provide or use hooks to implement certain features, for example Netfilter, often times hooks are used where there is no native support for hooking. Even without the support, may means of hooking have been invented on different computer platforms. Since these methods do not depend on software support (like plugin architectures), these techniques can modify and monitor the behavior of any software that uses know API calls, even without its source code. This makes hooking a very versatile technique.

My first encounter with hooking was four years ago, when I was working on a school project during my high school sophomore year, where I used Windows API hooks. The project was called “Process Firewall”, designed to intercept the start of any program, permit only those that have been whitelisted by the user to start, and terminate/block all others. The idea was to prevent any unknown program from starting, therefore preventing any malicious executables from infecting a users computer. Of course this idea is not much different from the UAC , and likewise, it didn’t really work out, but that’s another story. After some detours, I eventually settle on using hooks to intercept the CreateProcess Windows API calls using the Detours package provided by Microsoft Research. The process was fairly straightforward, I just started with the tutorial, hooked into “CreateProcess”, an did necessary security checks in the intercepted function call.

Linux Hooking

Fastforward to linux hooking. What I was trying to do was essentially the same as what I did four years ago: to modify the behavior of programs by intercepting their function calls; only this time, it’s under Linux.

So, I went ahead and looked for “linux api hook” on Google, and was lead straight to an excellent tutorial by Dibyendu Roy, “Let’s Hook a Library Function.” The tutorial is very well written, and I highly recommend going through the tutorial first to get an idea of how Linux hooking works.

The idea outlined in the tutorial is to write a dynamic link library that exports the same functions that you want to hook, and force the target process to load your dynamic link library first using the LD_PRELOAD environment variable, so that the dynamic linker will link your hook functions with the target program.

Читайте также:  Служба сервер кадров камеры windows неожиданно прервана это произошло

In this sense, hooking on Linux is a lot simpler than on Windows, where at the very least you need specialized Windows API calls, and at the worst, modifying in-memory dynamic link tables (which is what Detours does).

However, be warned. The last part of the aforementioned tutorial pointed to the usage of the function __libc_dlsym for hooking the dlsym function, which is an error prone method. The section “dlsym” in the following post will offer an alternative solution.

Target Program

Let’s first look at what kind of program we’d want to hook into. Hooking malloc was already explained in the tutorial mentioned above, so let’s try something a bit more complicated: GTK +. Why GTK + you ask? GTK + is used to write GUI programs, and therefore, hooking into GTK + allows us to modify the appearance of an application most directly. In extreme cases, it is possible to use hooks to augment an application, adding menu items and new dialogs/interfaces.

So, let’s have a look at a very basic GTK + example. The following example is adapted from First programs in GTK +

To compile it, you’ll need to install GTK +2.0 on your computer. Under Ubuntu (the distro that I’m using), type

Then, to compile, assuming that the file is named helloworld, use the following command (note the backticks “`”, not apostrophe)

After compiling, you may launch the program, using ./helloworld . You should then see an empty window with the title “Hello World.”

Hello World in GTK +

The Hook

Now that we have the target program, we can start writing the hook. So, what should we hook into? Let’s hook into gtk_window_set_title , that way, we can modify the title of the program. Suppose we want to append » (HOOKED)» to the title of the program that we have written. Here’s the code needed to accomplish the effect.

Be careful, you’ll need to compile this as a dynamic link library. Assuming the file were saved into hook.cpp , compile it using

To try it out do the following:

Hooked GTK + Hello World

Well, if you’re up to it, you can try hooking gedit as well:

Hooked GEdit

Why C++, you ask? Well, for one, I’m not a big fan of using strcat and doing fixed-size stack allocations of strings, and for another, using C++ allows us to easily initialize function pointers using global class variable constructors, which is a standard-complaint way of doing DllMain (a Windows DLL feature) under linux (see “Linux equivalent of DllMain”).

So, what have we done in the hook program?

  1. We implemented the GTK + function gtk_window_set_title in our own shared library. The dynamic linker would use our own program first because we specified our library in the environment variable LD_PRELOAD .
  2. Since we have written gtk_window_set_title ourselves, we can’t call this function inside the GTK + library directly (there’s no pkg-config —libs —cflags gtk+-2.0 ). Hence, we need to load it using dlsym .
    • This is implemented in the constructor of the class FunctionLoader , and it is invoked because we instantiated the global (static) variable functions . This allows us to invoke the gtk_window_set_title conveniently using functions.gtk_window_set_title , without even needing to explicitly initialize it.
    • Since we are using C++, we need to be careful about C function pointers. extern «C» must precede the function pointer definition to prevent decoration.
    • We don’t need to declare extern «C» on void gtk_window_set_title because it has already been defined in gtk/gtk.h . Do not neglect #include .
  3. The actual hook in the modified gtk_window_set_title function modifies the window title by appending » (HOOKED)» to the string using std::string . Care was taken to check for NULL strings (just in case) and empty strings (which is sometimes used by GTK internally, shouldn’t change that).

Refining the Hook

That was easy. At least much easier than would have been on Windows. However, there’s a catch. Just as we used the function dlsym to load a function from a system library, so could and would many program do so. This is particularly popular on cross distribution pre-compiled binaries, which often need to determine at run-time whether a set of system libraries is available for use and fallback to other libraries when not available. In this case, depending on the parameters passed to dlsym, it would be impossible to intercept library calls using the above method.

To get around this problem, we need to hook into the dlsym function and replace its system function pointers with our wrappers. However, it is not that simple. As shown in the sample code above, we need to load the real function pointers using dlsym so that we can pass intercepted requests to the real functions.

Источник

Оцените статью