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:
https://www.linuxjournal.com/article/7795
http://optumsoft.com/dangers-of-using-dlsym-with-rtld_next/
http://www.vishalchovatiya.com/hack-c-cpp-application-using-rtld-next-with-an-easy-example/
http://optumsoft.com/dangers-of-using-dlsym-with-rtld_next/
http://www.vishalchovatiya.com/hack-c-cpp-application-using-rtld-next-with-an-easy-example/
No comments:
Post a Comment