วิธีการแยกเซกเมนต์ของไฟล์ไบนารีโดยยึดตามการเริ่มต้นและสิ้นสุดสตริงสตริง


1

ฉันมีไฟล์ไบนารีขนาดใหญ่ (หลายร้อย GB) และฉันต้องการแยกกลุ่มจากมัน ฉันรู้ว่าสตริงเลขฐานสิบหกของจุดเริ่มต้นและจุดสิ้นสุด

คำตอบ:


2

วิธีแก้ปัญหาที่เป็นไปได้ (สมมติว่าคุณสามารถทำสำเนาไฟล์) สามารถใช้ตัวอย่างต่อไปนี้

  1. สมมติว่ารูปแบบเริ่มต้นคือ hex 4f 0f 87 82
  2. สมมติว่ารูปแบบสิ้นสุดคือ hex fb 8c e2 a0
  3. สมมติว่าไฟล์อินพุตถูกเรียกtfและมีความยาว 5,000 ไบต์

แล้วก็

ทำสำเนาของtfไฟล์ใหม่blahโดยเปลี่ยนรูปแบบเริ่มต้น

$ LC_ALL=C sed 's/'`printf "\x4f\x0f\x87\x82"`'/'`printf "AAAA"`'/'  <tf > blah

ตอนนี้หาตำแหน่งที่tfและblahแตกต่างกัน ( note - sed เขียนไบต์พิเศษที่มีการขึ้นบรรทัดใหม่ในตอนท้ายของไฟล์ที่แก้ไขดังนั้นเราจึงเปรียบเทียบกับความยาวของไฟล์ต้นฉบับดังนั้นไฟล์tfที่สร้างblahควรมีความยาวหนึ่งไบต์ )

$ cmp -n 5000 -b tf blah

สิ่งนี้จะให้อ็อฟเซ็ตไบต์, bs, ซึ่งไฟล์ต่างกันเช่น,

tf blah differ: byte 4337, line 10 is 117 O 101 A

ตอนนี้ทำแบบเดียวกันกับตอนจบ

 $ LC_ALL=C sed  's/'`printf "\xfb\x8c\xe2\xa0"`'/'`printf "AAAA"`'/'  < tf > blah2
 $ cmp -n 5000 -b tf blah2
 tf blah2 differ: byte 4433, line 10 is 373 ? 101 A

ตอนนี้ใช้ddเพื่อดึงส่วนที่น่าสนใจ

dd if=tf skip=4336 bs=1 count=100 > fbit

หมายเหตุพิเศษบางประการ:

  1. sed บางรุ่นรองรับ-bตัวเลือกที่ใช้กับไฟล์อินพุตเป็นไบนารี รุ่นอื่นมี-zตัวเลือกที่คั่นบรรทัดด้วยอักขระ NUL ไม่สามารถทดสอบรูปแบบการจับคู่ที่มีบรรทัดใหม่หรือแยกข้ามบรรทัดใหม่ได้

  2. count=100จะขึ้นอยู่กับความยาวของรูปแบบการจับคู่และไม่ว่ารูปแบบการจับคู่ที่จะรวมอยู่ในสารสกัด (ที่ไม่ชัดเจนในคำถาม) สูตรทั่วไปคือนับ = (ตอนจบ offset) - (เริ่ม offset) + (ขนาดของรูปแบบการสิ้นสุด) ชิ้นส่วนสำหรับตัวอย่างเฉพาะคือ 4433-4337 + 1 ซึ่งให้ 97 ไบต์ นั่นคือจากจุดเริ่มต้นของรูปแบบเริ่มต้นจนถึงและรวมถึงไบต์แรกของรูปแบบสิ้นสุด เพิ่ม 3 ไบต์พิเศษเพื่อให้ 100 ในตัวอย่างนี้เนื่องจากรูปแบบสุดท้ายมีสี่ไบต์และตัวอย่างรวมถึงรูปแบบสุดท้าย หากไม่ต้องการรูปแบบสุดท้ายก็count=96จะเป็นค่า

  3. วิธีการที่แข็งแกร่งสำหรับบรรทัดใหม่และการใช้คำสั่ง hexdump เป็นไปได้ ฉันยังไม่ได้ทดสอบวิธีการนั้นอย่างเต็มที่ โดยพื้นฐานแล้วจะใช้ hexdump กับ sed, grep และ tr เล็กน้อยเพื่อแปลงไฟล์ไบนารีดั้งเดิมเป็น hex ในรูปแบบ ascii จากนั้นกระบวนการเดียวกันสามารถนำไปใช้ได้ แต่จะมีการคำนวณทางคณิตศาสตร์มากขึ้น ฯลฯ .... คำสั่ง hexdump ที่ต้องการจะเป็น

    hexdump -v -x tf | sed s/'^[0-9]*\(.*\)/\1/' | sed s'/ *//g' | grep '[0-9]' | tr -d '\n' > tf.txt

  4. หลังจากhexdumpขั้นตอนกระบวนการเดียวกันsedและcmpสามารถใช้งานได้ รูปแบบที่ตรงกันจะต้องมีการอัปเดตเพื่อใช้อักขระ hexdump ascii ไม่ใช่การพิมพ์เลขฐานสิบหกแบบดิบ

  5. วิธีการนี้ควรจัดการกับอักขระบรรทัดใหม่

  6. LC_ALL=Cดูเหมือนว่าจำเป็นสำหรับ OSX เป็นค่าเริ่มต้น โดยไม่ต้องมันสั่งให้ข้อผิดพลาดsed RE error: illegal byte sequenceสิ่งนี้อาจไม่เป็นจริงในทุกแพลตฟอร์มและ / หรือระบบปฏิบัติการ OS


(1) คุณจะได้รับ96อย่างไร (คำแนะนำ: คิดเกี่ยวกับมันผมเชื่อว่ามันผิด..) (2) 0Aนี้จะไม่ทำงานถ้าหนึ่งในไบต์ที่รู้จักกันเป็นฐานสิบหก คุณสามารถขยายคำตอบให้ครอบคลุมกรณีนั้นได้หรือไม่? (3) LC_ALL=Cจำเป็นหรือไม่ คุณอธิบายได้ไหม (4) ในทำนองเดียวกันคุณสามารถอธิบายได้ว่าทำไมจึง-n 5000จำเป็น (5) กรุณาวิจัย“ UUOC” ………………………………ทุก…………………ทุก…………………ทุก……………………ทุก……………………………………………………ทุก………… แก้ไขคำตอบของคุณเพื่อให้ชัดเจนและสมบูรณ์ยิ่งขึ้น
G-Man

แก้ไข - ขอบคุณสำหรับข้อมูล
Chris Hill

ฉันตั้งใจจะบอกว่าฉันคิดว่า98ผิด (ตัว96พิมพ์ผิด) นี่เป็นเพราะคำตอบของคุณแสดงตัวอย่างรูปแบบสิ้นสุดที่มีสี่ไบต์ มิฉะนั้นงานที่ดี
G-Man

แน่นอนว่าสิ่งที่คุณต้องทำคือการsize = (ตอนจบ offset) - (เริ่ม offset) + (ขนาดของรูปแบบการสิ้นสุด) การแบ่ง 4 ลงใน 1 + 3 เป็นเพียงการเพิ่มความซับซ้อน
G-Man
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.