Comment extraire un segment d'un fichier binaire basé sur des chaînes hexagonales de début et de fin

1

J'ai un gros fichier binaire (plusieurs centaines de Go) et je veux en extraire un segment. Je connais les chaînes hexagonales des points de début et de fin.

Hyatt
la source

Réponses:

2

Une solution possible (en supposant que vous puissiez faire une copie de fichier) pourrait utiliser l'exemple suivant

  1. supposer que le motif de départ est hex 4f 0f 87 82
  2. supposons que le motif de fin est hex fb 8c e2 a0
  3. supposer que le fichier d'entrée est appelé tf et a une longueur de 5000 octets

puis

faire une copie de tf vers un nouveau fichier blah avec motif de départ changé

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

maintenant trouver l'emplacement où tf et blah différer ( note - sed écrit un octet supplémentaire contenant une nouvelle ligne à la fin du fichier modifié. Nous comparons donc jusqu'à la longueur du fichier d'origine. tf. Le fichier généré blah devrait être un octet plus long ).

$ cmp -n 5000 -b tf blah

cela donnera un décalage d'octet, bs, où les fichiers diffèrent, par exemple,

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

maintenant faire la même chose pour le motif de fin

 $ 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

maintenant utiliser dd extraire une partie de l'intérêt

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

Quelques notes supplémentaires:

  1. certaines versions de sed supportent un -b option qui traite le fichier d'entrée comme binaire. D'autres versions ont un -z option qui sépare les lignes par des caractères NUL. Dans les deux cas, les motifs correspondants contenant une nouvelle ligne ou répartis sur une nouvelle ligne n'ont pas été testés.

  2. la count=100 dépendra de la longueur du motif trouvé et de la question de savoir si le motif choisi doit être inclus dans l'extrait (cela n'était pas clair dans la question). La formule générale est compte = (décalage de fin) - (décalage de début) + (taille du motif de fin) . Les pièces pour l'exemple spécifique sont 4433-4337 + 1, ce qui donne 97 octets. Cela va du début du motif de début jusqu'au premier octet du motif de fin inclus. Trois octets supplémentaires sont ensuite ajoutés pour donner 100 dans cet exemple, car le modèle final avait quatre octets et l'exemple comprend le modèle final. Si le motif final n'était pas voulu, alors count=96 serait la valeur.

  3. une approche plus robuste aux nouvelles lignes et l'utilisation de la commande hexdump est possible. Je n'ai pas complètement testé cette approche. Il utilisera essentiellement hexdump avec un peu de sed, grep et tr pour convertir le fichier binaire original en un fichier hexadécimal au format ascii. Ensuite, le même processus pourrait être appliqué, mais avec une arithmétique plus complexe, etc ... La commande hexdump nécessaire serait

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

  4. Après le hexdump suivre le même processus de sed et cmp pourrait être employé. Le modèle à faire correspondre devra être mis à jour pour utiliser des caractères ASCII hexdump et non l'impression hexadécimale brute.

  5. Cette approche devrait également gérer les caractères de nouvelle ligne.

  6. LC_ALL=C semble être nécessaire sur OSX par défaut. Sans elle la sed commande donne une erreur RE error: illegal byte sequence. Cela peut ne pas être vrai sur toutes les plateformes et / ou les distributions de système d'exploitation.

Chris Hill
la source
(1) Comment obtenez-vous 96? (Indice: réfléchissez-y. Je crois que c'est faux.) (2) Cela ne fonctionnera pas si l'un des octets connus est hexadécimal. 0A. Pouvez-vous étendre votre réponse pour couvrir ce cas? (3) est LC_ALL=C nécessaire? Pouvez-vous expliquer pourquoi? (4) De même, pouvez-vous expliquer pourquoi -n 5000 est nécessaire? (5) Veuillez rechercher “UUOC”. ………………………………………………………………………………………… S'il vous plaît ne répondez pas dans les commentaires; modifier votre réponse pour la rendre plus claire et plus complète.
G-Man
édité - merci pour info.
Chris Hill
Je voulais dire que je pensais 98 a eu tort (le 96 était une faute de frappe). En effet, votre réponse montre un exemple de motif de fin qui est quatre octets. Sinon, bon travail.
G-Man
Bien sûr, tout ce que vous avez à faire est taille = (décalage de fin) - (décalage de début) + (taille du motif de fin) . Briser le 4 en 1 + 3 ne fait qu'ajouter à la complication.
G-Man