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ąć.

bertieb
źródło
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)
          }'
Dennis Williamson
źródło
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
akira
źródło
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
kenorb
źródło
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 .

njd
źródło
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ż:

Ciro Santilli
źródło
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).

Jewgienij
źródło
(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
BugoK
źródło
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.

Mick
źródło
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.

John Lawrence Aspden
źródło
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.

Vincent Vega
źródło
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
Wspomniano już na: superuser.com/a/125390/128124
Ciro Santilli 新疆 改造 中心 法轮功 六四 事件
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!

craken
źródło
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

phk
źródło
-1

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

BinDiff to świetne narzędzie interfejsu użytkownika do porównywania plików binarnych, które zostały ostatnio otwarte.

Jewgienij
źródło
3
Czy można go jednak stosować w dowolnych plikach binarnych? Ta strona wydaje się wskazywać, że jest przydatna tylko do porównywania plików wykonywalnych, które zostały zdemontowane przez Hex-Rays IDA Pro.
eswald
-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ź

Evan Carroll
źródło