Thursday, July 15, 2021

Beginning Function Calls Hooking via LD_PRELOAD Environment Variable

In this post, I am learning about function hooking. Function call hooking allows us to intercept calls to existing functions thus ensuring we can execute our own code once the function is called. 

Specifically we are leverage the "LD_PRELOAD" environment variable to modify the function behaviour at runtime.

Here is my "helloWorld.c" code.

1
2
3
4
5
6
7
8
kali@securitynik:~/lkd/funcHook$ cat helloWorld.c
#include <stdio.h>

int main()
  {
    puts("[*] Welcome to SecurityNik's world! \n");
    return 0;
  }

Compile the code:

1
kali@securitynik:~/lkd/funcHook$ gcc helloWorld.c -o helloWorld.exe

When "helloWorld.exe" is executed, we get:

1
2
kali@securitynik:~/lkd/funcHook$ ./helloWorld.exe 
[*] Welcome to SecurityNik's world! 

Before moving to the next step, let's look at the shared object dependencies which "helloWorld.exe" has.

1
2
3
4
kali@securitynik:~/lkd/funcHook$ ldd ./helloWorld.exe 
        linux-vdso.so.1 (0x00007ffc2d2b1000)
        libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fbd3624a000)
        /lib64/ld-linux-x86-64.so.2 (0x00007fbd3642c000)

Let's now see if we can cause our "helloWorld.exe" to print something other than "[*] Welcome to SecurityNik's world!". First the code:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
kali@securitynik:~/lkd/funcHook$ cat funcHooking.c 
#include <stdio.h>
#include <unistd.h>

// setup the original puts function. This structure must be the same as the original libc function
int puts(const char *myNewMsg)
  {
    // declare our 'malicious' function pointer.
    // This will point to the original puts function above
    int (*securitynik_puts) (const char *myNewMsg);
    int result;
   
    printf("[*] Making progress ... the value of result is:%d \n", result);
  }

Next we compile:

1
kali@securitynik:~/lkd/funcHook$ gcc funcHooking.c -o funcHooking.so -shared

Now that we have our shared object "funcHooking.so" file, let's set the "LD_PRELOAD" environment variable.

1
kali@securitynik:~/lkd/funcHook$ export LD_PRELOAD=/home/kali/lkd/funcHook/funcHooking.so 

Let's revisit the dependencies again using "ldd".

1
2
3
4
5
kali@securitynik:~/lkd/funcHook$ ldd ./helloWorld.exe 
        linux-vdso.so.1 (0x00007fff8afd7000)
        /home/kali/lkd/funcHook/funcHooking.so (0x00007f51e32f7000)
        libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f51e311c000)
        /lib64/ld-linux-x86-64.so.2 (0x00007f51e3303000)

We can see above that our funcHooking.so has been inserted. Let's now run "helloWorld.exe" again.

1
2
kali@securitynik:~/lkd/funcHook$ ./helloWorld.exe 
[*] Making progress ... the value of result is:32530 

Excellent. We were able to print something other than the original message. To confirm this actually works, let's unset the LD_PRELOAD environment variable and execute "helloWorld.exe" again.

Look at the dependencies again with "ldd"

1
2
3
4
kali@securitynik:~/lkd/funcHook$ ldd ./helloWorld.exe 
        linux-vdso.so.1 (0x00007fff7b9bd000)
        libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fa8ed5fa000)
        /lib64/ld-linux-x86-64.so.2 (0x00007fa8ed7dc000)

Out funcHooking.so file is no longer there. Let's run "./helloWorld.exe"

1
2
kali@securitynik:~/lkd/funcHook$ ./helloWorld.exe 
[*] Welcome to SecurityNik's world! 

While the above "worked", I don't believe it worked as it should have. Guess my understanding might have been wrong. Here is why I think so. I modified the hellWorld.c code to add a "printf" statement. 

1
2
3
4
5
6
7
8
9
kali@securitynik:~/lkd/funcHook$ cat helloWorld.c 
#include <stdio.h>

int main()
  {
    puts("[*] Welcome to SecurityNik's world! \n");
    printf("[*] Outputing with printf \n");
    return 0;
  }

This then produced upon execution.

1
2
3
kali@securitynik:~/lkd/funcHook$ ./helloWorld.exe 
[*] Making progress ... the value of result is:32678 
[*] Making progress ... the value of result is:32678 

So it seems we were able to execute the code within the "suspicious" shared object file but it did not work as expected. 

Clarifying my knowledge by modifying the "funcHooking.c" file more inline with the blog I am following:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
kali@securitynik:~/lkd/funcHook$ cat funcHooking.c 
// Need the define or may get an error when compiling about RTLD_NEXT undeclared
#define _GNU_SOURCE
#include <stdio.h>
#include <unistd.h>

#include <dlfcn.h> 

// For strcmp
#include <string.h>
// setup the original puts function. This structure must be the same as the original libc function
int puts(const char *myNewMsg)
  {
    // declare our 'malicious' function pointer.
    // This will point to the original puts function above
    int (*securitynik_puts) (const char *myNewMsg);
    int result;

    // Find the next occurrence of puts 
    // This allow for a wrapper around a function in another shared object
    securitynik_puts = dlsym(RTLD_NEXT, "puts");

    if (strcmp(myNewMsg, "[*] Welcome to SecurityNik's world! \n") == 0)
    {
      // if the strcmp matches then replace the text
      result = securitynik_puts("[*] Welcome to SecurityNik matrix!");
      printf("\tWe made progress ... \n");
    }
    else
    {
      // if the strcmp appear does not match print the original message
      // that is the message in the original function
      result = securitynik_puts(myNewMsg);
    }
    return result;
  }

Compiling the code and linking it with the "-ldl" argument

1
kali@securitynik:~/lkd/funcHook$ gcc funcHooking.c -o funcHooking.so -shared -ldl

Setting the LD_PRELOAD environment variable again, we see

1
2
3
4
5
6
7
8
kali@securitynik:~/lkd/funcHook$ export LD_PRELOAD=/home/kali/lkd/funcHook/funcHooking.so 

kali@securitynik:~/lkd/funcHook$ ldd helloWorld.exe 
        linux-vdso.so.1 (0x00007ffc245d6000)
        /home/kali/lkd/funcHook/funcHooking.so (0x00007fdeb8a84000)
        libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fdeb88a9000)
        libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007fdeb88a4000)
        /lib64/ld-linux-x86-64.so.2 (0x00007fdeb8a90000)

Executing "helloWorld.exe", we get:

1
2
3
4
kali@securitynik:~/lkd/funcHook$ ./helloWorld.exe 
[*] Welcome to SecurityNik matrix!
        We made progress ... 
[*] Outputing with printf 

Niceeee! That's progress.

That was a good learning for me. There is a lot more which can be done but at least I got enough of the basics in.

References:


No comments:

Post a Comment