Bagaimana cara membandingkan file biner di Linux?

304

Saya perlu membandingkan dua file biner dan mendapatkan output dalam bentuk:

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

untuk setiap byte yang berbeda. Jadi kalau file1.binbegitu

  00 90 00 11

dalam bentuk biner dan file2.binadalah

  00 91 00 10

Saya ingin mendapatkan sesuatu seperti

  00000001 90 91
  00000003 11 10

Apakah ada cara untuk melakukan ini di Linux? Saya tahu tentang cmp -ltetapi menggunakan sistem desimal untuk offset dan oktal untuk byte yang ingin saya hindari.

bertieb
sumber
9
Anda pada dasarnya mencari "binary diff". saya dapat membayangkan beberapa commandline jelek jelek satu baris dengan od...
quack quixote
2
@ quack quixote: Apa jeleknya one-liner? ;)
Bobby
xdelta.org bekerja dengan sangat baik. Mungkin ada baiknya kita melihatnya.
thatjuan
Karena Anda tidak dapat menjawab pertanyaan ini (karena Anda bukan pengguna), saya memilih untuk menutup. Perbedaan biner seperti yang diminta secara eksplisit di sini sama sekali tidak berguna, dan saya cenderung berpikir Anda menginginkan sesuatu yang bermanfaat, jika Anda memasukkan satu byte pada awal file, apakah semua byte ditandai sebagai berbeda? Tanpa mengetahui itu, ini terlalu kabur.
Evan Carroll
2
@ EvanCarroll Jika Anda pikir pertanyaannya di luar topik, mengapa Anda menjawabnya?
DavidPostill

Jawaban:

174

Ini akan mencetak offset dan byte dalam hex:

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

Atau lakukan $1-1agar cetakan offset pertama mulai dari 0.

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

Sayangnya, strtonum()ini khusus untuk GAWK, jadi untuk versi awk lainnya — mis. Mawk — Anda harus menggunakan fungsi konversi oktal ke desimal. Sebagai contoh,

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)}'

Dipatahkan untuk dibaca:

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)
          }'
Dennis Williamson
sumber
3
@gertvdijk: strtonumkhusus untuk GAWK. Saya percaya Ubuntu sebelumnya menggunakan GAWK sebagai default, tetapi beralih di beberapa titik ke mawk. Bagaimanapun, GAWK dapat diinstal dan diatur ke default (lihat juga man update-alternatives). Lihat jawaban saya yang diperbarui untuk solusi yang tidak memerlukan strtonum.
Dennis Williamson
Mengapa tidak membandingkan sha256sum dari kedua file?
Rodrigo
1
@ Rodrigo: Itu dan berbagai metode lain hanya akan menunjukkan apakah file berbeda. Jawaban saya memenuhi persyaratan OP untuk benar-benar menunjukkan perbedaannya.
Dennis Williamson
Tentu saja! Maaf, saya sangat khawatir tentang masalah SAYA sehingga saya hampir tidak membaca OP. Terima kasih.
Rodrigo
166

Seperti yang ditunjukkan oleh dukun :

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

Lalu

 % diff b1.hex b2.hex

atau

 % vimdiff b1.hex b2.hex
akira
sumber
70
Di Bash: diff <(xxd b1) <(xxd b2)tetapi format output ini (atau milik Anda) tidak jauh dari yang diminta OP.
Dennis Williamson
6
dengan vimdiff itu, itu akan mewarnai byte di baris di mana dua 'file' berbeda
akira
Ah, mengapa saya tidak memikirkan itu? Dan saya yakin saya juga pernah menggunakan teknik ini.
tgl
1
Ini bekerja sangat baik untuk saya (dengan opendiffmenggunakan OS X bukan vimdiff) - tampilan default xxdmenyediakan menjaga mesin diff pada jalur yang membandingkan byte-by-byte. Dengan hex (mentah) hex cukup kolom-cocok dengan fold, diffakan mencoba untuk melipat / mengelompokkan hal-hal acak dalam file yang saya bandingkan.
natevw
1
Perintah ini tidak berfungsi dengan baik untuk penghapusan penambahan byte, karena setiap baris yang mengikuti akan tidak selaras dan dilihat sebagai dimodifikasi oleh diff. Solusinya adalah dengan meletakkan 1 byte per baris dan menghapus kolom alamat seperti yang diusulkan oleh John Lawrence Aspden dan saya .
Ciro Santilli 新疆 改造 中心 法轮功 六四 事件
98

diff + xxd

Coba diffdalam kombinasi subtitusi proses zsh / bash berikut:

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

Dimana:

  • -y memperlihatkan kepada Anda perbedaan berdampingan (opsional).
  • xxd adalah alat CLI untuk membuat output hexdump dari file biner.
  • Tambahkan -W200ke diffuntuk keluaran yang lebih luas (200 karakter per baris).
  • Untuk warna, gunakan colordiffseperti yang ditunjukkan di bawah ini.

colordiff + xxd

Jika sudah colordiff, itu dapat mewarnai diffkeluaran, misalnya:

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

Jika tidak menginstal melalui: sudo apt-get install colordiff.

Output sampel:

output file biner di terminal - diff -y <(xxd foo1.bin) <(xxd foo2.bin) |  Colordiff

vimdiff + xxd

Anda juga dapat menggunakan vimdiff, mis

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

Petunjuk:

  • jika file terlalu besar, tambahkan batas (misalnya -l1000) untuk masing-masing filexxd
kenorb
sumber
11
Perintah dapat disederhanakan sebagai colordiff -y <(xxd foo1.bin) <(xxd foo2.bin).
golem
3
Jika Anda tidak memiliki colordiff, ini akan melakukan hal yang sama tanpa warna:diff -y <(xxd foo1.bin) <(xxd foo2.bin)
Rock Lee
5
Jika Anda hanya ingin tahu apakah kedua file tersebut sebenarnya sama, Anda dapat menggunakan -qatau --briefberalih, yang hanya akan menampilkan output ketika file berbeda.
Stefan van den Akker
1
buat fungsi xxddiffuntuk ini dengan:xxddiff() ( f() ( xxd "$1" ; ); diff -y <(f "$1") <(f "$2") | colordiff; )
rubo77
2
Bagus! tetap, diff -u <(xxd tinga.tgz) <(xxd dec.out.tinga.tgz) | vim - akan melakukan pekerjaan dengan baik enoug
ribamar
56

Ada alat yang disebut DHEX yang dapat melakukan pekerjaan itu, dan ada alat lain yang disebut VBinDiff .

Untuk pendekatan garis perintah yang ketat, coba jojodiff .

njd
sumber
8
DHEX luar biasa membandingkan biner adalah apa yang ingin Anda lakukan. Memberi makan dua file dan itu membawa Anda langsung ke tampilan komparatif, menyoroti perbedaan, dengan kemampuan yang mudah untuk pindah ke perbedaan berikutnya. Juga dapat bekerja dengan terminal besar, yang sangat berguna pada monitor layar lebar.
Marcin
7
Saya lebih suka VBinDiff. DHEX menggunakan CPU bahkan ketika idle, saya pikir itu menggambar ulang sepanjang waktu atau sesuatu. VBinDiff tidak bekerja dengan terminal lebar. Tetapi alamat menjadi aneh dengan terminal lebar, karena Anda memiliki lebih dari 16 byte per baris.
Janus Troelsen
1
vbindiff memungkinkan kita mengedit file, thx!
Aquarius Power
2
@DanielBeauyat file terkompresi akan sangat berbeda setelah Anda menemukan byte pertama yang berbeda. Outputnya kemungkinan tidak berguna.
Mark Ransom
2
@ 1111161171159459134 jdiff adalah bagian dari "rangkaian" program untuk menyinkronkan dan menambal perbedaan yang ditemukan oleh jdiff. Tapi, seperti yang dikatakan Mark Ransom, itu biasanya tidak bijaksana pada file yang dikompresi; pengecualiannya adalah format terkompresi yang "dapat disinkronkan" (seperti yang dihasilkan oleh gzip --rsyncable), di mana perbedaan kecil pada file yang tidak dikompres seharusnya memiliki efek terbatas pada file yang dikompresi.
hmijail
27

Metode yang berfungsi untuk penambahan / penghapusan byte

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

Buat test case dengan satu penghapusan 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

Keluaran:

64d63
<  40

Jika Anda juga ingin melihat versi ASCII dari karakter:

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

bdiff file1 file2

Keluaran:

64d63
<   40   @

Diuji pada Ubuntu 16.04.

Saya lebih suka odlebih xxdkarena:

  • itu POSIX , xxdbukan (dilengkapi dengan Vim)
  • memiliki -Anuntuk menghapus kolom alamat tanpa awk.

Penjelasan perintah:

  • -Anmenghapus kolom alamat. Ini penting jika tidak semua baris akan berbeda setelah penambahan / penghapusan byte.
  • -w1menempatkan satu byte per baris, sehingga diff dapat mengkonsumsinya. Sangat penting untuk memiliki satu byte per baris, atau setiap baris setelah penghapusan akan keluar dari fase dan berbeda. Sayangnya, ini bukan POSIX, tetapi ada di GNU.
  • -tx1 adalah representasi yang Anda inginkan, ubah ke nilai yang memungkinkan, selama Anda menyimpan 1 byte per baris.
  • -vmencegah singkatan pengulangan asterisk *yang dapat mengganggu diff
  • paste -d '' - -bergabung dengan setiap dua baris. Kami membutuhkannya karena hex dan ASCII masuk ke garis yang berdekatan yang terpisah. Diambil dari: https://stackoverflow.com/questions/8987257/concatenating-every-other-line-with-the-next
  • kami menggunakan tanda kurung ()untuk menentukan bdiffalih-alih {}membatasi ruang lingkup fungsi dalam f, lihat juga: https://stackoverflow.com/questions/8426077/how-to-define-a-function-inside-another-function-in-bash

Lihat juga:

Ciro Santilli 新疆 改造 中心 法轮功 六四 事件
sumber
13

Jawaban singkat

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

Saat menggunakan hexdumps dan teks diff untuk membandingkan file biner, khususnya xxd, penambahan dan penghapusan byte menjadi pergeseran dalam pengalamatan yang mungkin membuatnya sulit untuk dilihat. Metode ini memberitahu xxd untuk tidak menampilkan alamat, dan hanya menampilkan satu byte per baris, yang pada gilirannya menunjukkan dengan tepat byte mana yang diubah, ditambahkan, atau dihapus. Anda dapat menemukan alamat nanti dengan mencari urutan byte yang menarik di hexdump (output of xxd first.bin) yang lebih "normal" .

Evgeny
sumber
(Tentu saja, orang dapat menggunakan diffsebagai ganti vimdiff.)
VasyaNovikov
11

Saya akan merekomendasikan hexdump untuk membuang file biner ke format tekstual dan kdiff3 untuk tampilan yang berbeda.

hexdump myfile1.bin > myfile1.hex
hexdump myfile2.bin > myfile2.hex
kdiff3 myfile1.hex myfile2.hex
BugoK
sumber
2
Bahkan di sini di bash kdiff3 <(hexdump myfile1.bin) <(hexdump myfile2.bin)tanpa perlu membuat file myfile1.hexdan myfile2.hex.
Hastur
5

Ini hexdiffadalah program yang dirancang untuk melakukan persis apa yang Anda cari.

Pemakaian:

hexdiff file1 file2

Ini menampilkan hex (dan 7-bit ASCII) dari dua file satu di atas yang lain, dengan perbedaan yang disorot. Lihatlah man hexdiffperintah untuk bergerak di dalam file, dan sederhana qakan berhenti.

Mick
sumber
4
Tapi itu melakukan pekerjaan yang sangat buruk ketika datang ke bagian pembanding. Jika Anda memasukkan beberapa byte ke dalam sebuah file, itu akan menandai semua byte setelah perubahan
Murmel
dan hexdiff tidak tersedia melalui apt-get di Ubuntu 16.4
rubo77
1
@Murmel, sementara saya setuju, bukankah itu yang ditanyakan di sini?
Evan Carroll
@EvanCarroll benar, dan karenanya saya meninggalkan komentar (hanya) dan tidak downvote
Murmel
Saya juga tidak memilih Mick, tapi saya setuju dengan Anda dan menjawab di sini superuser.com/a/1373977/11116 karena sepertinya pertanyaan buruk ini akan direformasi atau ditutup.
Evan Carroll
3

Ini mungkin tidak sepenuhnya menjawab pertanyaan, tapi saya menggunakan ini untuk membedakan biner:

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

Ini mencetak kedua file sebagai nilai hex dan ASCII , satu byte per baris, dan kemudian menggunakan fasilitas diff Vim untuk membuat mereka secara visual.

John Lawrence Aspden
sumber
0

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

DHEX adalah lebih dari sekadar hex editor lain: Ini termasuk mode diff, yang dapat digunakan untuk membandingkan dua file biner dengan mudah dan nyaman. Karena didasarkan pada ncurses dan dapat disesuaikan, ia dapat berjalan pada sejumlah sistem dan skenario. Dengan pemanfaatan log pencarian, dimungkinkan untuk melacak perubahan di berbagai iterasi file dengan mudah.

Vincent Vega
sumber
Selamat datang di SuperUser! Meskipun perangkat lunak ini sepertinya bisa menyelesaikan masalah OP, iklan murni sangat disukai di jaringan Stack Exchange. Jika Anda berafiliasi dengan editor perangkat lunak ini, mohon ungkapkan fakta ini. Dan cobalah untuk menulis ulang posting Anda sehingga terlihat kurang seperti iklan. Terima kasih.
Nathan.Eilisha Shiraini
Saya tidak berafiliasi dengan dhex dengan cara apa pun. Saya menyalin deskripsi penulis ke dalam postingan karena ada batas panjang postingan minimum
Vincent Vega
Sudah disebutkan di: superuser.com/a/125390/128124
Ciro Santilli 新疆 改造 中心 法轮功 六四 事件
0

Anda dapat menggunakan gvimdiff alat yang termasuk dalam vim-gui-umum paket

sudo apt-get pembaruan

sudo apt-get install vim-gui-common

Kemudian Anda dapat membandingkan 2 file hex menggunakan perintah berikut:

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

Itu saja. Semoga bantuan!

kasar
sumber
0

Alat analisis firmware binwalkjuga memiliki ini sebagai fitur melalui opsi -W/ --hexdumpperintahnya yang menawarkan opsi seperti hanya menampilkan byte yang berbeda:

    -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

Dalam contoh OP saat melakukan binwalk -W file1.bin file2.bin:

binwalk -W file1.bin file2.bin

phk
sumber
-2

Pergi ke produk open source di Linux (dan yang lainnya) adalah Radare yang menyediakan radiff2secara eksplisit untuk tujuan ini. Saya memilih untuk menutup ini karena saya dan orang lain memiliki pertanyaan yang sama, dalam pertanyaan yang Anda ajukan

untuk setiap byte yang berbeda

Tapi itu gila. Karena seperti yang diminta, jika Anda memasukkan satu byte pada byte pertama dalam file, Anda akan menemukan bahwa setiap byte berikutnya berbeda dan jadi diff akan mengulangi seluruh file, untuk perbedaan sebenarnya dari satu byte.

Agak lebih praktis radiff -O. Ini -Ountuk "" Lakukan perbedaan kode dengan semua byte, bukan hanya byte opcode yang diperbaiki ""

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

Seperti IDA Pro, Radare adalah alat utama untuk analisis biner, Anda juga dapat menampilkan delta diffing with -d, atau menampilkan byte yang dibongkar alih-alih hex -D.

Jika Anda mengajukan pertanyaan semacam ini, lihat

Evan Carroll
sumber