การปรับปรุงไบนารีด้วย dd


32

ฉันได้อ่านคำพูดนี้ (ด้านล่าง) หลายครั้งล่าสุดที่นี่และฉันประหลาดใจอย่างต่อเนื่องว่าddจะใช้ในการแก้ไขสิ่งใดให้คอมไพเลอร์:

ระบบ Unix ที่ฉันใช้ที่โรงเรียนเมื่อ 30 ปีก่อนมีข้อ จำกัด ในเรื่อง RAM และพื้นที่ดิสก์ โดยเฉพาะอย่างยิ่ง/usr/tmpระบบไฟล์มีขนาดเล็กมากซึ่งนำไปสู่ปัญหาเมื่อมีคนพยายามรวบรวมโปรแกรมขนาดใหญ่ แน่นอนว่านักเรียนไม่ควรเขียน "โปรแกรมขนาดใหญ่" อยู่ดี โปรแกรมขนาดใหญ่มักจะคัดลอกซอร์สโค้ดจาก "ที่ไหนสักแห่ง" พวกเราหลายคนคัดลอก/usr/bin/ccไปยัง/home/<myname>/ccและใช้ddเพื่อแก้ไขไบนารีเพื่อใช้/tmpแทน/usr/tmpซึ่งใหญ่กว่า แน่นอนว่าสิ่งนี้ทำให้ปัญหาแย่ลง - พื้นที่ดิสก์ที่ครอบครองโดยสำเนาเหล่านี้มีความสำคัญในปัจจุบันและ/tmpเต็มไปด้วยสิ่งนี้เป็นประจำทำให้ผู้ใช้รายอื่นไม่สามารถแก้ไขไฟล์ได้ หลังจากที่พวกเขาพบว่าเกิดอะไรขึ้นผู้ดูแลระบบก็ทำchmod go-r /bin/* /usr/bin/* ซึ่ง "แก้ไข" ปัญหาและลบสำเนาของคอมไพเลอร์ C ทั้งหมดของเรา

(เหมืองเน้น)

ddคนหน้าไม่พูดอะไรเกี่ยวกับปะและไม่คิดว่ามันอาจจะเป็นใหม่วัตถุประสงค์ที่จะทำต่อไปนี้

ไบนารีสามารถได้รับการแก้ไขด้วยddหรือไม่ มีความสำคัญทางประวัติศาสตร์ในเรื่องนี้หรือไม่?


3
แน่นอนว่า - เพียงodไฟล์สำหรับรหัสฐานสิบหกค้นหาสิ่งชดเชยที่คุณต้องการตัดสินใจแก้ไขและbs=$patchsize count=1 seek=$((offset/bs)) conv=notruncแพตช์ของคุณติดตั้งเลย
mikeserv

3
บางคนไม่เคยเขียนทับบูตเซกเตอร์ ;)
คู่ปรับ Shot

@ParthianShot ที่จริงฉันเขียนทับไดรฟ์บูต (+ ราก) ~ 260MB แรกของฉันกับ Debian LiveCD เพียงครั้งเดียว O_o แต่ฉันไม่คิดว่าจริง ๆ กำลังปรับปรุง hehehe ...
Amziraro

1
หรือว่าเป็นพฤติกรรมที่คาดหวังและปกติโดยสิ้นเชิงของ Disk Destroyer: D
Amziraro

คำตอบ:


73

มาลองดูกัน. นี่คือโปรแกรม C เล็กน้อย:

#include <stdio.h>
int main(int argc, char **argv) {
    puts("/usr/tmp");
}

เราจะสร้างสิ่งต่อไปนี้test:

$ cc -o test test.c

ถ้าเราเรียกใช้มันจะพิมพ์ "/ usr / tmp"

ลองหาว่า "" อยู่ที่ไหน/usr/tmpในไบนารี:

$ strings -t d test | grep /usr/tmp
1460 /usr/tmp

-t d พิมพ์ออฟเซ็ตเป็นทศนิยมลงในไฟล์ของแต่ละสตริงที่พบ

ตอนนี้ให้สร้างไฟล์ชั่วคราวโดยมีเพียง " /tmp\0":

$ printf "/tmp\x00" > tmp

ตอนนี้เรามีไบนารี่เรารู้ว่าสตริงที่เราต้องการเปลี่ยนคืออะไรและเรามีไฟล์ที่มีสตริงแทนที่อยู่

ตอนนี้เราสามารถใช้dd:

$ dd if=tmp of=test obs=1 seek=1460 conv=notrunc

สิ่งนี้อ่านข้อมูลจากtmp( /tmp\0ไฟล์ " " ของเรา) เขียนลงในไบนารี่ของเราโดยใช้ขนาดบล็อกออก 1 ไบต์ข้ามไปยังออฟเซ็ตที่เราพบก่อนหน้านี้ก่อนที่จะเขียนอะไรและไม่ตัดทอนไฟล์เมื่อทำเสร็จ

เราสามารถเรียกใช้ไฟล์ปฏิบัติการที่ถูกแก้ไขได้:

$ ./test
/tmp

สตริงตัวอักษรที่โปรแกรมพิมพ์มีการเปลี่ยนแปลงดังนั้นตอนนี้จึงมี " /tmp\0tmp\0" แต่ฟังก์ชั่นสตริงจะหยุดทันทีที่เห็นไบต์แรก การแพตช์นี้อนุญาตให้ทำให้สตริงสั้นลงหรือยาวเท่ากันและไม่นาน แต่ก็เพียงพอสำหรับวัตถุประสงค์เหล่านี้

ดังนั้นไม่เพียง แต่เราสามารถแก้ไขสิ่งต่าง ๆ โดยใช้ddเราเพิ่งทำมัน


1
นี่เป็นสิ่งที่ยอดเยี่ยม ... และสิ่งที่ฉันหวังเป็นอย่างยิ่งว่าฉันจะไม่พบเจอในสภาพแวดล้อมการผลิต! ฉันเคยใช้วิธีการที่คล้ายกันในอดีตเพื่อรับหมายเลขซีเรียลเป็นภาพฐานหกสำหรับไมโครคอนโทรลเลอร์มันง่ายเกินไปที่จะถ่ายภาพตัวเองด้วยการเดินเท้า
Michael Shaw

หากฉันต้องการให้คำแนะนำเป็นลายลักษณ์อักษรแก่ผู้อื่นถึงวิธีการแก้ไขไบนารีเฉพาะฉันต้องการให้พวกเขาบรรทัดคำสั่งเพื่อคัดลอก / วางมากกว่าบอกพวกเขา "เปิดไฟล์ใน hex editor, หา/usr/tmpสตริงแทนที่ด้วย/tmpDon อย่าลืม\0ไบต์ต่อท้ายบันทึกไฟล์และข้ามนิ้วของคุณ " ddหรือดียิ่งขึ้นเชลล์สคริปต์ที่ไม่สติบางตรวจสอบก่อนแล้วโทรออก แต่น่าเสียดายที่จำเป็นสำหรับสิ่งเช่นนี้เกิดขึ้นบ่อยครั้งเมื่อชิ้นเก่าของซอฟต์แวร์โดยผู้ให้บริการนี้หมดอายุเพียงแค่มีที่จะถูกย้ายไปยังระบบใหม่
Guntram Blohm สนับสนุน Monica

ใช่ sed ของที่ดีกว่าสำหรับสิ่งนี้ แต่คุณไม่ถูกต้องเกี่ยวกับทั้งหมด "การปะแก้นี้อนุญาตให้ทำให้สายสั้นลงหรือยาวเท่ากันเท่านั้นและไม่นาน" คุณสมมติว่าคุณสนใจข้อมูลตามสตริงที่คุณต้องการแก้ไขทันทีหรือคุณไม่สามารถมีสตริงถัดไปเป็นสตริงย่อยของสตริงเดิมได้ กล่าวอีกนัยหนึ่งถ้าคุณอยู่ในส่วน .strings ของหน่วยความจำและคุณมี "/ usr \ 0 / bin / bash \ 0" คุณสามารถเปลี่ยนให้เป็น / usr / bin / bash เพียงแค่เปลี่ยนสิ่งแรก ไบต์ว่างและทำให้เป็น "/ usr // bin / bash" (ตัวอย่าง)
คู่ปรับ Shot

2
@ParthianShot - sed's ไม่ดีกว่าสำหรับชนิดของสิ่งนี้ - คุณไม่สามารถดังนั้น expliciltly และแม่นยำขีด จำกัดsedของบัฟเฟอร์อ่าน / เขียนในแบบที่คุณอาจจะมีdd- ซึ่งเป็นเหตุผลทั้งหมดที่มันเคยถูกใช้สำหรับการนี้ในสถานที่แรก ด้วยddคุณสามารถทำการนับจำนวนไบต์ใด ๆ สิ่งนี้ไม่สามารถพูดsedได้เช่นกัน หากddมีการใช้งานเหมือนมีดผ่าตัดที่นี่คุณจะใช้sedเหมือนลูกบอลทำลาย
mikeserv

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

9

มันขึ้นอยู่กับสิ่งที่คุณหมายถึงโดย "แก้ไขไบนารี"

ddบางครั้งฉันก็เปลี่ยนไบนารีโดยใช้ แน่นอนว่าไม่มีคุณสมบัติดังกล่าวddแต่สามารถเปิดไฟล์และอ่านและเขียนสิ่งต่าง ๆ ในออฟเซ็ตเฉพาะดังนั้นหากคุณรู้ว่าจะเขียนตำแหน่งไหน voila จะมีแพตช์ของคุณ

ตัวอย่างเช่นฉันมีไบนารีนี้ที่มีข้อมูล PNG บางส่วน ใช้binwalkเพื่อค้นหาออฟเซ็ตddเพื่อแยกมัน (โดยปกติ binwalk จะแยกสิ่งต่าง ๆ แต่สำเนาของฉันเป็น buggy) แก้ไขด้วยgimpตรวจสอบให้แน่ใจว่าไฟล์ที่แก้ไขมีขนาดเดียวกันหรือเล็กกว่าเดิม (เปลี่ยนออฟเซ็ตไม่ใช่สิ่งที่คุณทำได้ง่ายๆ ) จากนั้นใช้ddเพื่อทำให้ภาพที่ถูกเปลี่ยนกลับมาอยู่กับที่

$ binwalk thebinary
[…]
4194643    0x400153     PNG image, 800 x 160, 8-bit/color RGB, non-interlaced
[…]
$ dd if=nickel bs=1 skip=4194641 count=2 conv=swab | od -i
21869 # file size in this case - depends on the binary format
$ dd if=thebinary bs=1 skip=4194643 count=21869 of=theimage.png
$ gimp theimage.png
$ pngcrush myimage.png myimage.crush.png
# make sure myimage.crush.png is smaller than the original
$ dd if=myimage.crush.png of=thebinary bs=1 seek=4194643 conv=notrunc

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

sed -e s@/the/old/save/path@/the/new/save/path@ -i thebinary

หรือรับตัวอย่าง @ MichaelHomer พร้อมกับเพิ่ม 0 ไบต์ใน:

sed -e 's@/usr/tmp@/tmp\x00tmp@' -i test

แน่นอนคุณต้องตรวจสอบว่ามันใช้งานได้จริงในภายหลัง


... สมมติว่าคุณมีsedไฟล์ไบนารีที่จัดการได้ดีซึ่งดูเหมือนจะเป็นกรณีของ gnu sedแต่ไม่ใช่กับรุ่นเก่าsedที่ทำงานกับไฟล์ ASCII เท่านั้นสับสนกับสิ่งอื่น (โดยเฉพาะ\0ในอินพุต) และมีข้อ จำกัด เกี่ยวกับความยาวบรรทัดสูงสุด
Guntram Blohm สนับสนุน Monica

1
sedดูเหมือนว่าbusybox จะสามารถเปลี่ยนไฟล์ไบนารีได้ดี แต่ไม่เข้าใจ\x00ในสตริงการแทนที่อย่างที่ GNU sedทำ มันต้องมีการทดสอบ แต่ถึงอย่างนั้นฉันก็คิดว่ามันคุ้มค่าที่จะพูดถึงเพราะมันง่ายกว่าdd- สำหรับบางกรณี การปรับปรุงไบนารีเป็นธุรกิจที่ไม่มั่นคง
frostschutz
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.