Bu konuyu tartışmaya devam etmeyi dört gözle bekliyordum, size güvenlik açıkları üzerine biraz tarih, teori ve pratik anlatmama izin verin. Şimdiye kadar hepimiz güvenlik kusurlarının çok pahalıya mal olabileceğini duymuşuzdur, hepimiz yazılımımızı güncel tutmamız gerektiğini biliyoruz, hepimiz birçok güncellemenin güvenlik hatalarından kaynaklandığını biliyoruz. Ama bugün size bu hataların nasıl bulunduğunu ve nasıl kullanıldığını biraz anlatacağım 🙂 Ama bundan önce, daha iyi bir genel bakışa sahip olmak için birkaç detayı açıklığa kavuşturacağız.
Başlamadan önce
Öncelikle, yararlanmayı öğrendiğim ilk güvenlik açığına odaklanacağımızı söylemek istiyorum. Arabellek Taşmaları, bu güvenlik açığında eğlenceli şeyler yapmak için bellek doğrulama eksikliğinden yararlanıyoruz 🙂 Ama bunu biraz daha açıklayalım.
Bu gerçek bir dünya senaryosu olmayacak
Onlara gördükleri herhangi bir programı kırmayı öğretemem - ilk önce bilgisayarları için tehlikelidir, ikincisi bu benim normal kelime kotamdan fazlasını alır.
80'lere gidiyoruz
Size göstereceğim şey dizüstü bilgisayarımda yapabileceğim, ancak bugün basit bir şekilde yapılabileceği anlamına gelmiyor 🙂 bu kavramların birçoğu o kadar çok kez kullanıldı ki, yeni koruma yöntemleri ve yeni yöntemlerden kaçınılır ortaya çıktılar 😛 ama bu bizi aynı yere döndürüyor, bunların hepsini anlatacak yer yok 🙂
İşlemcinizde çalışmayabilir
Çok basit bir örnek kullanacak olsam da, bunun ayrıntılarının o kadar çok ve o kadar çeşitli ki, denemek isterseniz, benimle aynı şekilde ortaya çıkabildiğinin en başından oldukça açık olmasını istiyorum. İstenilen etkiye de ulaşılamayabilir 🙂 Ama bunu bu alanda açıklayamayacağımı hayal edebilirsiniz, özellikle de bu girişle zaten 300 kelimeden fazla konuştuğum için, doğrudan bizim amacımıza ulaşıyoruz.
Nedir Arabellek Taşması
Bunu cevaplamak için önce bu kombinasyonun ilk yarısını anlamalıyız.
tamponlar
Her şey bir bilgisayardaki bellekle ilgili olduğundan, bir tür bilgi kabı olması mantıklıdır. Hakkında konuştuğumuzda girişler o çıkışlardoğrudan kavramına geliyoruz tamponlar. Kısa tutmak için, bir tampon Bir miktar bilgiyi depolayacağımız, tanımlı büyüklükte bir hafıza alanıdır, basit 🙂
Adından da anlaşılacağı gibi, bir arabellek işleyebileceğinden daha fazla bilgi ile dolduğunda taşmalar meydana gelir. Ama bu neden önemli?
Yığın
Yığınlar olarak da bilinir, yapabileceğimiz soyut bir veri türüdür. yığın bilgi, temel özellikleri bir siparişe sahip olmalarıdır. LIFO (Son Giren İlk Çıkar). Bir saniyeliğine bir tabak yığınını düşünelim, onları teker teker üste koyarız ve sonra onları teker teker yukarıdan çıkarırız, bu koyduğumuz son tabağı yapar (en üstte olanı) ) çıkaracağımız ilk tabaktır, tabii ki bir seferde sadece bir tabak çıkarabilirsek ve bu sırayla yapmaya karar verirsek: P.
Artık bu iki kavramı bildiğinize göre, onları sıraya koymalıyız. Yığınlar önemlidir çünkü çalıştırdığımız her programın kendine ait yürütme yığını. Ama bu yığının bir belirli karakteristik, büyür. Bununla ilgili bilmeniz gereken tek şey, bir program çalışırken, bir işlev çağrıldığında, yığının bellekteki X sayısından bir sayıya (Xn) gitmesidir. Ancak devam etmek için bir kavramı daha anlamalıyız.
İşaretçiler
Bu, C dünyasına başladıklarında birçok programcıyı çılgına çeviren bir kavramdır, aslında C programlamanın büyük gücü kısmen işaretçilerin kullanımından kaynaklanmaktadır. Basit tutmak için bir işaretçi bir hafıza adresini gösterir. Kulağa karmaşık geliyor ama o kadar da karmaşık değil, hepimizin makinelerimizde RAM var değil mi? Bu şu şekilde tanımlanabilir: blokların ardışık düzeni, bu konumlar normalde onaltılık sayılarla ifade edilir (0'dan 9'a ve sonra A'dan F'ye, örneğin 0x0, 0x1, 0x6, 0xA, 0xF, 0x10). Burada ilginç bir not olarak, 0x10 YOK HAYIR 10'a eşittir 😛, eğer onu ondalık sıraya çevirirsek, 15 demekle aynı olur. Bu, ilk başta birden fazla kafayı karıştıran bir şey, ama hadi aşağı inelim.
kayıtlar
İşlemciler bir dizi kayıtlar, fiziksel bellekten işlemciye konumları iletmek için çalışan, 64 bit kullanan mimariler için, yazmaçların sayısı büyük ve burada tanımlanması zor, ancak fikri elde etmek için, kayıtlar işaretçiler gibidir, diğerlerinin yanı sıra bir hafıza alanı (konum).
Şimdi pratik yap
Şimdiye kadar işlenmesi gereken çok fazla bilgi olduğunu biliyorum, ancak gerçekte bunlar çok basit bir şekilde açıklamaya çalıştığım biraz karmaşık meseleler, tampon kullanan küçük bir program göreceğiz ve bunu anlamak için kırın, açıkçası bu değil Bu gerçek bir program ve bugün kullanılan birçok karşı önlemden "kaçacağız", sadece daha önce işlerin nasıl yapıldığını göstermek için 🙂 ve çünkü bunlardan bazıları Daha karmaşık şeyleri öğrenebilmek için ilkeler gereklidir 😉
GDB
Şüphesiz C programcıları tarafından en çok kullanılan harika bir program. Pek çok erdemi arasında şimdiye kadar bahsettiğimiz tüm bunları, yazmaçları, yığınları, arabellekleri vb. Görmemize izin verdiği gerçeğine sahibiz. Örneğimiz için kullanacağımız programı görelim.
retinput.c
Bu oldukça basit bir program, kütüphaneyi kullanacağız stdio.h
bilgi elde edebilme ve bir terminalde görüntüleyebilme. Adlı bir işlevi görebiliriz return_input
hangi bir tampon denilen diziuzunluğu 30 olan bayt (char veri türü 1 bayt uzunluğundadır).
İşlevi gets(array);
konsol ve işlevle bilgi isteme printf()
dizinin içeriğini döndürür ve ekranda görüntüler.
C'de yazılan her program, işlevle başlar main()
, bu sadece return_input'u çağırmaktan sorumlu olacak, şimdi programı derleyeceğiz.
Biraz önce yaptığımdan biraz alalım. Seçenek -ggdb
gcc'ye programı gdb'nin düzgün bir şekilde hata ayıklayabilmesi için bilgilerle derlemesini söyler. -fno-stack-protector
Açıkça kullanmamamız gereken, ancak kullanacağımız bir seçenektir çünkü aksi takdirde yığında tampon taşması oluşturmak mümkün olur. Sonunda sonucu test ettim. ./a.out
sadece az önce derlediğim şeyi çalıştırıyor, bilgi istiyor ve geri veriyor. Koşu 🙂
uyarılar
Burada başka bir not. Uyarıları görebiliyor musunuz? Açıkça, kodla veya derlemeyle çalışırken hesaba katılması gereken bir şey, bu biraz açık ve bugün işleve sahip çok az program var gets()
Kodda. Gentoo'nun bir avantajı, her programı derleyerek neyin yanlış olabileceğini görebilirim, "ideal" bir programın bunlara sahip olmaması gerekir, ancak kaç tane büyük programın bu uyarılara sahip olduğuna şaşıracaksınız çünkü bunlar sadece ÇOK büyük ve bu aynı anda çok sayıda uyarı olduğunda tehlikeli işlevler. Şimdi devam edersek
Programda hata ayıklama
Şimdi bu kısım biraz kafa karıştırıcı olabilir, ama zaten biraz yazdığım için her şeyi açıklamaya gücüm yetmez, çok hızlı gittiğimi görürseniz özür dilerim 🙂
Kodu etkisiz hale getirme
Derlenmiş makine dili programımıza bakarak başlayalım.
Bu, ana işlevimizin kodudur. Montaj, bu işlemcimizin anladığı şeydir, soldaki satır hafızadaki fiziksel adres, <+ n> olarak bilinir ofset, temel olarak işlevin başlangıcından (ana) bu ifadeye (olarak bilinir) işlemkodu). Daha sonra komut türünü (push / mov / callq…) ve bir veya daha fazla kaydı görüyoruz. Özetle, kaynak / menşe ve varış noktasının ardından bir gösterge olduğunu söyleyebiliriz. <return_input>
ikinci fonksiyonumuza değiniyor, bir bakalım
return_input
Bu biraz daha karmaşık, ancak birkaç şeyi kontrol etmenizi istiyorum, adında bir etiket var <gets@plt>
ve son bir işlem kodu çağrıldı retq
işlevin sonunu gösterir. Fonksiyona bir tane olmak üzere birkaç kesme noktası koyacağız gets
ve başka retq
.
koşmak
Şimdi eylemin nasıl başladığını görmek için programı çalıştıracağız.
Bulunduğumuz yerdeki işlem kodunu gösteren küçük bir ok göründüğünü görebiliriz, yönünü hesaba katmalarını istiyorum. 0x000055555555469b
bu, arandıktan sonraki adres return_input
işlevde main
bu önemlidir, çünkü burası, belgeyi almayı bitirdiğinizde programın giriş, hadi işleve geçelim. Şimdi işleve girmeden önce hafızayı kontrol edeceğiz gets
.
Ana işlevi sizin için yeniden koydum ve atıfta bulunduğum kodu, görebileceğiniz gibi, endianness iki bölüme ayrıldı, yönünü hesaba katmalarını istiyorum 0x7fffffffdbf0
(komandodan sonra soldan ilki x/20x $rsp
) bu, getiri sonuçlarını kontrol etmek için kullanmamız gereken konum olduğu için devam edelim:
Programı bozmak
Onları vurguladım 0x44444444
çünkü onlar bizim D'lerimizin temsili 🙂 şimdi eklemeye başladık giriş programa ve gördüğünüz gibi, istediğimiz adresten sadece iki satırdayız, önceki adımda vurguladığımız adreslerin hemen önüne gelene kadar dolduracağız.
Dönüş yolunu değiştirme
Şimdi kodun fonksiyonun geri dönüşünü gösterdiği bu bölümüne girmeyi başardığımıza göre, biraz önce sahip olduğumuz işlem kodunun konumuna gitmek yerine adresi 🙂 değiştirirsek ne olacağını görelim. geri dönersek ne düşünüyorsun return_input
? Fakat bunun için istediğimiz adresi ikili olarak yazmamız gerekiyor, bunu fonksiyon ile yapacağız printf
bash'dan 🙂
Şimdi bilgiyi iki kez aldık - kesinlikle program bunun için yapılmadı, ancak kodu kırmayı ve yapmaması gereken bir şeyi tekrar etmesini sağladık.
Yansımalar
Bu basit değişiklik bir sömürmek çok basit 🙂 programı bozmayı ve ondan yapmasını istediğimiz bir şeyi yapmayı başardı.
Bu, görülecek ve eklenecek neredeyse sonsuz bir şeyler listesinin ilk adımıdır, bir siparişi tekrarlamaktan daha fazla şey eklemenin yolları vardır, ancak bu sefer çok şey yazdım ve ilgili her şeyi kabuk kodlama makalelerden çok, tam kitaplar yazmak için bir konu diyebilirim. Hoşuma gidecek konulara biraz daha dalamadıysam özür dilerim, ama kesinlikle bir şansım olacak 🙂 Selamlar ve buraya geldiğiniz için teşekkürler.
Daha doğrudan olun. Daha az yazın ve önemli olana odaklanın
Merhaba, yorum için teşekkürler.
Doğruyu söylemek gerekirse, fikirlerin büyük bir kısmını kestim, ama öyle olsa bile, programlama bilgisine sahip olmayan birinin bir fikir edinebilmesi için minimumda kaldığını düşündüm.
selamlar
Sorun şu ki, programlama bilgisine sahip olmayanlar, başlamak için çok karmaşık olduğu için hiçbir şey öğrenemeyecekler, ancak programlamayı bilenler daha doğrudan olmayı takdir edeceklerdir.
Sanırım herkese ulaşamazsınız, seçmek zorundasınız ve bu durumda çok fazla örtmek istemek için günah işlediniz.
Bu arada size yapıcı eleştiri olarak söylüyorum, bu konuları çok seviyorum ve yazı yazmaya devam etmenizi istiyorum, tebrikler!
Ben de aynı şeyi düşünüyorum.
İkisine de çok teşekkür ederim !! Gerçek şu ki, bu makaleleri okuyan ileri düzeyde programlamaya sahip kişilerin sayısı düşükken (en azından yorumlara dayanarak bu çıkarılabilir) hedef kitleye nasıl ulaşılacağını anlamak kesinlikle zordur.
Anlaşılması için geniş bir bilgi tabanı gerektiren bir şeyi basitleştirmek istemekten kesinlikle günah işledim. Umarım blog yazmaya yeni başladığımdan beri, okuyucularımın ne söylediğimi bildiği ve anladığı noktayı henüz tam olarak keşfetmemiş olduğumu anlıyorsunuzdur. Bu gerçeği söylemeyi çok daha kolay hale getirir 🙂
Formatı kişiselleştirmeden, gerektiği zaman kısaltmaya çalışacağım, çünkü yazma şeklini içerikten ayırmak birinin hayal edebileceğinden biraz daha karmaşık, en azından onları oldukça bağlantılı hale getirdim, ama sanırım sonunda yapabileceğim içeriği kesmek yerine satır eklemek için.
selamlar
Konuyla ilgili nereden daha fazla bilgi edinebilirsiniz? Önerilen kitap var mı?
Örnek, Chris Anley, John Heasman, Felix Linder ve Gerardo Richarte tarafından The Shellcoder's Handbook'tan alınmıştır, ancak 64-bit çeviriyi yapmak için mimarim hakkında bilgi edinmem gerekiyordu, intel geliştirici el kitabı, cilt 2 ve 3 bunun için oldukça güvenilir bir kaynak. Ayrıca, 'info gdb' komutuyla gelen GDB belgelerini okumak da iyidir, Assembly ve C'yi öğrenmek için, Assembly kitaplarının biraz eski olması dışında, bir başkasıyla doldurulacak bir boşluk olması dışında, çok iyi birçok kitap vardır. tip belgeleri.
Kabuk kodunun kendisi bugünlerde çeşitli nedenlerle artık o kadar etkili değil, ancak yeni teknikler öğrenmek yine de ilginç.
Umarım biraz yardımcı olur 🙂 Selamlar
Buen artículo, el viejo blog desdelinux ha vuelto a renacer =)
Uzak kabuğun o kadar etkili olmadığını söylediğinizde, saldırıları azaltmak için tasarlanmış karşı önlemleri kastediyorsunuz, buna saldırgan güvenlik diyorlar.
Selamlar ve devam et
Çok teşekkür ederim Franz, çok nazik sözler, aslında bugün Shellcoding'in burada gördüğümüzden çok daha karmaşık olduğunu kastettim. ASLR (rastgele bellek konum üreteci) yığın koruyucumuz, bir programa enjekte edilebilecek işlem kodlarının sayısını sınırlayan çeşitli önlemlere ve karşı önlemlere sahibiz ve bu sadece başlangıç.
Saygılarımızla,
Merhaba, konuyu genişletmek için başka bir bölüm yapacak mısınız? İlginç
Merhaba, konu kesinlikle oldukça ilginç, ancak alacağımız karmaşıklık seviyesi çok yüksek olacak, muhtemelen diğerini anlamak için çeşitli ön koşulları açıklamak için çok sayıda gönderi içerecektir. Muhtemelen bunun hakkında yazacağım ama sonraki yazılar olmayacak, buna devam etmeden önce birkaç konu yazmak istiyorum.
Selamlar ve paylaştığınız için teşekkürler
Çok iyi che! Harika gönderilere katkıda bulunuyorsunuz! Bir soru, bu BT Güvenliği olayına "Kalem testi ile güvenliği sağlamak" adlı bir kitap okuyarak başlıyorum. Bu kitap tavsiye ediliyor mu? Bu konuları araştırmaya başlamamı nasıl önerirsiniz?
Merhaba kaktüs, güvenlik açıkları ve diğerleriyle ilgili bütün bir evren, gerçeği söylemek gerekirse, dikkatinizi çeken şeylere ve sahip olduğunuz ihtiyaçlara çok bağlıdır, bir BT yöneticisinin bir kalem test cihazı ile aynı şeyi bilmesine gerek yoktur. Ya da bir güvenlik açığı araştırmacısı veya bir adli tıp analisti, bir felaket kurtarma ekibinin çok farklı becerileri vardır. Açıkçası her biri farklı bir teknik bilgi seviyesi gerektiriyor, tam olarak neyi sevdiğinizi keşfetmeye başlamanızı ve kitapları, makaleleri ve diğerlerini yemeye başlamanızı ve en önemlisi, güncel olmasa bile okuduğunuz her şeyi pratik etmenizi tavsiye ederim. bu sonunda bir fark yaratacak.
Saygılarımızla,
Merhaba.
Bu konuyu açıkladığınız ve ek bilgi için "Shellcoder'ın El Kitabı" na sahip olduğumuzu yorumladığınız için çok teşekkür ederiz. Zaten bekleyen bir okumam var 😉