Sobreescrevendo chamadas de função com LD_PRELOAD

Nosso famoso dynamic-linker/loader `ld.so' fornece dentre vários recursos, um que nos permite carregar uma biblioteca dinâmica antes de qualquer outra de uma programa. E ele faz isso por meio da variável de ambiente LD_PRELOAD.

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 binaries, only libraries in the standard search directories that are also setgid will be loaded.

-- man ld.so

Sendo assim, nós conseguimos interceptar/substituir/sobreescrever uma função de um biblioteca que é chamada depois da que está no preload.

Vamos fazer um teste, vamos sobreescrever a função puts() da libc!

Primeiro o código da nossa shared library:

#define _GNU_SOURCE /* requerido para RTLD_NEXT */
#include <dlfcn.h>
#include <stdio.h>
 
void __attribute__((constructor)) init(void);
 
int (*orig_puts)(const char *s);
 
int puts(const char *s) {
	orig_puts("puts() sobreescrita!");
	orig_puts(s);
	return 0;
}
 
void init(void) {
	orig_puts = dlsym(RTLD_NEXT, "puts");
}

Repare no código acima que nós usamos a função dlsym() com RTLD_NEXT para obter o ponteiro para função "puts" do próximo objeto que o defina na ordem de carregamento, dessa forma podemos utilizar a função que seria chamada sem o preload.

Note também que fizemos isso em uma função com atributo de construtor, este atributo indica que a função é o construtor da nossa biblioteca, e que é executada automaticamente antes da main(). Antes isso era feito chamando uma função de "_init".

Compilamos com:

gcc -shared -fPIC -o puts.so puts.c -ldl

E o código do nosso programa de exemplo:

#include <stdio.h>
 
int main(int argc, char **argv) {
	puts("Hello world!\n");
 
	return 0;
}

Compilamos com:

gcc -o hello hello.c

E então testando teremos:

$ LD_PRELOAD=./puts.so ./hello
puts() sobreescrita!
Hello world!

Referências

- http://linux.die.net/man/8/ld-linux
- http://hackerboss.com/overriding-system-functions-for-fun-and-profit/
- http://pubs.opengroup.org/onlinepubs/009695399/functions/dlsym.html
- http://tldp.org/HOWTO/Program-Library-HOWTO/miscellaneous.html

Post new comment

The content of this field is kept private and will not be shown publicly.
  • Web page addresses and e-mail addresses turn into links automatically.
  • Allowed HTML tags: <a> <em> <strong> <cite> <code> <ul> <ol> <li> <dl> <dt> <dd>
  • Lines and paragraphs break automatically.

More information about formatting options