Menambal biner dengan dd

32

Saya telah membaca kutipan ini (di bawah) beberapa kali, paling baru di sini , dan saya terus-menerus bingung bagaimana ddbisa digunakan untuk menambal apa pun apalagi kompiler:

Sistem Unix yang saya gunakan di sekolah, 30 tahun yang lalu, sangat terbatas dalam ruang RAM dan Disk. Terutama, /usr/tmpsistem file sangat kecil, yang menyebabkan masalah ketika seseorang mencoba menyusun program besar. Tentu saja, siswa tidak seharusnya menulis "program besar"; program besar biasanya kode sumber disalin dari "suatu tempat". Banyak dari kita disalin /usr/bin/ccke /home/<myname>/cc, dan digunakan dduntuk menambal biner untuk menggunakan /tmpbukan/usr/tmp , yang lebih besar. Tentu saja, ini hanya memperburuk masalah - ruang disk yang ditempati oleh salinan ini memang penting hari itu, dan sekarang /tmpterisi penuh, mencegah pengguna lain bahkan mengedit file mereka. Setelah mereka mengetahui apa yang terjadi, para sysadmin melakukanchmod go-r /bin/* /usr/bin/* yang "memperbaiki" masalah, dan menghapus semua salinan kami dari kompiler C.

(Penekanan milikku)

Halaman ddmanual tidak mengatakan apa-apa tentang menambal dan tidak berpikir itu bisa bertujuan ulang untuk melakukan hal ini.

Bisakah binari benar-benar ditambal dd? Apakah ada signifikansi historis untuk ini?

Amziraro
sumber
3
Tentu - hanya odfile untuk kode hex byte, menemukan offset yang Anda butuhkan, memutuskan mengedit, dan bs=$patchsize count=1 seek=$((offset/bs)) conv=notruncpatch Anda tepat di dalam.
mikeserv
3
Seseorang tidak pernah menimpa sektor boot. ;)
Parthian Shot
@ParthianShot Sebenarnya saya menimpa ~ 260MB pertama dari boot drive saya (+ root) dengan bagian dari LiveCD Debian sekali. O_o Tapi saya tidak berpikir itu benar-benar menambal, hehehe ...
Amziraro
1
Atau lebih tepatnya, itu adalah perilaku Penghancur Disk yang diharapkan dan benar-benar normal: D
Amziraro

Jawaban:

73

Ayo kita coba. Berikut ini adalah program C sepele:

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

Kami akan membangunnya menjadi test:

$ cc -o test test.c

Jika kita menjalankannya, ia mencetak "/ usr / tmp".

Mari kita cari tahu di mana " /usr/tmp" ada dalam biner:

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

-t d mencetak offset dalam desimal ke dalam file dari setiap string yang ditemukannya.

Sekarang mari kita membuat file sementara hanya dengan " /tmp\0" di dalamnya:

$ printf "/tmp\x00" > tmp

Jadi sekarang kita memiliki biner, kita tahu di mana string yang ingin kita ubah adalah, dan kita memiliki file dengan string pengganti di dalamnya.

Sekarang kita bisa menggunakan dd:

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

Ini membaca data dari tmp( /tmp\0"file " kami ), menulisnya ke dalam biner kami, menggunakan ukuran blok keluaran 1 byte, melompati ke offset yang kami temukan sebelumnya sebelum menulis apa pun, dan secara eksplisit tidak memotong file ketika selesai.

Kita dapat menjalankan executable yang ditambal:

$ ./test
/tmp

String literal yang dicetak oleh program telah diubah, jadi sekarang berisi " /tmp\0tmp\0", tetapi fungsi string berhenti segera setelah mereka melihat byte nol pertama. Penambalan ini hanya memungkinkan membuat string lebih pendek atau sama panjang, dan tidak lebih lama, tetapi cukup untuk keperluan ini.

Jadi kita tidak hanya dapat menambal menggunakan sesuatu dd, kita baru saja melakukannya.

Michael Homer
sumber
1
Ini luar biasa ... dan sesuatu yang sangat saya harap tidak pernah saya temui di lingkungan produksi! Saya telah menggunakan metode serupa di masa lalu untuk mendapatkan nomor seri menjadi gambar hex untuk mikrokontroler, itu terlalu mudah untuk menembak diri sendiri di kaki.
Michael Shaw
Jika saya ingin memberikan instruksi tertulis kepada seseorang cara menambal biner tertentu, saya lebih suka memberi mereka baris perintah untuk menyalin / menempel daripada memberi tahu mereka "buka file dalam hex editor, temukan /usr/tmpstring, ganti dengan /tmp, don lupakan \0byte trailing , simpan file, dan silangkan jari Anda ". Atau, bahkan lebih baik, skrip shell yang melakukan pengecekan kewarasan terlebih dahulu, lalu menelepon dd. Sayangnya, kebutuhan untuk hal-hal seperti ini sering muncul ketika sepotong tua software oleh vendor sekarang sudah tidak berfungsi hanya memiliki untuk bermigrasi ke sistem baru.
Guntram Blohm mendukung Monica
Ya, sed lebih baik untuk hal semacam ini. Tapi Anda tidak sepenuhnya benar tentang keseluruhan "Penambalan ini hanya memungkinkan membuat string lebih pendek atau sama panjang, dan tidak lebih lama". Anda berasumsi bahwa Anda peduli dengan data segera mengikuti string yang ingin Anda modifikasi, atau bahwa Anda tidak dapat memiliki string berikutnya hanya menjadi substring dari string asli. Dengan kata lain, jika Anda berada di bagian .strings dari memori, dan Anda mendapatkan "/ usr \ 0 / bin / bash \ 0", Anda dapat mengubahnya menjadi / usr / bin / bash dengan hanya mengubah itu terlebih dahulu null byte dan menjadikannya "/ usr // bin / bash" (misalnya).
Parthian Shot
2
@ParthianShot - sedIni tidak baik untuk hal semacam ini - Anda tidak bisa begitu expliciltly dan tepat batas sed's read / write buffer dalam cara Anda mungkin dengan dd- yang merupakan seluruh alasan itu pernah digunakan untuk ini di tempat pertama. Dengan ddAnda dapat secara sewenang-wenang menempatkan jumlah byte yang sewenang-wenang. Ini juga tidak bisa dikatakan sed. Jika dddigunakan seperti pisau bedah di sini, Anda akan berlaku sedseperti bola perusak.
mikeserv
Itu poin yang adil (meskipun cukup langka!) - Akan ada saat-saat ketika Anda dapat membuat string lebih lama dengan tidak peduli tentang hasil atau sepotong data yang sewenang-wenang, tetapi spesifik. Saya akan mendukung pernyataan umum.
Michael Homer
9

Itu tergantung pada apa yang Anda maksud dengan "menambal biner".

Saya mengubah biner menggunakan ddkadang - kadang. Tentu saja tidak ada fitur seperti itu didd dalamnya, tetapi dapat membuka file, dan membaca dan menulis hal-hal di offset tertentu, jadi jika Anda tahu apa yang harus ditulis di mana, voila ada tambalan Anda.

Misalnya saya punya biner ini yang berisi beberapa data PNG. Gunakan binwalkuntuk menemukan offset, dduntuk mengekstraknya (biasanya binwalk juga mengekstraksi sesuatu tetapi salinan saya buggy), mengeditnya dengan gimp, pastikan file yang diedit berukuran sama atau lebih kecil dari yang asli (mengganti offset bukan sesuatu yang dapat Anda lakukan dengan mudah ), dan kemudian gunakan dduntuk meletakkan gambar yang diubah kembali ke tempatnya.

$ 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

Terkadang saya juga ingin mengganti string dalam binari (seperti path atau nama variabel). Meskipun ini juga bisa dilakukan menggunakan dd, lebih mudah untuk melakukannya menggunakan sed. Anda hanya perlu memastikan string yang Anda ganti memiliki panjang yang sama dengan string asli sehingga Anda tidak akhirnya mengganti offset.

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

atau untuk mengambil contoh @ MichaelHomer dengan 0 byte ditambahkan pada:

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

Tentu saja Anda harus memverifikasi apakah itu benar-benar berfungsi setelahnya.

frostschutz
sumber
... anggap Anda memiliki sedfile biner yang dapat ditangani dengan baik, yang tampaknya merupakan masalah dengan gnu sed, tetapi tidak dengan banyak file lama sedyang hanya bekerja pada file ascii, bingung dengan hal lain (terutama \0dalam input), dan memiliki batasan panjang garis maksimum.
Guntram Blohm mendukung Monica
1
busybox sedtampaknya dapat mengubah file biner dengan baik tetapi tidak mengerti \x00dalam string pengganti seperti cara GNU sed. Ini membutuhkan pengujian tetapi meskipun demikian saya pikir itu layak disebutkan karena jauh lebih sederhana daripada dd- untuk beberapa kasus. Menambal binari adalah bisnis yang rapuh.
frostschutz