Patchen einer Binärdatei mit dd

32

Ich habe dieses Zitat (unten) einige Male gelesen, zuletzt hier , und bin ständig verwirrt darüber, wie ddman etwas patchen kann, geschweige denn einen Compiler:

Das Unix-System, das ich vor 30 Jahren in der Schule verwendet habe, war in Bezug auf RAM und Festplattenspeicher sehr begrenzt. Insbesondere das /usr/tmpDateisystem war sehr klein, was zu Problemen führte, wenn jemand versuchte, ein großes Programm zu kompilieren. Natürlich sollten die Schüler sowieso keine "großen Programme" schreiben; Bei großen Programmen handelte es sich normalerweise um Quellcodes, die von "irgendwo" kopiert wurden. Viele von uns kopiert /usr/bin/cczu /home/<myname>/cc, und verwendet dddie binäre Patch zu verwenden , /tmpstatt/usr/tmp , die größer war. Dies machte das Problem natürlich nur noch schlimmer - der von diesen Kopien belegte Speicherplatz spielte damals eine Rolle und wurde jetzt /tmpregelmäßig gefüllt, sodass andere Benutzer ihre Dateien nicht einmal bearbeiten konnten. Nachdem sie herausgefunden hatten, was passiert war, taten die Sysadmins achmod go-r /bin/* /usr/bin/* was das Problem "behoben" und alle unsere Kopien des C-Compilers gelöscht.

(Betonung meiner)

Die ddMan-Page sagt nichts über das Patchen aus und ich glaube nicht, dass es trotzdem sinnvoll sein könnte, dies zu tun.

Könnten Binaries wirklich gepatcht werden dd? Hat dies eine historische Bedeutung?

Amziraro
quelle
3
Klar - nur odeine Datei für die Byte-Hex-Codes, den benötigten Offset finden, über die Bearbeitung und bs=$patchsize count=1 seek=$((offset/bs)) conv=notruncden Patch direkt in entscheiden.
mikeserv
3
Jemand hat noch nie einen Bootsektor überschrieben. ;)
Parthian Shot
@ParthianShot Eigentlich habe ich die ersten ~ 260MB meines Bootlaufwerks (+ root) einmal mit einem Teil einer Debian LiveCD überschrieben. O_o Aber ich denke nicht, dass das wirklich
flickend
1
Oder besser gesagt, das ist das erwartete und völlig normale Verhalten des Disk Destroyer: D
Amziraro

Antworten:

73

Lass es uns versuchen. Hier ist ein triviales C-Programm:

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

Das bauen wir ein in test:

$ cc -o test test.c

Wenn wir es ausführen, gibt es "/ usr / tmp" aus.

Lassen Sie uns herausfinden, wo sich " /usr/tmp" in der Binärdatei befindet:

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

-t d druckt den Offset in Dezimalzahl in die Datei jeder gefundenen Zeichenfolge.

Jetzt erstellen wir eine temporäre Datei mit nur " /tmp\0" darin:

$ printf "/tmp\x00" > tmp

Jetzt haben wir also die Binärdatei, wissen, wo sich die Zeichenfolge befindet, die geändert werden soll, und haben eine Datei mit der Ersatzzeichenfolge.

Jetzt können wir verwenden dd:

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

Dies liest Daten aus tmp(unserer " /tmp\0" Datei), schreibt sie in unsere Binärdatei, verwendet eine Ausgabeblockgröße von 1 Byte, überspringt den zuvor gefundenen Versatz, bevor etwas geschrieben wird, und schneidet die Datei nicht explizit ab, wenn dies erledigt ist.

Wir können die gepatchte ausführbare Datei ausführen:

$ ./test
/tmp

Das vom Programm ausgedruckte Zeichenfolgenliteral wurde geändert und enthält nun " /tmp\0tmp\0". Die Zeichenfolgenfunktionen werden jedoch beendet, sobald das erste Nullbyte angezeigt wird. Dieses Patchen erlaubt nur, die Saite kürzer oder gleich lang und nicht länger zu machen, aber es ist für diese Zwecke ausreichend.

Wir können also nicht nur Dinge patchen dd, wir haben es auch getan.

Michael Homer
quelle
1
Das ist exzellent ... und ich hoffe sehr, dass ich es in einer Produktionsumgebung nie antreffen werde! Ich habe in der Vergangenheit ähnliche Methoden angewendet, um Seriennummern für Mikrocontroller in hexadezimale Bilder umzuwandeln. Es ist jedoch viel zu einfach, sich selbst in den Fuß zu schießen.
Michael Shaw
Wenn ich jemandem schriftliche Anweisungen zum Patchen einer bestimmten Binärdatei geben möchte, gebe ich ihm lieber eine Befehlszeile zum Kopieren / Einfügen, als ihm mitzuteilen, dass er die Datei in einem Hex-Editor öffnen, die /usr/tmpZeichenfolge suchen und durch " /tmpdon" ersetzen soll Vergiss das letzte \0Byte nicht, speichere die Datei und drücke die Daumen ". Oder, noch besser, ein Shell-Skript, das zuerst die Richtigkeit überprüft und dann aufruft dd. Leider ergibt sich die Notwendigkeit für Sachen wie diese häufig auf, wenn ein altes Stück Software , die von einem heute nicht mehr existierenden Anbietern nur hat zu einem neuen System migriert werden.
Guntram Blohm unterstützt Monica
Ja, sed ist besser für so etwas. Aber Sie haben in Bezug auf das Ganze nicht ganz recht "Mit diesem Patch können Sie die Saite nur kürzer oder gleich lang und nicht länger machen". Sie gehen davon aus, dass Sie sich um die Daten kümmern, die unmittelbar auf die zu ändernde Zeichenfolge folgen, oder dass die nächste Zeichenfolge nicht einfach eine Teilzeichenfolge der ursprünglichen Zeichenfolge sein kann. Mit anderen Worten, wenn Sie sich im Abschnitt .strings des Speichers befinden und "/ usr \ 0 / bin / bash \ 0" haben, können Sie dies in / usr / bin / bash umwandeln, indem Sie dies einfach zuerst ändern null Byte und mache es zu "/ usr // bin / bash" (zum Beispiel).
Parthian Shot
2
@ParthianShot - sed‚s nicht besser für diese Art der Sache - man kann nicht so expliciltly und genau Limit sed‘ s Schreib- / Lesepuffer in der Art und Weise Sie könnte mit dd- was der ganze Grund ist es immer dafür in erster Linie verwendet wurde. Mit können ddSie eine beliebige Anzahl beliebiger Bytes beliebig platzieren. Dies kann auch nicht gesagt werden sed. Wenn ddhier wie ein Skalpell verwendet wird, würden Sie sedwie eine Abrissbirne anwenden .
mikeserv
Das ist ein fairer (wenn auch ziemlich seltener!) Punkt - es wird Fälle geben, in denen Sie die Zeichenfolge verlängern können, indem Sie sich nicht um das Ergebnis oder ein anderes willkürliches, aber spezifisches Datenelement kümmern. Ich werde jedoch zu der allgemeinen Aussage stehen.
Michael Homer
9

Es kommt darauf an, was Sie unter "Patchen der Binärdatei" verstehen.

Ich ändere ddmanchmal die Binärdateien mit . Natürlich gibt es keine solche Funktion dd, aber sie kann Dateien öffnen und Dinge an bestimmten Offsets lesen und schreiben. Wenn Sie also wissen, was Sie wo schreiben sollen, gibt es Ihren Patch.

Zum Beispiel hatte ich diese Binärdatei, die einige PNG-Daten enthielt. Verwenden Sie binwalk, um den Versatz zu finden, ddum ihn zu extrahieren (normalerweise extrahiert binwalk auch Dinge, aber meine Kopie war fehlerhaft), bearbeiten Sie ihn mit gimp, und stellen Sie sicher, dass die bearbeitete Datei dieselbe Größe oder kleiner als die ursprüngliche ist (das Ändern von Versätzen ist nicht einfach möglich) ), und verwenden Sie dann dd, um das geänderte Bild wieder in Position zu bringen.

$ 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

Manchmal möchte ich auch Zeichenfolgen in Binärdateien ersetzen (z. B. Pfad- oder Variablennamen). Dies könnte auch mit erfolgen dd, es ist jedoch einfacher, dies zu tun sed. Sie müssen nur sicherstellen, dass die Zeichenfolge, durch die Sie ersetzen, dieselbe Länge wie die ursprüngliche Zeichenfolge hat, damit Sie nicht die Offsets ändern.

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

oder um das Beispiel von @ MichaelHomer mit einem 0-Byte aufzuheben, das hinzugefügt wurde in:

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

Natürlich muss man danach nachprüfen, ob es tatsächlich funktioniert.

Frostschutz
quelle
... vorausgesetzt, Sie haben eine sed, die mit Binärdateien gut umgehen kann sed, was bei gnu der Fall zu sein scheint , aber nicht bei vielen älteren seds, die nur mit ASCII-Dateien gearbeitet \0haben. und hatte Einschränkungen für die maximale Leitungslänge.
Guntram Blohm unterstützt Monica
1
busybox sedscheint in der Lage zu sein, Binärdateien zu ändern, versteht aber \x00in der Ersetzungszeichenfolge nicht, wie es GNU sedtut. Es muss getestet werden, aber ich denke, es ist erwähnenswert, da es so viel einfacher ist als dd- für einige Fälle. Das Patchen von Binärdateien ist in beiden Fällen ein Problem.
Frostschutz