Як порівняти бінарні файли в Linux?


303

Мені потрібно порівняти два двійкові файли та отримати вихід у вигляді:

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

для кожного різного байта. Так що якщо file1.binє

  00 90 00 11

у бінарній формі і file2.binє

  00 91 00 10

Я хочу отримати щось подібне

  00000001 90 91
  00000003 11 10

Чи можна це зробити в Linux? Я знаю про, cmp -lале в ньому використовується десяткова система для зміщення та восьмерична для байтів, чого я хотів би уникнути.


9
ви в основному шукаєте "бінарний розл." я можу уявити собі справді потворний однолінійний командний рядок із od...
шарлатаний кіхот

2
@quack Кіхот: Що негарного в одноколірному? ;)
Боббі

xdelta.org працює досить добре. Можливо, варто було б поглянути на це.
thatjuan

Оскільки ви не можете відповісти на це запитання (оскільки ви не користувач), я голосую за закриття. Бінарний розріз, як явно запитується тут, зовсім не корисний, і я схильний вважати, що ви хочете чогось корисного, якщо ви вставляєте один байт на початку файлу, чи всі байти мають бути відмічені як різні? Не знаючи цього, це просто занадто розпливчасто.
Еван Керролл

2
@EvanCarroll Якщо ви вважаєте, що питання поза темою, чому ви на нього відповідаєте?
DavidPostill

Відповіді:


174

Це надрукує зміщення та байти у шістнадцятковій формі:

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

Або $1-1перше друковане зміщення починається з 0.

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

На жаль, strtonum()характерний для GAWK, тому для інших версій awk, наприклад, mawk, вам потрібно буде використовувати функцію перетворення восьмидесятих у десяткові. Наприклад,

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

Розроблено для читабельності:

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: властиво GAWK strtonum. Я вважаю, що Ubuntu раніше використовував GAWK як за замовчуванням, але в якийсь момент перейшов на mawk. У будь-якому випадку, GAWK можна встановити та встановити за замовчуванням (див. Також man update-alternatives). Дивіться мою оновлену відповідь щодо рішення, яке не потребує strtonum.
Денніс Вільямсон

Чому б просто не порівняти sha256sum обох файлів?
Родріго

1
@Rodrigo: Це та різні інші методи просто покажуть, чи відрізняються файли. Моя відповідь відповідає вимозі ОП фактично показати, в чому полягають відмінності.
Денніс Вільямсон

Звичайно! Вибачте, я так хвилювався з приводу моєї проблеми, що ледве читав ОП. Дякую.
Родріго

165

Як ~ quack зазначив:

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

І потім

 % diff b1.hex b2.hex

або

 % vimdiff b1.hex b2.hex

70
У Bash: diff <(xxd b1) <(xxd b2)але вихідний формат цього (або вашого) ніде не є тим, про що вимагала ОП.
Денніс Вільямсон

6
з vimdiff це, він забарвлює байти в рядки, де два "файли" відрізняються
akira

Ау, чому я не придумав цього? І я впевнений, що і раніше використовував цю техніку.
njd

1
Для мене це спрацювало чудово (з opendiffОС X замість vimdiff) - подання за замовчуванням xxdзабезпечує утримування двигуна diff на трасі, порівнюючи байт-байт. З простою (сирою) шістнадцятковою формою, яка просто підходить у стовпчик fold, diffспробую скласти / групувати випадкові речі у файли, з якими я порівнював
natevw

1
Ця команда не працює добре для видалення додавання байтів, тому що кожен наступний рядок буде нерівним і розглядається як змінений diff. Рішення полягає в тому, щоб поставити 1 байт на рядок і видалити стовпчик адреси, як запропонували Джон Лоуренс Аспден і я .
Ciro Santilli 新疆 改造 中心 法轮功 六四 事件

97

diff + xxd

Спробуйте diffскористатись такою комбінацією заміну процесу zsh / bash:

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

Де:

  • -y показує відмінності поруч (необов’язково).
  • xxd є інструментом CLI для створення гексадумного виводу бінарного файлу.
  • Додати -W200до diffякомога ширшої виходу (з 200 символів в рядку).
  • Для кольорів використовуйте, colordiffяк показано нижче.

colordiff + xxd

Якщо у вас є colordiff, він може розфарбувати diffвихід, наприклад:

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

В іншому випадку встановити через: sudo apt-get install colordiff.

Вибірка зразка:

вихід бінарного файлу в терміналі - diff -y <(xxd foo1.bin) <(xxd foo2.bin) |  колорит

vimdiff + xxd

Ви також можете використовувати vimdiff, наприклад

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

Підказки:

  • якщо файли занадто великі, додайте ліміт (наприклад -l1000) для кожногоxxd

11
Команду можна спростити як colordiff -y <(xxd foo1.bin) <(xxd foo2.bin).
голем

3
Якщо у вас немає кольорового розрізу, це зробить те ж саме без кольорів:diff -y <(xxd foo1.bin) <(xxd foo2.bin)
Rock Lee

5
Якщо ви просто хочете знати , є чи обидва файли на насправді те ж саме, ви можете використовувати -qабо --briefперемикач, який буде показувати тільки висновок , коли файли відрізняються.
Стефан ван ден Аккер

1
створити xxddiffдля цього функцію за допомогою:xxddiff() ( f() ( xxd "$1" ; ); diff -y <(f "$1") <(f "$2") | colordiff; )
rubo77

2
чудово! все-таки, diff -u <(xxd tinga.tgz) <(xxd dec.out.tinga.tgz) | vim - зробить роботу добре enoug
ribamar

56

Є інструмент під назвою DHEX, який може виконувати цю роботу, і є ще один інструмент під назвою VBinDiff .

Для суворого підходу командного рядка спробуйте їїodiff .


8
DHEX приголомшливо - це порівняння бінарних файлів - те, що ви хочете зробити. Подайте в нього два файли, і це допоможе вам отримати порівняльний вигляд, виділивши відмінності, з легкою можливістю перейти до наступної різниці. Крім того, він може працювати з великими терміналами, що дуже корисно на широкоекранних моніторах.
Марцін

7
Я віддаю перевагу VBinDiff. DHEX використовує процесор навіть на холостому ходу, я думаю, що він переробляє весь час чи щось. VBinDiff, однак, не працює з широкими терміналами. Але адреси все-таки стають дивними з широкими терміналами, оскільки у вас більше 16 байт у рядку.
Янус Троельсен

1
vbindiff дозволяє нам фактично редагувати файл, thx!
Сила Водолія

2
@DanielBeauyat стиснуті файли будуть абсолютно різними після того, як ви зустрінете перший різний байт. Результат, ймовірно, не буде корисним.
Марк Викуп

2
@ 1111161171159459134 jdiff є частиною "набору" програм для синхронізації та виправлення відмінностей, знайдених jdiff. Але, як сказав Марк Рансом, це, як правило, не буде мудрим для стислих файлів; виняток становлять "синхронізовані" стислі формати (наприклад, створені gzip --rsyncable), в яких невеликі відмінності в нестиснених файлах повинні мати обмежений вплив на стислий файл.
hmijail

27

Метод, який працює для додавання / видалення байтів

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

Створіть тестовий випадок з одним видаленням байта 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

Вихід:

64d63
<  40

Якщо ви також хочете побачити версію символу ASCII:

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

bdiff file1 file2

Вихід:

64d63
<   40   @

Тестовано на Ubuntu 16.04.

Я віддаю перевагу odбільш , xxdтому що:

  • це POSIX , xxdне є (постачається з Vim)
  • має -Anвидалити адресний стовпець без awk.

Пояснення команди:

  • -Anвидаляє стовпчик адреси. Це важливо, інакше після додавання / видалення байта всі рядки будуть відрізнятися.
  • -w1ставить один байт на рядок, так що diff може споживати його. Важливо мати один байт на рядок, інакше кожен рядок після видалення стане поза фазою та відрізнятиметься. На жаль, це не POSIX, але присутнє в GNU.
  • -tx1 це представлення, яке ви хочете, зміни на будь-яке можливе значення, якщо ви зберігаєте 1 байт на рядок.
  • -vзапобігає абревіатурі повторення зірочки, *яка може заважати розл
  • paste -d '' - -приєднується кожні два рядки. Він потрібен тому, що шістнадцятковий і ASCII переходять в окремі суміжні лінії. Взято з: https://stackoverflow.com/questions/8987257/concatenating-every-other-line-with-the-next
  • ми використовуємо дужки ()для визначення, bdiffа не {}для обмеження сфери внутрішньої функції f, див. також: https://stackoverflow.com/questions/8426077/how-to-define-a-function-inside-another-function-in-bash

Дивитися також:


13

Коротка відповідь

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

При використанні шістнадцяткових і текстових розбіжностей для порівняння бінарних файлів, особливо xxd, додавання та видалення байтів стають зрушеннями в адресації, що може ускладнити їх розбір . Цей метод вказує xxd не виводити адреси, а виводити лише один байт на рядок, що в свою чергу показує, які саме байти були змінені, додані чи видалені. Пізніше ви можете знайти адреси, шукаючи цікаві послідовності байтів у більш "звичайному" шестигранному (вихідний xxd first.bin).


(Звичайно, можна використовувати diffзамість цього vimdiff.)
Вася Новиков

11

Я рекомендую hexdump для скидання бінарних файлів у текстовий формат та kdiff3 для різного перегляду.

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

2
Навіть тут, в баші, kdiff3 <(hexdump myfile1.bin) <(hexdump myfile2.bin)не потрібно створювати файли myfile1.hexі myfile2.hex.
Гастур

5

Це hexdiffпрограма, покликана робити саме те, що ви шукаєте.

Використання:

hexdiff file1 file2

Він відображає шістнадцятковий (і 7-бітний ASCII) двох файлів один над одним, з будь-якими відмінностями. Подивіться на man hexdiffкоманди, котрі рухатимуться у файлі, і проста qвийде.


4
Але це робить досить погану роботу, коли мова йде про порівняльну частину. Якщо ви вставите кілька байтів у файл, він позначить усі байти згодом як зміни
Murmel

і hexdiff недоступний через apt-get на Ubuntu 16.4
rubo77

1
@Murmel, хоча я згоден, чи не про це тут питають?
Еван Керролл

@EvanCarroll правда, і тому я залишив коментар (тільки) і не подав заяву
Murmel

Я також не відмовився проголосувати Міка, але я згоден з вами і відповів тут superuser.com/a/1373977/11116, тому що, мабуть, це погане питання буде реформоване чи закрите.
Еван Керролл

3

Це може не відповісти строго на питання, але я використовую це для різних бінарних файлів:

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

Він друкує обидва файли у вигляді шістнадцяткових та ASCII значень, по одному байту на рядок, а потім використовує різний інструмент Vim для візуального їх відображення.


0

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

DHEX - це не просто ще один шестигранний редактор: він включає в себе різний режим, який можна використовувати для легкого та зручного порівняння двох бінарних файлів. Оскільки він заснований на ncurses і є тематичним, він може працювати на будь-якій кількості систем та сценаріїв. За допомогою використання журналів пошуку можна легко відслідковувати зміни в різних ітераціях файлів.


Ласкаво просимо до SuperUser! Хоча це програмне забезпечення виглядає так, що може вирішити проблему ОП, чиста реклама сильно нахмуриться в мережі Stack Exchange. Якщо ви належите до редактора цього програмного забезпечення, розкрийте цей факт. І спробуйте переписати свою публікацію, щоб вона виглядала менш як комерційна. Дякую.
Nathan.Eilisha Shiraini

Я жодним чином не пов'язаний з dhex. Я скопіював опис автора до публікації, оскільки існує обмеження мінімальної тривалості публікації
Вінсент Вега


0

Ви можете використовувати інструмент gvimdiff , який входить до пакету vim-gui-common

sudo apt-get update

sudo apt-get install vim-gui-common

Потім ви можете порівняти два шістнадцяткові файли, використовуючи наступні команди:

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

Та все. Сподіваюся, що допоможе!


0

Інструмент аналізу вбудованого програмного забезпечення binwalkтакож має це як функцію через опцію -W/ --hexdumpкомандного рядка, яка пропонує такі варіанти, як лише показ різних байтів:

    -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

На прикладі ОП binwalk -W file1.bin file2.bin:

binwalk -W file1.bin file2.bin


-1

https://security.googleblog.com/2016/03/bindiff-now-available-for-free.html

BinDiff - чудовий інструмент користувальницького інтерфейсу для порівняння бінарних файлів, відкритих останнім часом.


3
Чи можна його використовувати в довільних бінарних файлах? Ця сторінка, схоже, вказує на те, що вона корисна лише для порівняння виконуваних файлів, які були розібрані програмою Hex-Rays IDA Pro.
eswald

-2

Доступ до продукту з відкритим кодом на Linux (і все інше) - це Radare, який radiff2явно пропонує для цього. Я проголосував за те, щоб закрити це, оскільки у мене та інших є те саме питання, у питанні, яке ви ставите

для кожного різного байта

Це божевільно. Оскільки за запитом, якщо ви вставите один байт у перший байт у файл, ви знайдете, що кожен наступний байт був різним, і тому diff повторив би весь файл за фактичну різницю в один байт.

Трохи практичніше radiff -O. Код -Oє для "" Чи відрізняється код усіма байтами, а не лише фіксованими байтами коду ""

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

Як і IDA Pro, Radare є основним інструментом для бінарного аналізу, ви також можете показати дельту, що відрізняється -d, або відобразити розібрані байти замість шістнадцяткових -D.

Якщо ви задаєте подібні запитання, перевірте

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.