Jak porównać pliki binarne w systemie Linux?


303

Muszę porównać dwa pliki binarne i uzyskać wynik w postaci:

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

dla każdego innego bajtu. Więc jeśli file1.binjest

  00 90 00 11

w formie binarnej i file2.binjest

  00 91 00 10

Chcę dostać coś takiego

  00000001 90 91
  00000003 11 10

Czy jest na to sposób w Linuksie? Wiem o tym, cmp -lale używa systemu dziesiętnego dla przesunięć i ósemkowego dla bajtów, których chciałbym uniknąć.


9
zasadniczo szukasz „różnic binarnych”. mogę sobie wyobrazić naprawdę brzydką linijkę komend z od...
— quack quixote

2
@ quackote: Co jest brzydkiego w jednej linijce? ;)
— Bobby

xdelta.org działa całkiem dobrze. Być może warto na to rzucić okiem.
— thatjuan

Ponieważ nie możesz odpowiedzieć na to pytanie (ponieważ nie jesteś użytkownikiem), głosuję za jego zamknięciem. Binarny plik różnic, o który wyraźnie tu poprosiliśmy, wcale nie jest użyteczny, a ja jestem skłonny myśleć, że chcesz czegoś przydatnego, jeśli wstawisz jeden bajt na początku pliku, czy wszystkie bajty powinny być oznaczone jako różne? Nie wiedząc o tym, jest to po prostu zbyt niejasne.
— Evan Carroll

2
@EvanCarroll Jeśli uważasz, że pytanie jest nie na temat, dlaczego na nie odpowiadasz?
— DavidPostill

Odpowiedzi:


174

Spowoduje to wydrukowanie przesunięcia i bajtów w postaci szesnastkowej:

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

Lub zrób, $1-1aby pierwsze drukowane przesunięcie zaczynało się od 0.

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

Niestety, strtonum()jest specyficzny dla GAWK, więc w innych wersjach awk - np. Mawk - będziesz musiał użyć funkcji konwersji ósemkowej na dziesiętną. Na przykład,

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

Podział na czytelność:

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: strtonumjest specyficzny dla GAWK. Wierzę, że Ubuntu poprzednio używał GAWK jako domyślnego, ale w pewnym momencie zmienił na mawk. W każdym razie GAWK może zostać zainstalowany i ustawiony na domyślny (patrz także man update-alternatives). Zobacz moją zaktualizowaną odpowiedź na rozwiązanie, które nie wymaga strtonum.
— Dennis Williamson

Dlaczego po prostu nie porównać sumy sha256 obu plików?
— Rodrigo

1
@Rodrigo: Ta i wiele innych metod pokaże tylko, czy pliki się różnią. Moja odpowiedź spełnia wymóg PO dotyczący faktycznego wykazania różnic.
— Dennis Williamson,

Oczywiście! Przepraszam, tak bardzo martwiłem się o MÓJ problem, że ledwo czytam OP. Dziękuję Ci.
— Rodrigo

165

Jak wskazał ~ kwak :

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

I wtedy

 % diff b1.hex b2.hex

lub

 % vimdiff b1.hex b2.hex

70
W Bash: diff <(xxd b1) <(xxd b2)ale format wyjściowy tego (lub twojego) nie jest bliski żądaniu OP.
— Dennis Williamson

6
z vimdiff, pokoloruje bajty w liniach, w których dwa „pliki” różnią się
— akira

Aww, dlaczego o tym nie pomyślałem? I jestem pewien, że używałem tej techniki również w przeszłości.
— njd

1
Działa to świetnie dla mnie (z opendiffOS X zamiast vimdiff) - domyślny widok xxdzapewnia utrzymanie mechanizmu różnicowego na ścieżce porównywania bajt po bajcie. Przy zwykłym (surowym) heksie po prostu dopasowanym do kolumny fold, diffpróbowałbym składać / grupować losowe rzeczy w plikach, które porównywałem.
— natevw

1
To polecenie nie działa dobrze w przypadku usuwania dodawania bajtów, ponieważ każda następna linia będzie źle wyrównana i będzie widoczna jako zmodyfikowana przez diff. Rozwiązaniem jest wstawienie 1 bajtu na wiersz i usunięcie kolumny adresu, jak zaproponowali John Lawrence Aspden i ja .
— Ciro Santilli 4 改造 中心 法轮功 六四 事件

97

diff + xxd

Wypróbuj diffnastępującą kombinację podstawienia procesu zsh / bash:

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

Gdzie:

  • -y pokazuje różnice obok siebie (opcjonalnie).
  • xxd jest narzędziem CLI do tworzenia pliku zrzutu heksadecymalnego pliku binarnego.
  • Dodaj -W200do, aby diffuzyskać szerszy wynik (200 znaków w wierszu).
  • W przypadku kolorów użyj colordiffjak pokazano poniżej.

colordiff + xxd

Jeśli masz colordiff, może pokolorować diffdane wyjściowe, np .:

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

Inaczej zainstalować poprzez: sudo apt-get install colordiff.

Przykładowe dane wyjściowe:

wyjście pliku binarnego w terminalu - diff -y <(xxd foo1.bin) <(xxd foo2.bin) |  Colordiff

vimdiff + xxd

Możesz także użyć vimdiffnp

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

Poradnik:

  • jeśli pliki są zbyt duże, dodaj limit (np. -l1000) dla każdegoxxd

11
Polecenie można uprościć jako colordiff -y <(xxd foo1.bin) <(xxd foo2.bin).
— golem,

3
Jeśli nie masz colordiff, zrobi to samo bez kolorów:diff -y <(xxd foo1.bin) <(xxd foo2.bin)
— Rock Lee

5
Jeśli chcesz tylko wiedzieć, czy oba pliki są w rzeczywistości takie same, możesz użyć przełącznika -qlub --brief, który wyświetli dane wyjściowe tylko wtedy, gdy pliki się różnią.
— Stefan van den Akker

1
utwórz xxddiffdla tego funkcję za pomocą:xxddiff() ( f() ( xxd "$1" ; ); diff -y <(f "$1") <(f "$2") | colordiff; )
— rubo77

2
świetny! mimo diff -u <(xxd tinga.tgz) <(xxd dec.out.tinga.tgz) | vim - to wykona dobrą robotę
— ribamar

56

Istnieje narzędzie o nazwie DHEX, które może wykonać tę pracę, oraz inne narzędzie o nazwie VBinDiff .

Aby uzyskać podejście oparte wyłącznie na wierszu poleceń, wypróbuj jojodiff .


8
DHEX jest niesamowity, porównywanie plików binarnych jest tym, co chcesz zrobić. Nakarm go dwoma plikami i zabierze Cię do widoku porównawczego, podkreślając różnice, z łatwą możliwością przejścia do następnej różnicy. Ponadto może współpracować z dużymi terminalami, co jest bardzo przydatne w monitorach szerokoekranowych.
— Marcin

7
Wolę VBinDiff. DHEX używa procesora nawet na biegu jałowym, myślę, że przerysowuje cały czas czy coś. VBinDiff nie działa jednak z szerokimi terminalami. Ale adresy i tak stają się dziwne z szerokimi terminalami, ponieważ masz więcej niż 16 bajtów na wiersz.
— Janus Troelsen

1
vbindiff pozwala nam edytować plik, dzięki!
— Aquarius Power

2
Pliki skompresowane @DanielBeauyat będą zupełnie inne po napotkaniu pierwszego innego bajtu. Dane wyjściowe prawdopodobnie nie będą przydatne.
— Mark Ransom,

2
@ 1111161171159459134 jdiff jest częścią „pakietu” programów do synchronizacji i łatania różnic znalezionych przez jdiff. Ale, jak powiedział Mark Ransom, nie byłoby to rozsądne w przypadku skompresowanych plików; wyjątkiem są skompresowane formaty „zsynchronizowane” (takie jak te tworzone przez gzip --rsyncable), w których niewielkie różnice w nieskompresowanych plikach powinny mieć ograniczony wpływ na skompresowany plik.
— hmijail

27

Metoda, która działa w przypadku dodawania / usuwania bajtów

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

Wygeneruj przypadek testowy z pojedynczym usunięciem bajtu 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

Wynik:

64d63
<  40

Jeśli chcesz również zobaczyć wersję ASCII znaku:

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

bdiff file1 file2

Wynik:

64d63
<   40   @

Testowane na Ubuntu 16.04.

Wolę odsię xxd, ponieważ:

  • to jest POSIX , xxdnie jest (pochodzi z Vimem)
  • musi -Anusunąć kolumnę adresu bez awk.

Wyjaśnienie polecenia:

  • -Anusuwa kolumnę adresu. Jest to ważne, w przeciwnym razie wszystkie wiersze będą się różnić po dodaniu / usunięciu bajtu.
  • -w1wstawia jeden bajt na linię, aby diff mógł go wykorzystać. Ważne jest, aby mieć jeden bajt na linię, w przeciwnym razie każda linia po usunięciu stanie się poza fazą i będzie inna. Niestety nie jest to POSIX, ale występuje w GNU.
  • -tx1 to reprezentacja, którą chcesz, zmień na dowolną możliwą wartość, o ile zachowasz 1 bajt na linię.
  • -vzapobiega skrótowi powtórzeń gwiazdki, *który może zakłócać różnicę
  • paste -d '' - -łączy się co dwie linie. Potrzebujemy go, ponieważ hex i ASCII przechodzą w oddzielne sąsiednie linie. Zaczerpnięte z: https://stackoverflow.com/questions/8987257/concatenating-every-other-line-with-the-next
  • używamy nawiasów, ()aby zdefiniować bdiffzamiast {}ograniczać zakres funkcji wewnętrznej f, patrz również: https://stackoverflow.com/questions/8426077/how-to-define-a-function-inside-another-function-in-bash

Zobacz też:


13

Krótka odpowiedź

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

Kiedy używasz zrzutów szesnastkowych i różnic tekstowych do porównywania plików binarnych, zwłaszcza xxddodawanie i usuwanie bajtów zmienia się w adresowaniu, co może utrudnić ich dostrzeżenie. Ta metoda każe xxd nie wysyłać adresów i wypisywać tylko jeden bajt na linię, co z kolei pokazuje dokładnie, które bajty zostały zmienione, dodane lub usunięte. Adresy można znaleźć później, wyszukując interesujące sekwencje bajtów w bardziej „normalnym” zrzutie szesnastkowym (wynik xxd first.bin).


(Oczywiście można użyć diffzamiast vimdiff.)
— VasyaNovikov,

11

Polecam hexdump do zrzucania plików binarnych do formatu tekstowego i kdiff3 do przeglądania różnic.

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

2
Nawet tutaj w bash kdiff3 <(hexdump myfile1.bin) <(hexdump myfile2.bin)bez potrzeby tworzenia plików myfile1.hexi myfile2.hex.
— Hastur

5

hexdiffTo program przeznaczony do zrobić dokładnie to, czego szukasz.

Stosowanie:

hexdiff file1 file2

Wyświetla szesnastkowy (i 7-bitowy ASCII) dwóch plików jeden nad drugim, z zaznaczonymi różnicami. Poszukaj man hexdiffpoleceń do poruszania się w pliku, a proste qzostanie zamknięte.


4
Ale robi to dość kiepską robotę, jeśli chodzi o porównywanie. Jeśli wstawisz kilka bajtów do pliku, oznaczony zostanie cały bajt później jako zmiany
— Murmel 27.04.16

i hexdiff nie jest dostępny przez apt-get na Ubuntu 16.4
— rubo77

1
@Murmel, kiedy się zgadzam, czy nie o to tu pyta?
— Evan Carroll

@EvanCarroll prawda, i dlatego zostawiłem komentarz (tylko) i nie głosowałem
— Murmel

Nie oddałem też głosu Mickowi, ale zgadzam się z tobą i odpowiedziałem tutaj superuser.com/a/1373977/11116, ponieważ wydaje się prawdopodobne, że to złe pytanie zostanie zreformowane lub zamknięte.
— Evan Carroll,

3

Może nie ściśle odpowiada na pytanie, ale używam tego do różnicowania plików binarnych:

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

Drukuje oba pliki jako wartości szesnastkowe i ASCII , jeden bajt na linię, a następnie używa funkcji różnicowania Vima do renderowania ich wizualnie.


0

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

DHEX to coś więcej niż kolejny edytor szesnastkowy: zawiera tryb różnicowy, za pomocą którego można łatwo i wygodnie porównywać dwa pliki binarne. Ponieważ jest oparty na ncurses i jest tematyczny, może działać na dowolnej liczbie systemów i scenariuszy. Dzięki wykorzystaniu dzienników wyszukiwania możliwe jest łatwe śledzenie zmian w różnych iteracjach plików.


Witamy w SuperUser! Chociaż to oprogramowanie wygląda na to, że mogłoby rozwiązać problem OP, czysta reklama jest zdecydowanie niezadowolona w sieci Stack Exchange. Jeśli jesteś powiązany z edytorem tego oprogramowania, ujawnij ten fakt. I spróbuj przepisać swój post, aby mniej przypominał reklamę. Dziękuję Ci.
— Nathan.Eilisha Shiraini

Nie jestem w żaden sposób związany z dhex. Skopiowałem opis autora do postu, ponieważ istnieje minimalny limit długości posta
— Vincent Vega


0

Możesz użyć narzędzia gvimdiff , które jest zawarte w pakiecie vim-gui-common

sudo apt-get update

sudo apt-get install vim-gui-common

Następnie możesz porównać 2 pliki szesnastkowe za pomocą następujących poleceń:

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

To wszystko. Mam nadzieję, że pomoże!


0

Narzędzie do analizy oprogramowania układowego binwalkma tę funkcję również za pomocą opcji -W/ --hexdumpwiersza poleceń, która oferuje opcje takie jak wyświetlanie tylko różnych bajtów:

    -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

W przykładzie OP podczas wykonywania binwalk -W file1.bin file2.bin:

binwalk -W plik1.bin plik2.bin



-2

Przejście do produktu open source w Linuksie (i wszystkim innym) to Radare, który zapewnia to radiff2wyraźnie. Głosowałem za jej zamknięciem, ponieważ ja i inni mamy to samo pytanie w pytaniu, które zadajesz

dla każdego innego bajtu

To szalone. Ponieważ, zgodnie z pytaniem, jeśli wstawisz jeden bajt na pierwszym bajcie w pliku, przekonasz się, że każdy kolejny bajt był inny, więc diff powtórzyłby cały plik, z faktyczną różnicą jednego bajta.

Nieco bardziej praktyczny jest radiff -O. Jest -Oto dla „Wykonuj różnicę kodu wszystkimi bajtami zamiast tylko ustalonymi bajtami opcode” ”

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

Podobnie jak IDA Pro, Radare jest narzędziem podstawowym do analizy binarnej, możesz także pokazywać różnicowanie delty za pomocą -dlub wyświetlać zdemontowane bajty zamiast szesnastkowego za pomocą -D.

Jeśli jednak zadajesz tego rodzaju pytania, sprawdź

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.