On Linux, you can do pretty neat tricks with dynamic libraries.
Theory
The manpage of ld.so tells us :
LD_PRELOAD A whitespace-separated list of additional, user-specified, ELF shared libraries to be loaded before all others. This can be used to selectively override functions in other shared libraries. For setuid/setgid ELF bina‐ ries, only libraries in the standard search directories that are also setgid will be loaded.
Nice, we are able to put some libraries before others, without recompiling. Soooooooo, we can force a program to use our functions instead of the dynamically loaded ones.
Example
Given a code like this:
#include <stdio.h>
#include <string.h>
char* KEY = "secret";
int main(int argc, char* argv[]){
if(argc <2){
printf("Usage: %s <secret_password>n", argv[0]);
return 1;
}
if(! strcmp(KEY, argv[1]))
printf("Goodboyn");
else
printf("Badboyn");
return 0;
}
It would be nice if we could replace the strcmp function with something more verbose, like this:
int strcmp(const char* s1, const char* s2){
printf("s1: %sn", s1);
printf("s2: %sn", s2);
return 0;
}
Our function always returns 0 (Which means "strings are equals" in regular strcmp) and shows us the two strings.
$ gcc -fPIC -c strcmp.c -o strcmp.o
$ gcc -shared -o strcmp.so strcmp.o
This will compile our crafted strcmp function as a shared lib.
$ LD_PRELOAD="./live_patch.so" a.out azerty
s1: secret
s2: azerty
Goodboy
Woot !
Even more fun
Remember the ptrace trick to detect debugging ? It can be bypassed by a custom ptrace function:
int ptrace(int request, int pid, int addr, int data){
return 0;
}
Of course, this need to be adapted if a more elaborate trick than ptrace(PTRACE_TRACEME, ...) is used.
But this can be countered by looking at the environment variables, with, for example, the getenv function. So, we could do this to counter this counter-measure:
char *getenv(const char *name){
return 0;
}
And so on ;)
Resources
- securityvulns.ru
- The manpage of ld.so
- A lot of useful tools are using this trick : libeatmydata, installwatch, libshape, electricfence, libglfps...