ฉันจะเปรียบเทียบไฟล์ไบนารีใน 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
คุณกำลังมองหา "binary diff" ฉันสามารถจินตนาการบางอย่างน่าเกลียด reeeally commandline หนึ่งซับด้วยod...
นักต้มตุ๋น Quixote

2
@quack quixote: สิ่งที่น่าเกลียดเกี่ยวกับหนึ่งซับ? ;)
Bobby

xdelta.org ทำงานได้ค่อนข้างดี บางทีมันอาจจะคุ้มค่าที่จะดูมัน
thatjuan

เนื่องจากคุณไม่สามารถตอบคำถามนี้ (เนื่องจากคุณไม่ใช่ผู้ใช้) ฉันจึงลงคะแนนให้ปิด ไบนารีที่แตกต่างกันตามที่ขออย่างชัดเจนที่นี่ไม่มีประโยชน์เลยและฉันอยากจะคิดว่าคุณต้องการสิ่งที่มีประโยชน์ถ้าคุณใส่หนึ่งไบต์ที่จุดเริ่มต้นของไฟล์ควรทำเครื่องหมายว่าไบต์ทั้งหมดแตกต่างกันหรือไม่ โดยไม่ทราบว่านี่เป็นสิ่งที่คลุมเครือเกินไป
Evan Carroll

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: strtonumเฉพาะ GAWK ผมเชื่อว่าอูบุนตูใช้ก่อนหน้านี้เพ่งพิศเป็นค่าเริ่มต้น mawkแต่เปลี่ยนในบางจุดเพื่อ ไม่ว่าในกรณีใด GAWK สามารถติดตั้งและตั้งเป็นค่าเริ่มต้น (ดูเพิ่มเติมได้man update-alternatives) strtonumดูคำตอบที่อัปเดตของฉันสำหรับการแก้ปัญหาที่ไม่จำเป็นต้องมี
Dennis Williamson

ทำไมไม่เปรียบเทียบ sha256sum ของทั้งสองไฟล์?
Rodrigo

1
@Rodrigo: นั่นและวิธีการอื่น ๆ จะแสดงให้เห็นว่าไฟล์แตกต่างกันหรือไม่ คำตอบของฉันตรงตามข้อกำหนดของ OP เพื่อแสดงความแตกต่างจริง ๆ
Dennis Williamson

แน่นอน! ขออภัยฉันกังวลเกี่ยวกับปัญหาของฉันมากจนแทบจะไม่อ่าน OP ขอขอบคุณ.
Rodrigo

165

ในฐานะที่เป็นนักต้มตุ๋นชี้ให้เห็น:

 % 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)แต่รูปแบบผลลัพธ์ของสิ่งนี้ (หรือของคุณ) ไม่มีอะไรใกล้เคียงกับสิ่งที่ OP ร้องขอ
Dennis Williamson

6
ด้วย vimdiff มันจะสีไบต์ในบรรทัดที่แตกต่างกัน 'ไฟล์' สอง
akira

ทำไมฉันไม่คิดอย่างนั้นล่ะ และฉันแน่ใจว่าฉันเคยใช้เทคนิคนี้ในอดีตเช่นกัน
njd

1
สิ่งนี้ใช้งานได้ดีสำหรับฉัน ( opendiffเมื่อใช้ OS X แทนvimdiff) - มุมมองเริ่มต้นxxdช่วยให้เอ็นจิ้น diff ติดตามการเปรียบเทียบไบต์ต่อไบต์ ด้วยธรรมดา (ดิบ) ฐานสิบหกเพียงคอลัมน์พอดีกับfold, diffจะพยายามที่จะพับ / กลุ่มสิ่งที่สุ่มในแฟ้มที่ผมเปรียบเทียบ
natevw

1
คำสั่งนี้จะไม่ทำงานได้ดีสำหรับการกำจัดไบต์นอกจากนี้ยังเป็นเส้นที่ต่อไปนี้จะได้รับการ misaligned diffและมองว่าเป็นแก้ไขโดยทุก การแก้ปัญหาคือการใส่ 1 ไบต์ต่อบรรทัดและลบคอลัมน์ที่อยู่ตามที่เสนอโดยจอห์นลอว์เร Aspdenและฉัน
Ciro Santilli 事件改造中心法轮功六四事件

98

diff + xxd

ลองdiffในการรวมกันของการทดแทนกระบวนการ zsh / bash ต่อไปนี้:

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

ที่ไหน:

  • -y แสดงให้คุณเห็นความแตกต่างแบบเคียงข้างกัน (ตัวเลือก)
  • xxd เป็นเครื่องมือ CLI เพื่อสร้างเอาต์พุตเลขฐานสิบหกของไฟล์ไบนารี
  • เพิ่ม-W200ไปยังdiffเอาต์พุตที่กว้างขึ้น (จาก 200 อักขระต่อบรรทัด)
  • สำหรับสีใช้colordiffตามที่แสดงด้านล่าง

colordiff + xxd

หากคุณcolordiffมันสามารถ colorize diffเอาท์พุทเช่น:

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

sudo apt-get install colordiffมิฉะนั้นการติดตั้งผ่าน:

ตัวอย่างผลลัพธ์:

เอาต์พุตไฟล์ไบนารีในเทอร์มินัล - diff -y <(xxd foo1.bin) <(xxd foo2.bin) |  colordiff

vimdiff + xxd

คุณยังสามารถใช้vimdiffเช่น

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

คำแนะนำ:

  • หากไฟล์มีขนาดใหญ่เกินไปให้เพิ่มขีด จำกัด (เช่น-l1000) สำหรับแต่ละไฟล์xxd

11
colordiff -y <(xxd foo1.bin) <(xxd foo2.bin)คำสั่งได้ง่ายเป็น
golem

3
หากคุณไม่มี colordiff สิ่งนี้จะทำแบบเดียวกันโดยไม่มีสี:diff -y <(xxd foo1.bin) <(xxd foo2.bin)
Rock Lee

5
หากคุณต้องการทราบว่าทั้งสองไฟล์นั้นเหมือนกันจริงหรือไม่คุณสามารถใช้สวิตช์-qหรือ--briefซึ่งจะแสดงเฉพาะเมื่อไฟล์ต่างกัน
Stefan van den Akker

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

สำหรับวิธีการอย่างเคร่งครัดบรรทัดคำสั่งให้ลองjojodiff


8
DHEX ยอดเยี่ยมมากคือการเปรียบเทียบไบนารีคือสิ่งที่คุณต้องการทำ ป้อนสองไฟล์และนำคุณไปสู่มุมมองเปรียบเทียบโดยเน้นที่ความแตกต่างพร้อมความสามารถในการเลื่อนไปยังความแตกต่างถัดไปได้อย่างง่ายดาย นอกจากนี้ยังสามารถทำงานร่วมกับเทอร์มินัลขนาดใหญ่ซึ่งมีประโยชน์มากบนจอภาพไวด์สกรีน
Marcin

7
ฉันชอบ VBinDiff DHEX ใช้ CPU แม้ในขณะที่ไม่ได้ใช้งานฉันคิดว่ามันสามารถวาดใหม่ได้ตลอดเวลาหรือบางสิ่งบางอย่าง VBinDiff ไม่สามารถใช้งานกับเทอร์มินัลแบบกว้างได้ แต่ที่อยู่แปลก ๆ ด้วยเทอร์มินัลกว้างเนื่องจากคุณมีมากกว่า 16 ไบต์ต่อแถว
Janus Troelsen

1
vbindiff ช่วยให้เราแก้ไขไฟล์จริงขอบคุณ!
กุมภ์อำนาจ

2
@DanielBeauyat ไฟล์บีบอัดจะแตกต่างอย่างสิ้นเชิงหลังจากที่คุณพบไบต์แรกที่แตกต่างกัน ผลลัพธ์ไม่น่าจะมีประโยชน์
Mark Ransom

2
@ 1111161171159459134 jdiff เป็นส่วนหนึ่งของ "ชุด" ของโปรแกรมที่จะซิงค์และแก้ไขความแตกต่างที่พบโดย jdiff แต่ดังที่ Mark Ransom กล่าวว่าโดยทั่วไปแล้วจะไม่ฉลาดในไฟล์บีบอัด ข้อยกเว้นคือรูปแบบที่บีบอัด "แบบซิงโครไนซ์" (เช่นที่สร้างโดย 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ไม่ได้ (มาพร้อมกับกลุ่ม)
  • มีการเอาคอลัมน์ที่อยู่ได้โดยไม่ต้อง-Anawk

คำอธิบายคำสั่ง:

  • -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-fash-ฟังก์ชัน

ดูสิ่งนี้ด้วย:


13

คำตอบสั้น ๆ

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

เมื่อใช้ hexdumps และ text diff เพื่อเปรียบเทียบไฟล์ไบนารีโดยเฉพาะอย่างยิ่งxxdการเพิ่มและการลบไบต์กลายเป็นการกะที่อยู่ซึ่งอาจทำให้มองเห็นได้ยาก วิธีนี้บอกให้ xxd ไม่ได้ที่อยู่เอาท์พุทและส่งออกเพียงหนึ่งไบต์ต่อบรรทัดเท่านั้นซึ่งจะแสดงว่ามีการเปลี่ยนแปลงเพิ่มหรือลบจำนวนไบต์ใดอย่างแน่นอน คุณสามารถค้นหาที่อยู่ได้ในภายหลังโดยค้นหาลำดับที่น่าสนใจของไบต์ในฐานสิบหก "ปกติ" เพิ่มเติม (เอาต์พุตของxxd first.bin)


(แน่นอนว่าอาจใช้diffแทนvimdiffได้)
VasyaNovikov

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
Hastur

5

hexdiffเป็นโปรแกรมที่ออกแบบมาเพื่อทำสิ่งที่คุณกำลังมองหา

การใช้งาน:

hexdiff file1 file2

จะแสดงเลขฐานสิบหก (และ ASCII 7 บิต) ของไฟล์สองไฟล์ที่อยู่เหนืออีกไฟล์หนึ่งโดยมีการเน้นที่ความแตกต่างใด ๆ ดูman hexdiffคำสั่งที่จะย้ายไปรอบ ๆ ในไฟล์และวิqจะออกจาก


4
แต่มันก็เป็นงานที่แย่มากเมื่อเทียบกับส่วนเปรียบเทียบ หากคุณใส่ไบต์บางลงในไฟล์ก็จะทำเครื่องหมายไบต์ทั้งหมดภายหลังการเปลี่ยนแปลง
Murmel

และ hexdiff ไม่สามารถใช้ได้ผ่าน apt-get บน Ubuntu 16.4
rubo77

1
@Murmel ในขณะที่ฉันเห็นด้วยนั่นคือสิ่งที่ถูกถามที่นี่?
Evan Carroll

@EvanCarroll จริงและด้วยเหตุนี้ฉันออกความคิดเห็น (เท่านั้น) และไม่ได้ลงคะแนน
Murmel

ฉันยังไม่ได้ลงคะแนนมิค แต่ฉันเห็นด้วยกับคุณและตอบที่นี่superuser.com/a/1373977/11116เพราะดูเหมือนว่าคำถามที่ไม่ดีนี้จะได้รับการปฏิรูปหรือปิด
Evan Carroll

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 เป็นมากกว่า hex editor อื่น ๆ : มันมีโหมด diff ซึ่งสามารถใช้เพื่อเปรียบเทียบไบนารีไฟล์สองไฟล์ได้อย่างง่ายดายและสะดวก เนื่องจากมันขึ้นอยู่กับ ncurses และเป็นรูปแบบมันจึงสามารถทำงานได้กับระบบและสถานการณ์ต่างๆ ด้วยการใช้บันทึกการค้นหาทำให้สามารถติดตามการเปลี่ยนแปลงในการวนซ้ำของไฟล์ต่าง ๆ ได้อย่างง่ายดาย


ยินดีต้อนรับสู่ SuperUser! แม้ว่าซอฟต์แวร์นี้จะดูเหมือนว่าจะสามารถแก้ปัญหาของ OP ได้ แต่การโฆษณาล้วนๆ หากคุณมีส่วนเกี่ยวข้องกับโปรแกรมแก้ไขของซอฟต์แวร์นี้โปรดเปิดเผยข้อเท็จจริงนี้ และพยายามเขียนโพสต์ของคุณใหม่เพื่อให้ดูเหมือนโฆษณาน้อยลง ขอขอบคุณ.
Nathan.Eilisha Shiraini

ฉันไม่ได้มีส่วนเกี่ยวข้องกับ dhex แต่อย่างใด ฉันคัดลอกคำอธิบายของผู้เขียนลงในโพสต์เนื่องจากมีการจำกัดความยาวโพสต์ต่ำสุด
Vincent Vega


0

คุณสามารถใช้เครื่องมือgvimdiffที่รวมอยู่ในแพ็คเกจvim-gui-common

sudo apt-get update

sudo apt-get install vim-gui-common

จากนั้นคุณสามารถเปรียบเทียบไฟล์ hex 2 ไฟล์โดยใช้คำสั่งต่อไปนี้:

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

ในตัวอย่างของ OP เมื่อทำ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 เป็นเครื่องมือ UI ที่ยอดเยี่ยมสำหรับการเปรียบเทียบไฟล์ไบนารีที่เพิ่งเปิดมาเมื่อไม่นานมานี้


3
มันสามารถใช้กับไฟล์ไบนารีโดยพลการได้หรือไม่? ดูเหมือนว่าหน้าดังกล่าวจะระบุว่ามีประโยชน์สำหรับการเปรียบเทียบไฟล์ประมวลผลที่ถูกถอดออกโดย Hex-Rays IDA Pro เท่านั้น
eswald

-2

ผลิตภัณฑ์โอเพ่นซอร์สบนลีนุกซ์ (และทุกอย่างอื่น) คือ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 เป็นหลักเครื่องมือสำหรับการวิเคราะห์ไบนารีคุณยังสามารถแสดงเดลต้า diffing ด้วย-dหรือแสดงไบต์ disassembled -Dแทนเลขฐานสิบหกด้วย

หากคุณกำลังถามคำถามแบบนี้ลองดู

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.