Como eu comparo arquivos binários no Linux?


304

Preciso comparar dois arquivos binários e obter a saída no formulário:

<fileoffset-hex> <file1-byte-hex> <file2-byte-hex>

para cada byte diferente. Então, se file1.biné

  00 90 00 11

em forma binária e file2.biné

  00 91 00 10

Eu quero algo como

  00000001 90 91
  00000003 11 10

Existe uma maneira de fazer isso no Linux? Eu sei, cmp -lmas ele usa um sistema decimal para compensações e octal para bytes que eu gostaria de evitar.


9
você está basicamente procurando por "diff binário". eu posso imaginar alguma linha de comando de uma linha reeeally feio com od...
quack quixote

2
@ Quackote Quackote: O que é feio em um one-liner? ;)
Bobby

O xdelta.org funciona muito bem. Talvez valesse a pena dar uma olhada.
thatjuan

Como você não pode responder a esta pergunta (como você não é usuário), estou votando para encerrar. Um diff binário, conforme solicitado explicitamente aqui, não é de todo útil, e estou inclinado a pensar que você deseja algo útil, se você inserir um byte no início do arquivo, todos os bytes deverão ser marcados como diferentes? Sem saber disso, isso é simplesmente muito vago.
Evan Carroll

2
@EvanCarroll Se você acha que a pergunta está errada, por que está respondendo?
DavidPostill

Respostas:


174

Isso imprimirá o deslocamento e os bytes em hexadecimal:

cmp -l file1.bin file2.bin | gawk '{printf "%08X %02X %02X\n", $1, strtonum(0$2), strtonum(0$3)}'

Ou faça $1-1para que o primeiro deslocamento impresso comece em 0.

cmp -l file1.bin file2.bin | gawk '{printf "%08X %02X %02X\n", $1-1, strtonum(0$2), strtonum(0$3)}'

Infelizmente, strtonum()é específico para o GAWK, portanto, para outras versões do awk - por exemplo, mawk - você precisará usar uma função de conversão de octal para decimal. Por exemplo,

cmp -l file1.bin file2.bin | mawk 'function oct2dec(oct,     dec) {for (i = 1; i <= length(oct); i++) {dec *= 8; dec += substr(oct, i, 1)}; return dec} {printf "%08X %02X %02X\n", $1, oct2dec($2), oct2dec($3)}'

Dividido para facilitar a leitura:

cmp -l file1.bin file2.bin |
    mawk 'function oct2dec(oct,    dec) {
              for (i = 1; i <= length(oct); i++) {
                  dec *= 8;
                  dec += substr(oct, i, 1)
              };
              return dec
          }
          {
              printf "%08X %02X %02X\n", $1, oct2dec($2), oct2dec($3)
          }'

3
@gertvdijk: strtonumé específico para o GAWK. Acredito que o Ubuntu anteriormente usou o GAWK como padrão, mas mudou em algum momento para mawk. De qualquer forma, o GAWK pode ser instalado e definido como o padrão (consulte também man update-alternatives). Veja minha resposta atualizada para uma solução que não requer strtonum.
Dennis Williamson

Por que não simplesmente comparar o sha256sum dos dois arquivos?
Rodrigo

1
@ Rodrigo: Esse e vários outros métodos mostrarão apenas se os arquivos diferem. Minha resposta atende ao requisito do OP de realmente mostrar quais são as diferenças.
Dennis Williamson

Claro! Desculpe, eu estava tão preocupado com o meu problema que mal li os OPs. Obrigado.
Rodrigo

166

Como o charlatão apontou:

 % xxd b1 > b1.hex
 % xxd b2 > b2.hex

E depois

 % diff b1.hex b2.hex

ou

 % vimdiff b1.hex b2.hex

70
No Bash: diff <(xxd b1) <(xxd b2)mas o formato de saída deste (ou seu) não está nem perto do que o OP solicitou.
Dennis Williamson

6
com o vimdiff, ele colorirá os bytes nas linhas em que os dois 'arquivos' diferem
akira 30/03/10

Aww, por que eu não pensei nisso? E tenho certeza de que já usei essa técnica no passado.
NJD

1
Isso funcionou muito bem para mim (com o opendiffOS X em vez de vimdiff) - a exibição padrão xxdmantém o mecanismo diff no caminho, comparando byte a byte. Com hexadecimal simples (bruto), simplesmente com ajuste de coluna fold, difftentaria dobrar / agrupar itens aleatórios nos arquivos que eu estava comparando.
Natevw

1
Este comando não funciona bem para remoção de adição de bytes, pois todas as linhas a seguir serão desalinhadas e vistas como modificadas por diff. A solução é colocar 1 byte por linha e remover a coluna de endereço, conforme proposto por John Lawrence Aspden e eu .
Ciro Santilli escreveu:

98

diff + xxd

Tente diffa seguinte combinação de substituição do processo zsh / bash:

diff -y <(xxd foo1.bin) <(xxd foo2.bin)

Onde:

  • -y mostra as diferenças lado a lado (opcional).
  • xxd é uma ferramenta CLI para criar uma saída hexdump do arquivo binário.
  • Adicione -W200a diffpara saída mais ampla (de 200 caracteres por linha).
  • Para cores, use colordiffcomo mostrado abaixo.

colordiff + xxd

Se você tiver colordiff, pode colorir a diffsaída, por exemplo:

colordiff -y <(xxd foo1.bin) <(xxd foo2.bin)

Caso contrário, instalar via: sudo apt-get install colordiff.

Saída de amostra:

saída de arquivo binário no terminal - diff -y <(xxd foo1.bin) <(xxd foo2.bin) |  colordiff

vimdiff + xxd

Você também pode usar vimdiff, por exemplo

vimdiff <(xxd foo1.bin) <(xxd foo2.bin)

Dicas:

  • se os arquivos forem muito grandes, adicione limite (por exemplo -l1000) para cadaxxd

11
O comando pode ser simplificado como colordiff -y <(xxd foo1.bin) <(xxd foo2.bin).
golem

3
Se você não tem colordiff, isso fará a mesma coisa sem cores:diff -y <(xxd foo1.bin) <(xxd foo2.bin)
Rock Lee

5
Se você quiser apenas saber se os dois arquivos são realmente iguais, use a opção -qou --brief, que só mostrará a saída quando os arquivos diferirem.
Stefan van den Akker

1
crie uma função xxddiffpara isso com:xxddiff() ( f() ( xxd "$1" ; ); diff -y <(f "$1") <(f "$2") | colordiff; )
rubo77 14/11

2
ótimo! Ainda assim, diff -u <(xxd tinga.tgz) <(xxd dec.out.tinga.tgz) | vim - vai fazer um trabalho bom enoug
Ribamar

56

Há uma ferramenta chamada DHEX que pode fazer o trabalho, e há outra ferramenta chamada VBinDiff .

Para uma abordagem estritamente de linha de comando, tente jojodiff .


8
DHEX é impressionante é comparar binários é o que você quer fazer. Alimente dois arquivos e o levará diretamente para uma visualização comparativa, destacando as diferenças, com facilidade para passar para a próxima diferença. Também é capaz de trabalhar com terminais grandes, o que é muito útil em monitores widescreen.
Marcin

7
Eu prefiro o VBinDiff. DHEX está usando CPU, mesmo quando ocioso, acho que está redesenhando o tempo todo ou algo assim. O VBinDiff não funciona com terminais largos. Mas os endereços ficam estranhos com terminais largos de qualquer maneira, já que você tem mais de 16 bytes por linha.
Janus Troelsen

1
vbindiff nos permite editar o arquivo, thx!
Poder de Aquário

2
Os arquivos compactados @DanielBeauyat serão completamente diferentes depois que você encontrar o primeiro byte diferente. É provável que a saída não seja útil.
Mark Ransom

2
@ 1111161171159459134 O jdiff faz parte de um "conjunto" de programas para sincronizar e corrigir as diferenças encontradas pelo jdiff. Mas, como Mark Ransom disse, isso geralmente não seria sensato em arquivos compactados; a exceção são os formatos compactados "sincronizáveis" (como o produzido por gzip --rsyncable), nos quais pequenas diferenças nos arquivos descompactados devem ter um efeito limitado no arquivo compactado.
Htmx #

27

Método que funciona para adição / exclusão de bytes

diff <(od -An -tx1 -w1 -v file1) \
     <(od -An -tx1 -w1 -v file2)

Gere um caso de teste com uma única remoção do byte 64:

for i in `seq 128`; do printf "%02x" "$i"; done | xxd -r -p > file1
for i in `seq 128`; do if [ "$i" -ne 64 ]; then printf "%02x" $i; fi; done | xxd -r -p > file2

Resultado:

64d63
<  40

Se você também deseja ver a versão ASCII do personagem:

bdiff() (
  f() (
    od -An -tx1c -w1 -v "$1" | paste -d '' - -
  )
  diff <(f "$1") <(f "$2")
)

bdiff file1 file2

Resultado:

64d63
<   40   @

Testado no Ubuntu 16.04.

Eu prefiro odmais xxdporque:

  • ele é POSIX , xxdnão é (vem com Vim)
  • tem a -Anpara remover a coluna de endereço sem awk.

Explicação do comando:

  • -Anremove a coluna de endereço. Isso é importante, caso contrário, todas as linhas diferirão após a adição / remoção de bytes.
  • -w1coloca um byte por linha, para que o diff possa consumi-lo. É crucial ter um byte por linha, ou então todas as linhas após uma exclusão ficarão fora de fase e diferirão. Infelizmente, isso não é POSIX, mas está presente no GNU.
  • -tx1 é a representação desejada, altere para qualquer valor possível, desde que você mantenha 1 byte por linha.
  • -vevita a abreviação de repetição de asterisco *que pode interferir na diferença
  • paste -d '' - -junta-se a cada duas linhas. Precisamos disso porque o hex e o ASCII entram em linhas adjacentes separadas. Retirado de: https://stackoverflow.com/questions/8987257/concatenating-every-other-line-with-the-next
  • usamos parênteses ()para definir, em bdiffvez de {}limitar o escopo da função interna f, consulte também: https://stackoverflow.com/questions/8426077/how-to-define-a-function-inside-another-function-in-bash

Veja também:


13

Resposta curta

vimdiff <(xxd -c1 -p first.bin) <(xxd -c1 -p second.bin)

Ao usar hexdumps e diff de texto para comparar arquivos binários, especialmente xxd, as adições e remoções de bytes se tornam mudanças no endereçamento, o que pode dificultar a visualização. Esse método diz ao xxd para não enviar endereços e gerar apenas um byte por linha, o que, por sua vez, mostra exatamente quais bytes foram alterados, adicionados ou removidos. Você pode encontrar os endereços posteriormente pesquisando as interessantes seqüências de bytes em um hexdump mais "normal" (saída de xxd first.bin).


(Claro, pode-se usar diffem vez de vimdiff.)
VasyaNovikov

11

Eu recomendaria o hexdump para descarregar arquivos binários para o formato textual e o kdiff3 para visualização de diferenças.

hexdump myfile1.bin > myfile1.hex
hexdump myfile2.bin > myfile2.hex
kdiff3 myfile1.hex myfile2.hex

2
Mesmo aqui no bash kdiff3 <(hexdump myfile1.bin) <(hexdump myfile2.bin)sem a necessidade de criar arquivos myfile1.hexe myfile2.hex.
Hastur

5

O hexdiffé um programa projetado para fazer exatamente o que você está procurando.

Uso:

hexdiff file1 file2

Ele exibe o hex (e ASCII de 7 bits) dos dois arquivos, um acima do outro, com as diferenças destacadas. Veja man hexdiffos comandos para se movimentar no arquivo, e um simples qserá encerrado.


4
Mas faz um trabalho muito ruim quando se trata da parte comparativa. Se você inserir alguns bytes em um arquivo, ele marcará todos os bytes posteriormente como alterações
Murmel

e hexdiff não está disponível via apt-get no Ubuntu 16.4
rubo77 14/11

1
@ Murmel enquanto eu concordo, não é isso que está sendo perguntado aqui?
Evan Carroll

@EvanCarroll verdade e, portanto, Eu deixei um comentário (apenas) e não downvote
Murmel

Também não votei em Mick, mas concordo com você e respondi aqui superuser.com/a/1373977/11116, porque parece provável que essa pergunta ruim seja reformada ou fechada.
Evan Carroll

3

Pode não responder estritamente à pergunta, mas eu uso isso para diferentes binários:

gvim -d <(xxd -c 1 ~/file1.bin | awk '{print $2, $3}') <(xxd -c 1 ~/file2.bin | awk '{print $2, $3}')

Ele imprime os dois arquivos como valores hexadecimais e ASCII , um byte por linha e, em seguida, usa o recurso diff do Vim para renderizá-los visualmente.


0

dhex http://www.dettus.net/dhex/

O DHEX é mais do que apenas outro editor hexadecimal: inclui um modo diff, que pode ser usado para comparar fácil e convenientemente dois arquivos binários. Como é baseado em ncurses e é utilizável, ele pode ser executado em qualquer número de sistemas e cenários. Com a utilização de logs de pesquisa, é possível rastrear alterações em diferentes iterações de arquivos facilmente.


Bem-vindo ao SuperUser! Embora este software parece que ele poderia resolver o problema do OP, puro anúncio é fortemente desaprovada na rede Stack Exchange. Se você é afiliado ao editor deste software, divulgue esse fato. E tente reescrever sua postagem para que ela pareça menos com um comercial. Obrigado.
você precisa saber é o seguinte

Eu não sou afiliado ao dhex de forma alguma. Copiei descrição do autor para o cargo porque não há limite mínimo pós comprimento
Vincent Vega


0

Você pode usar a ferramenta gvimdiff incluída no pacote vim-gui-common

sudo apt-get update

sudo apt-get install vim-gui-common

Em seguida, você pode comparar 2 arquivos hexadecimais usando os seguintes comandos:

ubuntu> gvimdiff <hex-file1> <hex-file2>

Tha is all. Espero que ajude!


0

A ferramenta de análise de firmware binwalktambém possui isso como um recurso na opção -W/ --hexdumplinha de comando, que oferece opções como mostrar apenas os bytes diferentes:

    -W, --hexdump                Perform a hexdump / diff of a file or files
    -G, --green                  Only show lines containing bytes that are the same among all files
    -i, --red                    Only show lines containing bytes that are different among all files
    -U, --blue                   Only show lines containing bytes that are different among some files
    -w, --terse                  Diff all files, but only display a hex dump of the first file

No exemplo do OP ao fazer binwalk -W file1.bin file2.bin:

binwalk -W file1.bin file2.bin



-2

O produto go to open source no Linux (e tudo mais) é o Radare, que fornece radiff2explicitamente para esse fim. Votei em encerrar isso porque eu e outros temos a mesma pergunta, na pergunta que você faz

para cada byte diferente

Isso é loucura. Como solicitado, se você inserir um byte no primeiro byte no arquivo, descobrirá que cada byte subsequente é diferente e, portanto, o diff repetirá o arquivo inteiro, com uma diferença real de um byte.

Um pouco mais prático é radiff -O. A -Oé para "" Faça código diffing com todos os bytes em vez de apenas os bytes opcode fixos ""

0x000000a4 0c01 => 3802 0x000000a4
0x000000a8 1401 => 3802 0x000000a8
0x000000ac 06 => 05 0x000000ac
0x000000b4 02 => 01 0x000000b4
0x000000b8 4c05 => 0020 0x000000b8
0x000000bc 4c95 => 00a0 0x000000bc
0x000000c0 4c95 => 00a0 0x000000c0

Como o IDA Pro, o Radare é uma ferramenta primária para análise binária, você também pode mostrar diferenças de delta -dou exibir os bytes desmontados em vez de hexadecimal com -D.

Se você está fazendo esse tipo de pergunta, confira

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.