2010-10-27 7 views
9

Supponiamo di disporre di un binario ELF collegato in modo dinamico e di sovrascrivere/reindirizzare determinate chiamate di libreria. So che posso farlo con LD_PRELOAD, ma voglio una soluzione permanente nel binario, indipendente dall'ambiente, e che funzioni per i binari setuid/setgid, nessuno dei quali può raggiungere LD_PRELOAD.Patching di codice/simboli in un binario ELF con collegamento dinamico

Quello che mi piacerebbe fare è aggiungere codice da file oggetto aggiuntivi (eventualmente in nuove sezioni, se necessario) e aggiungere i simboli da questi file oggetto alla tabella dei simboli del binario in modo che la nuova versione aggiunta del codice venga usato al posto del codice della libreria condivisa. Credo che questo dovrebbe essere possibile senza effettivamente effettuare alcuna delocalizzazione nel codice esistente; anche se sono nello stesso file, questi dovrebbero essere risolti in fase di esecuzione nel solito modo PLT (per quello che vale mi interessa solo le funzioni, non i dati).

Per favore non darmi risposte sulla falsariga di "Non vuoi farlo!" o "Non è portatile!" Quello su cui sto lavorando è un modo per interfacciare i binari con implementazioni di libreria condivisa alternative leggermente ABI-incompatibili. La piattaforma in questione è i386-linux (cioè 32 bit) se è importante. A meno che non mi sbagli su ciò che è possibile, potrei scrivere alcuni strumenti per analizzare i file ELF ed eseguire i miei hack, ma sospetto che ci sia un modo elegante per usare il linker GNU e altri strumenti per realizzare ciò senza scrivere un nuovo codice.

+0

Non so se questo è funziona tutto per te, ma controlla il comando di sistema 'nm' (probabilmente lo sai già). Fornisce un po 'di informazioni su un così. – Marm0t

+0

Wow, il trucco LD_PRELOAD sembra divertente! Anche io sto cercando un modo per farlo nel binario. Il mio problema è che il mio file binario ha un simbolo che il linker del mio BeagleBone non può risolvere. – CJxD

risposta

5

Suggerisco il elfsh et al. strumenti dal progetto ERESI, se si desidera strumentare i file ELF stessi. La compatibilità con i386-linux non è un problema, dato che l'ho usato io stesso per lo stesso scopo.

Le istruzioni pertinenti sono here.

+0

Sembra che ci vorrà un po 'di lettura, ma penso che questo sia lo strumento che stavo cercando. Grazie! –

+0

Esiste * una documentazione * per ERESI? Non riesco a trovare alcun "inizio", esempi, ecc. –

+0

Hmm, sembra che non ci sia nessuno (tutti i link puntano a svn?). –

0

È possibile gestire alcuni dei collegamenti dinamici nel proprio programma. Leggi la pagina man per dlsym (3) in particolare, e dlopen (3), dlerror (3) e dlclose (3) per il resto dell'interfaccia di collegamento dinamico.

Un semplice esempio: ad esempio, voglio eseguire l'override di dup2 (2) da libc. Ho potuto utilizzare il seguente codice (chiamiamolo "dltest.c"):

#define _GNU_SOURCE 

#include <stdio.h> 
#include <stdlib.h> 
#include <unistd.h> 
#include <dlfcn.h> 

int (*prev_dup2)(int oldfd, int newfd); 

int dup2(int oldfd, int newfd) { 
    printf("DUP2: %d --> %d\n", oldfd, newfd); 
    return prev_dup2(oldfd, newfd); 
} 

int main(void) { 
    int i; 

    prev_dup2 = dlsym(RTLD_NEXT, "dup2"); 
    if (!prev_dup2) { 
     printf("dlsym failed to find 'dup2' function!\n"); 
     return 1; 
    } 
    if (prev_dup2 == dup2) { 
     printf("dlsym found our own 'dup2' function!\n"); 
     return 1; 
    } 

    i = dup2(1,3); 
    if (i == -1) { 
     perror("dup2() failed"); 
    } 

    return 0; 
} 

Compilare con:

gcc -o dltest dltest.c -ldl 

La funzione dup2 collegata in modo statico() sostituisce il dup2() dalla libreria. Funziona anche se la funzione si trova in un altro file .c (ed è compilata come separata .o).

Se le funzioni di override sono a loro volta collegate dinamicamente, è possibile utilizzare dlopen() anziché affidarsi al linker per ottenere le librerie nell'ordine corretto.

EDIT: Sospetto che se una funzione diversa all'interno della libreria sostituita chiama una funzione sostituita, viene richiamata la funzione originale anziché l'override. Non so cosa succederà se una libreria dinamica chiama un altro.

+0

Sto provando a modificare i binari, non la fonte. –

2

ld ha l'opzione --wrap che consente di sostituire un dato simbolo come malloc con un simbolo che si chiama __wrap_malloc. Con ciò potresti scrivere alcuni stub per le funzioni che ti interessano e collegarli alla libreria in questione.

+0

Ancora una volta questa domanda riguarda l'applicazione di patch ai file binari, non il wrapping delle chiamate alle librerie nei programmi che compilo. –

+0

R .: Non vedo perché non puoi fare ciò che hai chiesto nella tua domanda con quello che propongo. A '__wrap_malloc' non è necessario chiamare il vecchio' malloc', sostituisce semplicemente un simbolo con un altro simbolo. 'ld' è lo strumento migliore per manipolare i binari che conosco, portatile, flessibile, tutto ciò che hai richiesto. Ma sembri avere certi tipi di risposte nella tua testa, che non si riflettono necessariamente nella tua domanda. –

+0

Se vuoi dire che c'è un modo per prendere un file ELF eseguibile esistente e aggiungere del codice al suo interno per definire alcuni simboli che sarebbero altrimenti risolti nel codice della libreria condivisa, usando solo GNU 'ld', mi piacerebbe sapere come. Ma tieni presente che i programmi di input a cui questo deve essere applicato sono file ELF eseguibili, non i file o l'origine '.o'. –

1

Non riesco a aggiungere commenti a questa domanda, quindi pubblicandolo come una "risposta". Mi dispiace, lo faccio solo per aiutare, sperabilmente, altre persone che cercano una risposta.

Quindi, mi sembra di avere usecase simile, ma in modo esplicito a trovare alcuna modifica al file binari esistenti inaccettabili (per me), quindi sto cercando standalone approccio delega: Proxy shared library (sharedlib, shlib, so) for ELF?