So extrahieren Sie ein Segment einer Binärdatei basierend auf Start- und Endzeichen von Hex-Strings

729
Hyatt

Ich habe eine große Binärdatei (mehrere hundert GB) und möchte ein Segment daraus extrahieren. Ich kenne die Hex-Zeichenfolgen der Anfangs- und Endpunkte.

1

1 Antwort auf die Frage

2
Chris Hill

Eine mögliche Lösung (vorausgesetzt, Sie können eine Kopie der Datei erstellen) kann das folgende Beispiel verwenden

  1. Es wird angenommen, dass das Startmuster hexadezimal 4f 0f 87 82 ist
  2. Es sei angenommen, dass das Endmuster hex fb 8c e2 a0 ist
  3. Angenommen, die Eingabedatei wird aufgerufen tfund hat eine Länge von 5000 Byte

dann

Kopie tfeiner neuen Datei blahmit geändertem Startmuster erstellen

$ LC_ALL=C sed 's/'`printf "\x4f\x0f\x87\x82"`'/'`printf "AAAA"`'/' <tf > blah 

Suchen Sie nun den Ort, an dem sich die Dateien befinden,tf und blahunterscheiden Sie sich ( Note-Sed schreibt ein zusätzliches Byte mit einem Zeilenumbruch am Ende der geänderten Datei, sodass wir bis zur Länge der Originaldatei vergleichen tf. Die generierte Datei blahsollte ein Byte länger sein ).

$ cmp -n 5000 -b tf blah 

Dies gibt einen Byte-Offset, bs, bei dem sich Dateien unterscheiden, z.

tf blah differ: byte 4337, line 10 is 117 O 101 A 

mache jetzt dasselbe für das Endmuster

 $ LC_ALL=C sed 's/'`printf "\xfb\x8c\xe2\xa0"`'/'`printf "AAAA"`'/' < tf > blah2 $ cmp -n 5000 -b tf blah2 tf blah2 differ: byte 4433, line 10 is 373 ? 101 A 

Jetzt verwenden dd, um einen Teil des Interesses zu extrahieren

dd if=tf skip=4336 bs=1 count=100 > fbit 

Einige zusätzliche Hinweise:

  1. Einige Versionen von Sed unterstützen eine -bOption, die die Eingabedatei als binär behandelt. Andere Versionen haben eine -zOption, die Zeilen durch NUL-Zeichen voneinander trennt. Entweder wurden übereinstimmende Muster, die eine neue Zeile enthalten, oder über eine neue Zeile aufgeteilt, nicht getestet.

  2. das count=100hängt von der Länge des angepaßten Musters abhängen und ob das angepasste Muster ist in dem Extrakt enthalten sein (das war in der Frage nicht klar). Die allgemeine Formel lautet count = (Endoffset) - (Startoffset) + (Größe des Endmusters) . Die Teile für das spezifische Beispiel sind 4433-4337 + 1, was 97 Bytes ergibt. Dies ist vom Beginn des Anfangsmusters bis einschließlich des ersten Bytes des Endmusters. Dann werden zusätzliche 3 Bytes hinzugefügt, um in diesem Beispiel 100 zu ergeben, da das Endmuster vier Bytes hatte und das Beispiel das Endmuster enthält. Wenn das endgültige Muster nicht erwünscht count=96wäre, wäre dies der Wert.

  3. Ein Ansatz, der robuster gegenüber neuen Zeilen ist und den Befehl hexdump verwendet, ist möglich. Ich habe diesen Ansatz nicht vollständig getestet. Es würde im Wesentlichen hexdump mit ein wenig sed, grep und tr verwenden, um die ursprüngliche Binärdatei in ein hexadezimales ASCII-Format zu konvertieren. Dann könnte derselbe Prozess angewendet werden, aber mit mehr fummeliger Arithmetik usw. Der erforderliche Hexdump-Befehl wäre

    hexdump -v -x tf | sed s/'^[0-9]*\(.*\)/\1/' | sed s'/ *//g' | grep '[0-9]' | tr -d '\n' > tf.txt

  4. Nach dem hexdumpSchritt kann das gleiche Verfahren von sedund cmpangewendet werden. Das übereinstimmende Muster muss aktualisiert werden, um Hex-Dump-ASCII-Zeichen und nicht den Roh-Hex-Druck zu verwenden.

  5. Dieser Ansatz sollte auch Zeilenumbrüche berücksichtigen.

  6. LC_ALL=Cscheint unter OSX standardmäßig erforderlich zu sein. Ohne sie sedgibt der Befehl einen Fehler aus RE error: illegal byte sequence. Dies gilt möglicherweise nicht für alle Plattformen und / oder Betriebssystemdistributionen.

(1) Wie bekommst du 96? (Hinweis: Denken Sie darüber nach. Ich glaube, dass es falsch ist.) (2) Dies funktioniert nicht, wenn eines der bekannten Bytes hexadezimal '0A' ist. Können Sie Ihre Antwort auf diesen Fall ausweiten? (3) Wird `LC_ALL = C` benötigt? Kannst du erklären warum? (4) Können Sie auf ähnliche Weise erklären, warum "-n 5000" benötigt wird? (5) Bitte recherchieren Sie „UUOC“. ……………………………………………………………………………………… Bitte antworten Sie nicht in Kommentaren; Bearbeiten Sie Ihre Antwort, um sie klarer und vollständiger zu machen. G-Man vor 6 Jahren 0
bearbeitet - thx für info. Chris Hill vor 6 Jahren 0
Ich wollte damit sagen, dass ich dachte, dass "98" falsch war (die "96" war ein Tippfehler). Dies liegt daran, dass Ihre Antwort ein Beispiel für ein Endemuster zeigt, das aus vier Bytes besteht. Ansonsten gute Arbeit. G-Man vor 6 Jahren 0
Alles was Sie tun müssen, ist natürlich ** size = (Endoffset) - (Startoffset) + (Größe des Endmusters) **. Das Zerlegen der 4 in 1 + 3 ist eine weitere Komplikation. G-Man vor 6 Jahren 0