Como extrair um segmento de um arquivo binário com base no início e término das sequências hexadecimais

1

Eu tenho um arquivo binário grande (várias centenas de GBs) e quero extrair um segmento dele. Eu sei as cordas hexadecimais dos pontos inicial e final.

    
por Hyatt 25.11.2017 / 00:30

1 resposta

2

Uma possível solução (supondo que você pode fazer uma cópia do arquivo) poderia usar o seguinte exemplo

  1. assuma que o padrão inicial é hex 4f 0f 87 82
  2. suponha que o padrão final seja hex fb 8c e2 a0
  3. suponha que o arquivo de entrada seja chamado de tf e tenha comprimento de 5000 bytes

então

faça uma cópia de tf para um novo arquivo blah com o padrão de início alterado

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

agora encontre a localização onde tf e blah diferem ( note-sed escreve um byte extra contendo uma nova linha no final do arquivo modificado, então nós comparamos com o comprimento do arquivo original, tf . O arquivo gerado blah deve ser um byte maior ).

$ cmp -n 5000 -b tf blah

isso resultará em um deslocamento de bytes, bs, em que os arquivos são diferentes, por exemplo,

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

agora faça o mesmo para terminar o padrão

 $ 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

agora use dd para extrair parte do interesse

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

Algumas notas extras:

  1. algumas versões do sed suportam uma opção -b que trata o arquivo de entrada como binário. Outras versões têm uma opção -z que separa linhas por caracteres NUL. De qualquer maneira, os padrões correspondentes que contêm uma nova linha, ou divididos sobre uma nova linha, não foram testados.

  2. o count=100 dependerá do comprimento do padrão combinado e se o padrão correspondente deve ser incluído na extração (isso não estava claro na pergunta). A fórmula geral é count = (offset final) - (offset inicial) + (tamanho do padrão final) . As peças para o exemplo específico são 4433-4337 + 1, que dão 97 bytes. Isso é desde o início do padrão inicial até o primeiro byte do padrão final. Um extra de 3 bytes é então adicionado para dar 100 neste exemplo, porque o padrão final tinha quatro bytes e o exemplo inclui o padrão final. Se o padrão final não fosse desejado, então count=96 seria o valor.

  3. uma abordagem que é mais robusta para novas linhas e usando o comando hexdump é possível. Eu não testei totalmente essa abordagem. Essencialmente, ele usaria o hexdump com um pouco de sed, grep e tr para converter o arquivo binário original em hexadecimal. Então, o mesmo processo poderia ser aplicado, mas com mais aritmética complicada, etc .... O comando hexdump necessário seria

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

  4. Após a etapa hexdump , o mesmo processo de sed e cmp poderia ser empregado. O padrão para correspondência teria que ser atualizado para usar caracteres ascii hexdump não a impressão hexadecimal bruta.

  5. Essa abordagem também deve manipular caracteres de nova linha.

  6. LC_ALL=C parece ser necessário no OSX por padrão. Sem ele, o comando sed gerará um erro RE error: illegal byte sequence . Isso pode não ser verdade em todas as plataformas e / ou distribuições do sistema operacional.

por 25.11.2017 / 02:05