Как извлечь сегмент двоичного файла на основе начальной и конечной шестнадцатеричных строк
У меня большой двоичный файл (несколько сотен гигабайт), и я хочу извлечь из него сегмент. Я знаю шестнадцатеричные строки начала и конца.
1 ответ
Возможное решение (при условии, что вы можете сделать копию файла) может использовать следующий пример
- предположим, что стартовый паттерн шестнадцатеричный 4f 0f 87 82
- Предположим, что конец шаблона является шестнадцатеричным fb 8c e2 a0
- Предположим, что входной файл называется
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
Некоторые дополнительные заметки:
некоторые версии sed поддерживают
-b
опция, которая обрабатывает входной файл как двоичный. Другие версии имеют-z
опция, которая разделяет строки символами NUL. В любом случае сопоставление шаблонов, содержащих новую строку, или разбиение на новую строку не было проверено.count=100
будет зависеть от длины сопоставляемого шаблона и от того, должен ли соответствующий шаблон быть включен в извлечение (это не было ясно в вопросе). Общая формула: count = (конечное смещение) - (начальное смещение) + (размер конечного шаблона). Части для конкретного примера 4433-4337+1, что дает 97 байтов. То есть от начала начального шаблона до первого байта конечного шаблона включительно. Затем добавляются дополнительные 3 байта, чтобы получить 100 в этом примере, потому что последний шаблон имел четыре байта, и пример включает в себя последний шаблон. Если окончательный шаблон не нужен, тоcount=96
будет значение.возможен подход, более устойчивый к новым строкам и использующий команду 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
После
hexdump
шаг в том же процессеsed
а такжеcmp
может быть нанят. Соответствующий шаблон должен быть обновлен, чтобы использовать шестнадцатеричные символы ascii, а не исходный шестнадцатеричный текст.Этот подход должен также обрабатывать символы новой строки.
LC_ALL=C
По-видимому, по умолчанию требуется на OSX. Без этогоsed
команда выдает ошибкуRE error: illegal byte sequence
, Это может быть не так на всех платформах и / или дистрибутивах ОС.