Как извлечь сегмент двоичного файла на основе начальной и конечной шестнадцатеричных строк

У меня большой двоичный файл (несколько сотен гигабайт), и я хочу извлечь из него сегмент. Я знаю шестнадцатеричные строки начала и конца.

1 ответ

Возможное решение (при условии, что вы можете сделать копию файла) может использовать следующий пример

  1. предположим, что стартовый паттерн шестнадцатеричный 4f 0f 87 82
  2. Предположим, что конец шаблона является шестнадцатеричным fb 8c e2 a0
  3. Предположим, что входной файл называется tf и имеет длину 5000 байт

затем

сделать копию tf в новый файл blah с измененным стартовым шаблоном

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

теперь найти место, где tf а также blah отличаются (примечание - sed записывает дополнительный байт, содержащий символ новой строки в конце измененного файла, поэтому мы сравниваем до длины исходного файла, tf , Сгенерированный файл blah должен быть на один байт длиннее).

$ cmp -n 5000 -b tf blah

это даст смещение байта, bs, где файлы различаются, например,

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

Теперь сделайте то же самое для окончания шаблона

 $ 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

сейчас использую dd извлечь часть интереса

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

Некоторые дополнительные заметки:

  1. некоторые версии sed поддерживают -b опция, которая обрабатывает входной файл как двоичный. Другие версии имеют -z опция, которая разделяет строки символами NUL. В любом случае сопоставление шаблонов, содержащих новую строку, или разбиение на новую строку не было проверено.

  2. count=100 будет зависеть от длины сопоставляемого шаблона и от того, должен ли соответствующий шаблон быть включен в извлечение (это не было ясно в вопросе). Общая формула: count = (конечное смещение) - (начальное смещение) + (размер конечного шаблона). Части для конкретного примера 4433-4337+1, что дает 97 байтов. То есть от начала начального шаблона до первого байта конечного шаблона включительно. Затем добавляются дополнительные 3 байта, чтобы получить 100 в этом примере, потому что последний шаблон имел четыре байта, и пример включает в себя последний шаблон. Если окончательный шаблон не нужен, то count=96 будет значение.

  3. возможен подход, более устойчивый к новым строкам и использующий команду hexdump. Я не полностью проверил этот подход. По сути, он будет использовать hexdump с небольшим количеством sed, grep и tr для преобразования исходного двоичного файла в шестнадцатеричный формат в виде ascii. Затем можно применить тот же процесс, но с более сложной арифметикой и т. Д. Необходимая команда hexdump будет

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

  4. После hexdump шаг в том же процессе sed а также cmp может быть нанят. Соответствующий шаблон должен быть обновлен, чтобы использовать шестнадцатеричные символы ascii, а не исходный шестнадцатеричный текст.

  5. Этот подход должен также обрабатывать символы новой строки.

  6. LC_ALL=C По-видимому, по умолчанию требуется на OSX. Без этого sed команда выдает ошибку RE error: illegal byte sequence, Это может быть не так на всех платформах и / или дистрибутивах ОС.

Другие вопросы по тегам