Patch di un binario con dd


32

Ho letto questa citazione (sotto) più volte, di recente qui , e sono continuamente perplesso su come ddpuò essere usato per correggere qualsiasi cosa per non parlare di un compilatore:

Il sistema Unix che ho usato a scuola, 30 anni fa, era molto limitato nella RAM e nello spazio su disco. Soprattutto, il /usr/tmpfile system era molto piccolo, il che causava problemi quando qualcuno cercava di compilare un programma di grandi dimensioni. Ovviamente, gli studenti non dovevano scrivere "grandi programmi" comunque; i programmi di grandi dimensioni erano in genere codici sorgente copiati da "da qualche parte". Molti di noi copiato /usr/bin/cca /home/<myname>/cc, e utilizzato ddper patchare il binario da utilizzare /tmpal posto di/usr/tmp , che era più grande. Naturalmente, questo ha solo aggravato il problema: lo spazio su disco occupato da queste copie contava in quei giorni, e ora si /tmpriempiva regolarmente, impedendo ad altri utenti di modificare anche i propri file. Dopo aver scoperto cosa è successo, gli amministratori di sistema hanno fatto unchmod go-r /bin/* /usr/bin/* che "risolto" il problema e cancellato tutte le nostre copie del compilatore C.

(Enfasi mia)

La ddpagina man non dice nulla sul patching e non credo che potrebbe essere riutilizzato per farlo comunque.

I binari potrebbero davvero essere patchati dd? C'è qualche significato storico in questo?


3
Certo - solo odun file per i codici esadecimali di byte, trova l'offset di cui hai bisogno, decidi sulla tua modifica e la bs=$patchsize count=1 seek=$((offset/bs)) conv=notrunctua patch subito.
mikeserv

3
Qualcuno non ha mai sovrascritto un settore di avvio. ;)
Parthian Shot il

@ParthianShot In realtà ho sovrascritto una volta i primi ~ 260 MB del mio disco di avvio (+ root) con parte di un Debian LiveCD. O_o Ma non penso che sia davvero patch, hehehe ...
Amziraro,

1
O meglio, questo è il comportamento atteso e del tutto normale del Disk Destroyer: D
Amziraro,

Risposte:


73

Proviamolo. Ecco un banale programma C:

#include <stdio.h>
int main(int argc, char **argv) {
    puts("/usr/tmp");
}

Lo costruiremo in test:

$ cc -o test test.c

Se lo eseguiamo, stampa "/ usr / tmp".

Scopriamo dove " /usr/tmp" è nel binario:

$ strings -t d test | grep /usr/tmp
1460 /usr/tmp

-t d stampa l'offset in decimale nel file di ogni stringa trovata.

Ora facciamo un file temporaneo con solo " /tmp\0" al suo interno:

$ printf "/tmp\x00" > tmp

Quindi ora abbiamo il binario, sappiamo dove si trova la stringa che vogliamo cambiare e abbiamo un file con la stringa di sostituzione al suo interno.

Ora possiamo usare dd:

$ dd if=tmp of=test obs=1 seek=1460 conv=notrunc

Questo legge i dati dal tmp(nostro " /tmp\0" file), scrivendoli nel nostro binario, usando una dimensione del blocco di output di 1 byte, saltando all'offset che abbiamo trovato prima prima che scriva qualcosa e non troncando esplicitamente il file quando è fatto.

Possiamo eseguire l'eseguibile con patch:

$ ./test
/tmp

La stringa letterale che il programma stampa è stata modificata, quindi ora contiene " /tmp\0tmp\0", ma le funzioni di stringa si interrompono non appena vedono il primo byte null. Questo patching consente solo di rendere la stringa più corta o della stessa lunghezza e non più lunga, ma è adeguata per questi scopi.

Quindi non solo possiamo correggere le cose usando dd, ma l'abbiamo appena fatto.


1
Questo è eccellente ... e qualcosa che spero vivamente di non incontrare mai in un ambiente di produzione! Ho usato metodi simili in passato per ottenere numeri seriali in immagini esadecimali per microcontrollori, ma è fin troppo facile spararsi ai piedi.
Michael Shaw,

Se volessi dare istruzioni scritte a qualcuno su come patchare un particolare binario, preferirei dare loro una riga di comando per copiare / incollare piuttosto che dire loro "aprire il file in un editor esadecimale, trovare la /usr/tmpstringa, sostituirla con /tmp, don dimentica il \0byte finale , salva il file e incrocia le dita ". O, ancora meglio, uno script di shell che esegue prima un controllo di integrità, quindi chiama dd. Sfortunatamente, la necessità di cose come questa sorge spesso quando un vecchio software da un fornitore ormai defunto deve solo essere migrato su un nuovo sistema.
Guntram Blohm supporta Monica il

Sì, sed è meglio per questo genere di cose. Ma non hai completamente ragione sull'intero "Questo patching consente solo di rendere la stringa più corta o della stessa lunghezza e non più lunga". Stai assumendo che ti preoccupi dei dati che seguono immediatamente la stringa che desideri modificare o che non puoi avere la stringa successiva semplicemente come sottostringa della stringa originale. In altre parole, se ti trovi nella sezione .strings della memoria e hai "/ usr \ 0 / bin / bash \ 0", puoi trasformarlo in / usr / bin / bash semplicemente cambiando prima quello byte nullo e rendendolo "/ usr // bin / bash" (ad esempio).
Parthian sparato il

2
@ParthianShot - sed's non è migliore per questo genere di cose - non si può così expliciltly e precisamente limite sed' s in lettura / buffer di scrittura nel modo in cui si potrebbe con dd- che è tutta la ragione è stato mai utilizzato per questo, in primo luogo. Con ddte puoi arbitrariamente inserire un conteggio arbitrario di byte arbitrari. Non si può dire anche questo sed. Se qui ddviene usato come un bisturi, si applica sedcome una palla da demolizione.
Mikeserv,

Questo è un punto giusto (anche se abbastanza raro!) - Ci saranno occasioni in cui puoi allungare la stringa non preoccupandoti del risultato o di un altro dato arbitrario, ma specifico. Starò dalla dichiarazione generale, comunque.
Michael Homer,

9

Dipende da cosa intendi per "patch the binary".

Cambio binari a ddvolte. Ovviamente non esiste una tale funzionalità dd, ma può aprire file e leggere e scrivere cose con offset specifici, quindi se sai cosa scrivere dove, voilà c'è la tua patch.

Ad esempio avevo questo binario che conteneva alcuni dati PNG. Usa binwalkper trovare l'offset, ddper estrarlo (di solito binwalk estrae anche le cose ma la mia copia era difettosa), modificalo con gimp, assicurati che il file modificato abbia le stesse dimensioni o più piccolo di quello originale (cambiare offset non è qualcosa che puoi fare facilmente ), quindi utilizzare ddper rimettere in posizione l'immagine modificata.

$ binwalk thebinary
[…]
4194643    0x400153     PNG image, 800 x 160, 8-bit/color RGB, non-interlaced
[…]
$ dd if=nickel bs=1 skip=4194641 count=2 conv=swab | od -i
21869 # file size in this case - depends on the binary format
$ dd if=thebinary bs=1 skip=4194643 count=21869 of=theimage.png
$ gimp theimage.png
$ pngcrush myimage.png myimage.crush.png
# make sure myimage.crush.png is smaller than the original
$ dd if=myimage.crush.png of=thebinary bs=1 seek=4194643 conv=notrunc

A volte desidero anche sostituire le stringhe nei file binari (come percorso o nomi delle variabili). Anche se questo potrebbe essere fatto anche usando dd, è più semplice farlo usando sed. Devi solo assicurarti che la stringa che sostituisci abbia la stessa lunghezza della stringa originale in modo da non finire per cambiare gli offset.

sed -e s@/the/old/save/path@/the/new/save/path@ -i thebinary

o per prendere l'esempio di @ MichaelHomer con un 0 byte aggiunto in:

sed -e 's@/usr/tmp@/tmp\x00tmp@' -i test

Ovviamente devi verificare se effettivamente funziona dopo.


... supponendo che tu abbia un sedfile che gestisce bene i file binari, il che sembra essere il caso di gnu sed, ma non con molti dei vecchi sedche funzionavano solo con i file ASCII, ti sei confuso con qualsiasi altra cosa (specialmente se \0nell'input), e aveva restrizioni sulla lunghezza massima della linea.
Guntram Blohm supporta Monica il

1
busybox sedsembra essere in grado di cambiare bene i file binari ma non capisce \x00nella stringa di sostituzione come sedfa GNU . Richiede dei test, ma penso che valga la pena menzionarlo poiché è molto più semplice di dd- in alcuni casi. L'applicazione di patch ai file binari è un affare imperfetto in entrambi i casi.
frostschutz,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.