Dd ile bir ikili dosya ekleme


32

Bu alıntıyı (aşağıda) birkaç kez okudum, en son burada , ve sürekli bir derleyiciden bile bir şeyidd yamalamak için nasıl kullanılacağına sürekli şaşırdım :

30 yıl önce okulda kullandığım Unix sistemi RAM ve Disk alanında çok sınırlıydı. Özellikle, /usr/tmpdosya sistemi çok küçüktü ve birileri büyük bir programı derlemeye çalıştığında sorunlara yol açtı. Tabii ki, öğrencilerin yine de "büyük programlar" yazmaması gerekiyordu; büyük programlar tipik olarak "bir yerden" kopyalanan kaynak kodlarıdır. Birçoğumuz kopyalanan /usr/bin/cciçin /home/<myname>/ccve kullanılan ddkullanımı ikili yama /tmpyerine/usr/tmp daha büyük olan,. Tabii ki, bu sorunu daha da kötüleştirdi - bu kopyaların işgal ettiği disk alanı o günlerde önemliydi ve şimdi /tmpdüzenli olarak doldu, diğer kullanıcıların dosyalarını bile düzenlemesini engelledi. Ne olduğunu öğrendikten sonra, sistem yöneticileri birchmod go-r /bin/* /usr/bin/* sorunu "düzelten" ve C derleyicisinin tüm kopyalarını silen.

(Vurgu madeni)

ddAdam sayfalık yama hakkında hiçbir şey ifade edilenlerle bu Zaten yapacak amaçlı yeniden olması gerektiği sanmıyorum.

İkili dosyalar gerçekten eklenebilir ddmi? Bunun tarihsel bir önemi var mı?


3
Tabii - sadece odbyte hex kodları için bir dosya, ihtiyacınız olan ofseti bulun, düzenlemenize karar verin ve bs=$patchsize count=1 seek=$((offset/bs)) conv=notrunc
yamanız

3
Birisi asla bir önyükleme sektörünün üzerine yazmamış. ;)
Parthian Shot

@ParthianShot Aslında, bir kez Debian LiveCD'nin bir parçası olan ilk ~ 260 MB önyükleme sürücümün (+ root) üzerine yazdım. O_o Ama bunun gerçekten
yamalı

1
Daha doğrusu, bu, Disk Destroyer'ın beklenen ve tamamen normal davranışıdır: D
Amziraro

Yanıtlar:


73

Hadi deneyelim. İşte önemsiz bir C programı:

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

Bunu şu şekilde inşa edeceğiz test:

$ cc -o test test.c

Eğer çalıştırırsak, "/ usr / tmp" yazar.

/usr/tmpİkili " " nin nerde olduğunu bulalım :

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

-t d Ofseti, ondalık basamağa bulduğu her dizgenin dosyasına basar .

Şimdi sadece " /tmp\0" ile geçici bir dosya yapalım :

$ printf "/tmp\x00" > tmp

Şimdi ikilimiz var, değiştirmek istediğimiz dizginin nerede olduğunu biliyoruz ve içinde yedek dizginin bulunduğu bir dosya var.

Şimdi kullanabiliriz dd:

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

Bu, tmp(" /tmp\0" dosyamızdaki) gelen verileri okur , 1 bayt'lık bir çıkış bloğu boyutu kullanarak, ikili dosyamıza yazar, daha önce herhangi bir şey yazmadan önce bulduğumuz ofsete atlar ve bittiğinde dosyayı kesin olarak kesmez.

Yamalı yürütülebilir dosyayı çalıştırabiliriz:

$ ./test
/tmp

Programın yazdığı değişmez dizisi değiştirildi, bu nedenle şimdi " /tmp\0tmp\0" içeriyor , ancak dizge işlevleri ilk boş baytı gördüklerinde durur. Bu yama, ipin sadece daha kısa veya aynı uzunlukta olmasına ve daha uzun olmamasına izin verir, ancak bu amaçlar için yeterlidir.

Bu yüzden sadece kullanarak şeyleri düzeltmekle kalmayıp, ddsadece yaptık


1
Bu mükemmel ... ve kesinlikle bir üretim ortamında asla karşılaşmamayı umduğum bir şey! Geçmişte benzer yöntemleri mikrodenetleyiciler için onaltılık görüntüye almak için benzer yöntemler kullandım, yine de ayağınıza basmak çok kolay.
Michael Shaw,

Birine belli bir binary yamasını nasıl yapacağımla ilgili yazılı talimatlar vermek istersem, onlara "onaltılık düzenleyicide dosyayı aç, /usr/tmpdizeyi bul , yerine /tmpkoy izleyen \0baytı unutma, dosyayı kaydet ve parmaklarını çarp ". Veya daha da iyisi, önce bazı akıl sağlığı kontrol eden bir kabuk betiği, sonra çağırır dd. Bir artık dağılmış satıcı tarafından yazılımın eski bir parçası sadece Ne yazık ki, bu gibi şeyler için ihtiyaç sık sık ortaya çıkar vardır yeni sisteme taşınacak.
Guntram Blohm,

Evet, sed bu tür şeyler için daha iyidir. Ancak, "Bu yama yalnızca ipin daha kısa veya aynı uzunlukta ve daha uzun olmasına izin verir" konusunda tamamen haklı değilsindir. Değiştirmek istediğiniz dizeyi hemen takip eden verilere hemen önem verdiğinizi veya bir sonraki dizgeye orijinal dizginin bir alt dizisi olamayacağınızı varsayıyorsunuz. Başka bir deyişle, hafızanın .strings bölümündeyseniz ve "/ usr \ 0 / bin / bash \ 0" kodunuz varsa, önce onu değiştirerek / usr / bin / bash komutuna dönüştürebilirsiniz. boş bayt ve "/ usr // bin / bash" (örneğin).
Parthian Shot,

2
@ParthianShot - sed's değil bu tür şeyleri daha iyi - yapabilecekleriniz o kadar expliciltly ve hassas sınırı sed' ın okuma / Birlikte olabilir şekilde yazma tamponlar dd- her zamankinden ilk etapta bu kullanıldı bütün nedenidir. İle ddsize keyfi keyfi bir bayt ile ifade sayımını yerleştirebilirsiniz. Bu da söylenemez sed. Eğer ddburada bir neşter gibi kullanılır, sen de geçerli olacak sedbir yıkım topu gibi.
mikeserv

Bu adil (nadiren de olsa!) Bir nokta - sonucu ya da başka bir keyfi, ancak belirli bir veri parçasını umursamayarak ipi daha uzun hale getirebileceğiniz durumlar olacaktır. Yine de genel açıklamada duracağım.
Michael Homer

9

"İkili yamayı" ile ne demek istediğine bağlı.

İkili dosyaları ddbazen kullanarak değiştiriyorum . Elbette böyle bir özellik yoktur dd, ancak dosyaları açabilir ve belirli ofsetlerdeki şeyleri okuyabilir ve yazabilir, bu yüzden nereye yazacağınızı biliyorsanız, işte yamanız.

Örneğin, bazı PNG verilerini içeren bu ikili dosyaya sahibim. Ofseti binwalkbulmak için kullanın , ddçıkartın (genellikle binwalk da bir şeyler çıkartır ama kopyamda bir yazım hatası vardı), onu düzenleyin gimp, düzenlenen dosyanın orijinalinden daha küçük veya aynı olduğundan emin olun (ofsetleri değiştirmek kolayca yapabileceğiniz bir şey değildir) ) ve ardından dddeğiştirilen görüntüyü tekrar yerine yerleştirmek için kullanın.

$ 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

Bazen, ikilikteki dizeleri de değiştirmek isterim (örneğin yol veya değişken isimleri). Bu kullanılarak da yapılabilir dd, ancak bunu kullanarak yapmak daha kolaydır sed. Yalnızca değiştirdiğiniz dizenin orijinal dizeyle aynı uzunluğa sahip olduğundan emin olmanız gerekir, böylece ofsetleri değiştirmezsiniz.

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

veya @ MichaelHomer örneğini, 0-byte eklenmiş olarak almak için:

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

Tabii ki daha sonra gerçekten işe yarayıp yaramadığını kontrol etmeniz gerekiyor.


... sanırım sedikili dosyaları iyi işleyen bir dosyaya sahipseniz , ki bu gnu için geçerli gibi gözükse de, sadece ascii dosyalarında çalışan sedeskilerin çoğuyla değil sed(özellikle \0girişte) ve maksimum hat uzunluğu konusunda kısıtlamalar vardı.
Guntram Blohm,

1
busybox sedikili dosyaları iyi değiştirebiliyor gibi görünüyor ancak \x00GNU'nun sedyaptığı gibi yeni dizgede anlamıyor . Test gerektiriyor ancak yine ddde bazı durumlarda çok daha basit olduğu için bahsetmeye değer olduğunu düşünüyorum . İkilileri yamalamak her iki şekilde de flakey bir iştir.
frostschutz
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.