Muitas pessoas utilizam, utilizaram ou vão utilizar a variável LD_PRELOAD, e por sua vez nem sempre sabem para que ela serve! Caso este seja o seu problema, problema este não mais será!!
O que acontece basicamente e que o linker dinâmico do Linux (assim como em tantos outros sistemas operacionais) utiliza diversas formas, alguma delas sendo através de variáveis de ambiente para controlar seu comportamento. Sendo que neste caso a variável LD_PRELOAD informa ao linker dinâmico que carregue as bibliotecas listadas nela antes de carregar quaisquer outras bibliotecas necessárias, enquando LD_LIBRARY_PATH especifica um caminho alternativo para usar ao procurar bibliotecas que serão carregadas.
Partindo deste principio podemos fazer com que um programa a ser executado seja “hijacked” por outro programa, ou seja. Podemos fazer por exemplo que a função hehe() previamente chamada pelo programa “A” tenha seu comportamento alterado sem precisar fazer quaisquer alteração no programa “A”. Um pouco complexo? talvez! Mais vamos por a mão na massa! hands on!
Digamos que você tem o programa “main” conforme o código de exemplo abaixo, perceba que o código e super simples. apenas declaro um ponteiro de caracteres, aloco memória e em seguida copio uma sequência de caracteres para o ponteiro previamente alocado. Simples, certo?
1) Abaixo código de exemplo de nosso “main.c” ou clique aqui para download.
/* * Filename: hijack_main.c * Created: Wed Jun 9 22:11:12 BRT 2010 * Author: Jorge Pereira <jpereiran@gmail.com> */ #include <stdio.h> #include <stdlib.h> #include <string.h> int main (int argc, char* argv[]) { char* nome = (char*)malloc (100); strcpy (nome, "Jorge Pereira"); printf ("NOME: %s\n", nome); free (nome); return 0; }
# Vamos compilar e executar o nosso exemplo “main.c”
$ gcc -Wall -o main main.c $ ./main NOME: Jorge Pereira $
Até aqui tudo bem, porém imagine você em uma determinada situação em que precisa saber quantos bytes está sendo alocado por um determinado programa? e você por alguns instantes imagina sobre a possibilidade de poder fazer algum tipo de “overload” de uma determinada função na qual você conhece sua assinatura. (Digamos, você sabe a assinatura do método, quantidade e tipos dos parâmetros, …).
Pois bem, neste exemplo que irei demonstrar será para sobrecarregar todas as chamadas feitas pelo meu programa “main” às funções malloc() e free() e em seguida exibir uma mensagem no caso do malloc() imprimindo seu parâmetro que e o tamanho de bytes alocados, e na função free() exibindo os ponteiros que foram liberados.
Neste caso, iremos criar uma biblioteca chamada “libhijack_hehe.so” que será carregada através da variável mágica LD_PRELOAD em parceria com nosso querido linker dinâmico.
2) Abaixo código de exemplo de “libhijack_hehe.c”, ou clique aqui para download.
/* * Filename: hijack_hehe.c * Created: Wed Jun 9 22:11:12 BRT 2010 * Author: Jorge Pereira <jpereiran@gmail.com> */ #define _GNU_SOURCE #include <stdint.h> #include <stdio.h> #include <stdlib.h> #include <stdarg.h> #include <dlfcn.h> #define HIJACK_DEBUG(fmt, ...) \ fprintf(stderr, " ** DEBUG: %s:%d %s(): "fmt"\n", \ __FILE__, __LINE__, __PRETTY_FUNCTION__, ##__VA_ARGS__) static void* (*hack_malloc)(size_t size) = NULL; static void (*hack_free)(void *p) = NULL; static void* rest_malloc = NULL; void* malloc (size_t size) { if (hack_malloc == NULL) { hack_malloc = (void *(*)(size_t)) dlsym (RTLD_NEXT, "malloc"); rest_malloc = NULL; } if (rest_malloc == NULL) { rest_malloc = hack_malloc (size); HIJACK_DEBUG ("Alocando (%d) bytes, chunck(%p)", size, (void*)rest_malloc); return rest_malloc; } hack_malloc = NULL; return rest_malloc; } void free (void *p) { HIJACK_DEBUG ("Desalocando (%p)", p); if (hack_free == NULL) { hack_free = (void (*)(void *)) dlsym(RTLD_NEXT, "free"); } hack_free (p); }
Agora vamos compilar, executar e analisar o comportamento.
$ gcc -Wall -shared -ldl -o libhijack_hehe.so hijack_hehe.c $ LD_PRELOAD=./libhijack_hehe.so ./main ** DEBUG: hijack_hehe.c:35 malloc(): Alocando (100) bytes, chunck(0x9273008) NOME: Jorge Pereira ** DEBUG: hijack_hehe.c:46 free(): Desalocando (0x9273008) $
Percebeu algo diferente na execução com a LD_PRELOAD passando como parâmetro a nossa libhijack_hehe.so? pois bem, todas as chamadas às funções malloc() e free() foram sobrecarregadas e passaram a se comportar conforme as versões que escrevi em hijack_hehe.c. Caso tenha ficado curioso, e so re-escrever tais exemplos com outras funções que você deseja sobrecarregar e ver o comportamento. Lembrando que basta utilizar a criatividade e perceberá na quantidade de coisas que podem ser feita com tal técnica.
Exemplo: Nas funções que fazem checagem com strcmp(), uso da crypt(), … entre outras.
Referências
- man 8 ld.so
Autor: Jorge Pereira
Data: Wed Jun 9 23:42:26 BRT 2010
0sem comentários ainda