DLL injection, baby

There are a lot of concepts (specially in the world of computer security) which look very mystic and dll injection is, without any doubt, one of those. I’ll just post here a proof of concept because… well, because I think it’s interesting shit! :)

I’ll do it on Linux because I feel more comfortable in this OS but the concept is similar in MS Windows. First of all, an excerpt from an online program library howto:

Shared libraries are libraries that are loaded by programs when they start. When a shared library is installed properly, all programs that start afterwards automatically use the new shared library. It’s actually much more flexible and sophisticated than this, because the approach used by Linux permits you to:

  • update libraries and still support programs that want to use older, non-backward-compatible versions of those libraries;
  • override specific libraries or even specific functions in a library when executing a particular program.
  • do all this while programs are running using existing libraries.

The second point is the interesting one for us, since it will allow us to “impersonate” some of the functions the program calls that are situated inside dynamic link libraries. Several examples crossed my mind right now, all of them containing functions with names like checkPassword() or something similar :)

Instead of giving a boring lecture I’ll try to explain every point on the way. Let’s say our target program is this one (core.c):

#include <stdio.h>
#include <stdint.h>
#include <time.h>

int
main(int argc, char **argv)
{
time_t result;

printf(“I’m about to call time() in time.hn”);
result = time(NULL);
printf(“The time is %ju secsn”, (uintmax_t)result);

return(0);
}

It just get the system time using the time() function in glibc 2.0 and prints it to the console.

carlos@pattern:~/Projects/dll_injection$ ./core
I’m about to call time() in time.h
The time is 1253876880 secs
carlos@pattern:~/Projects/dll_injection$ ./core
I’m about to call time() in time.h
The time is 1253876888 secs

Until here, nothing really interesting so let’s get a bit more deep. In order to get the system time, core.c uses a function which code is not in my program but inside a shared library. Our core.c program publishes, after compiling, a series of symbols, that is, information about where should these functions code be inserted. This can be inspected with nm:

carlos@pattern:~/Projects/dll_injection$ nm core
08049f20 d _DYNAMIC
08049ff4 d _GLOBAL_OFFSET_TABLE_
0804853c R _IO_stdin_used
[…]
0804a014 W data_start
0804a020 b dtor_idx.6637
08048400 t frame_dummy
08048424 T main
U printf@@GLIBC_2.0
U puts@@GLIBC_2.0
U time@@GLIBC_2.0

Notice how time and printf are listed here. We can see as well what libraries are linked at runtime with ldd:

carlos@pattern:~/Projects/dll_injection$ ldd core
linux-gate.so.1 =>  (0xb8058000)
libc.so.6 => /lib/tls/i686/cmov/libc.so.6 (0xb7eda000)
/lib/ld-linux.so.2 (0xb8059000)

As expected, the libc is listed here, along with a very special one ld-linux.so.2, the dynamic linker/loader.

From the man page:

ld.so loads the shared libraries needed by a program, prepares the program to run, and then runs it.  Unless  explicitly  specified  via  the -static  option to ld during compilation, all Linux programs are incomplete and require further linking at run time.

[SuperNerd parenthesis]

GCC inserts at compile time an ELF header specifying which dynamic loader will be used at runtime:

carlos@pattern:~/Projects/dll_injection$ readelf -l core

Elf file type is EXEC (Executable file)
Entry point 0x8048370
There are 8 program headers, starting at offset 52

Program Headers:
Type           Offset   VirtAddr   PhysAddr   FileSiz MemSiz  Flg Align
PHDR           0x000034 0x08048034 0x08048034 0x00100 0x00100 R E 0x4
INTERP         0x000134 0x08048134 0x08048134 0x00013 0x00013 R   0x1
[Requesting program interpreter: /lib/ld-linux.so.2]
LOAD           0x000000 0x08048000 0x08048000 0x00580 0x00580 R E 0x1000
LOAD           0x000f0c 0x08049f0c 0x08049f0c 0x00110 0x00118 RW  0x1000
DYNAMIC        0x000f20 0x08049f20 0x08049f20 0x000d0 0x000d0 RW  0x4
NOTE           0x000148 0x08048148 0x08048148 0x00020 0x00020 R   0x4

[…]

That instructs the OS to pass the control of the program to ld-linux.so.2 instead of the normal entry point of the application.

[End of SuperNerd parenthesis]

ld-linux.so.2 checks the symbols (the way nm does), searches for the library files and loads the corresponding code into the process memory.

There’s a way, however, of preloading a shared object (or dll) at run time giving it precedence over this process. Here is where the technical info gets obscure but I guess this lib becomes a preferred target for symbol retrieval, so if it contains a symbol with a matching name, its code will be loaded and this dependency marked as satisfied.

That’s all we need to know. Let’s create our shared object then with a function called… yes, time()

carlos@pattern:~/Projects/dll_injection$ cat lib_evil.c

/* The evil library.
It exports the symbol time()
and overrides glibc
*/

#include <stdio.h>

int time()
{
printf(“FAKE TIME FUNCTION says: No you didn’t!n”);
return(1234);
}

and compile it as shared object:

To create the object file:

$ gcc -c -fPIC -ggdb -Wall -o lib_evil.o lib_evil.c

To create the shared object (library .so):

$ ld -shared lib_evil.o -o lib_evil.so

Finally, let’s try our cool DLL injection, preloading our evil shared object.

Normal operation

carlos@pattern:~/Projects/dll_injection$ ./core
I’m about to call time() in time.h
The time is 1253881612 secs

DLL injection
carlos@pattern:~/Projects/dll_injection$ LD_PRELOAD=”./lib_evil.so” ./core
I’m about to call time() in time.h
FAKE TIME FUNCTION says: No you didn’t!
The time is 1234 secs

Now find your favourite software and try to bypass authentication following this pseudocode:

function checkPassword

return EverythingCool ;)

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s