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

627
Hyatt

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

1

1 ответ на вопрос

2
Chris Hill

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

  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. Это может быть не так на всех платформах и / или дистрибутивах ОС.

(1) Как вы получаете `96`? (Подсказка: подумайте об этом. Я считаю, что это неправильно.) (2) Это не сработает, если один из известных байтов имеет шестнадцатеричное `0A`. Можете ли вы расширить свой ответ на этот случай? (3) Нужно ли `LC_ALL = C`? Вы можете объяснить, почему? (4) Точно так же, можете ли вы объяснить, почему необходим ключ -n 5000? (5) Пожалуйста, исследуйте «UUOC». …………………………………………………………………………………………… Пожалуйста, не отвечайте в комментариях; [отредактируйте] ваш ответ, чтобы сделать его более понятным и полным. G-Man 6 лет назад 0
отредактировано - спасибо за информацию. Chris Hill 6 лет назад 0
Я хотел сказать, что я думал, что «98» был неправильным («96» был опечаткой). Это потому, что ваш ответ показывает пример конца шаблона, который составляет *** четыре *** байта. В остальном хорошая работа. G-Man 6 лет назад 0
Конечно, все, что вам нужно сделать, это ** size = (конечное смещение) - (начальное смещение) + (размер конечного шаблона) **. Разбивка 4 на 1 + 3 просто добавляет сложность. G-Man 6 лет назад 0