Leaking libc address with ROP
Last updated
Last updated
AWS Hacking'i öğrenin ve pratik yapın:HackTricks Training AWS Red Team Expert (ARTE) GCP Hacking'i öğrenin ve pratik yapın: HackTricks Training GCP Red Team Expert (GRTE)
Taşma offset'ini bulun
POP_RDI
gadget'ını, PUTS_PLT
ve MAIN
gadget'larını bulun
Önceki gadget'ları kullanarak puts veya başka bir libc fonksiyonunun bellek adresini sızdırın ve libc sürümünü bulun (indirin)
Kütüphane ile, ROP'u hesaplayın ve istismar edin
Bu eğitim, bu eğitimde önerilen kod/ikili dosyayı istismar edecek: https://tasteofsecurity.com/security/ret2libc-unknown-libc/ Diğer yararlı eğitimler: https://made0x78.com/bseries-ret2libc/, https://guyinatuxedo.github.io/08-bof_dynamic/csaw19_babyboi/index.html
Dosya adı: vuln.c
Exploit'i indirin ve onu savunmasız ikili dosya ile aynı dizine yerleştirin ve script'e gerekli verileri verin:
Leaking libc - templateŞablon, exploit'e devam etmeden önce bir ofsete ihtiyaç duyar. Herhangi bir ofset sağlanırsa, onu bulmak için gerekli kodu çalıştıracaktır (varsayılan olarak OFFSET = ""
):
Çalıştır python template.py
bir GDB konsolu açılacak ve program çökertilecektir. O GDB konsolu içinde x/wx $rsp
komutunu çalıştırarak RIP'i geçecek olan baytları al. Son olarak, bir python konsolu kullanarak offset'i al:
Offset'u bulduktan sonra (bu durumda 40), bu değeri kullanarak şablon içindeki OFFSET değişkenini değiştirin.
OFFSET = "A" * 40
Başka bir yol ise: pattern create 1000
-- ret'e kadar çalıştır -- pattern seach $rsp
komutunu GEF'den kullanmaktır.
Artık ikili dosya içinde ROP gadget'larını bulmamız gerekiyor. Bu ROP gadget'ları, kullanılan libc'yi bulmak için puts
çağırmak ve daha sonra son istismarı başlatmak için faydalı olacaktır.
PUTS_PLT
, puts fonksiyonunu çağırmak için gereklidir.
MAIN_PLT
, bir etkileşimden sonra main function'ı tekrar çağırmak için gereklidir, böylece taşmayı tekrar istismar edebiliriz (sonsuz istismar turları). Her ROP'un sonunda programı tekrar çağırmak için kullanılır.
POP_RDI, çağrılan fonksiyona bir parametre geçmek için gereklidir.
Bu adımda, pwntools'un yürütme sırasında her şeyi bulacağı için hiçbir şey çalıştırmanıza gerek yok.
Artık hangi sürümde libc kütüphanesinin kullanıldığını bulma zamanı. Bunu yapmak için, puts fonksiyonunun bellek adresini sızdıracağız ve ardından bu adreste hangi kütüphane sürümü içinde puts sürümünün bulunduğunu arama yapacağız.
Bunu yapmak için, yürütülen kodun en önemli satırı şudur:
Bu, bazı baytları RIP'i aşındırmak mümkün olana kadar gönderecektir: OFFSET
.
Sonra, POP_RDI
gadget'ının adresini ayarlayacak, böylece bir sonraki adres (FUNC_GOT
) RDI kaydında saklanacaktır. Bunun nedeni, puts'u çağırmak istememizdir; PUTS_GOT'ın adresini geçirerek, puts fonksiyonunun bellek adresi PUTS_GOT
tarafından işaret edilen adreste saklanmaktadır.
Bundan sonra, PUTS_PLT
çağrılacak (içinde RDI'de PUTS_GOT
ile) böylece puts, PUTS_GOT
içindeki içeriği (puts fonksiyonunun bellek adresi) okuyacak ve yazdıracaktır.
Son olarak, ana fonksiyon tekrar çağrılır böylece taşmayı tekrar istismar edebiliriz.
Bu şekilde, puts fonksiyonunu aldatmayı başardık ve puts fonksiyonunun bellekteki adresini (ki bu libc kütüphanesinin içindedir) yazdırdık. Artık bu adrese sahip olduğumuza göre, hangi libc sürümünün kullanıldığını arayabiliriz.
Yerel bir ikiliyi istismar ettiğimiz için, hangi libc sürümünün kullanıldığını bulmamıza gerek yoktur (sadece /lib/x86_64-linux-gnu/libc.so.6
içindeki kütüphaneyi bulmanız yeterlidir).
Ancak, uzaktan bir istismar durumunda, bunu nasıl bulabileceğinizi burada açıklayacağım:
Hangi kütüphanenin kullanıldığını web sayfasında arayabilirsiniz: https://libc.blukat.me/ Ayrıca, keşfedilen libc sürümünü indirmenize de olanak tanır.
Ayrıca şunları yapabilirsiniz:
$ git clone https://github.com/niklasb/libc-database.git
$ cd libc-database
$ ./get
Bu biraz zaman alacaktır, sabırlı olun. Bunun çalışması için şunlara ihtiyacımız var:
Libc sembol adı: puts
Sızdırılan libc adresi: 0x7ff629878690
Hangi libc'nin muhtemelen kullanıldığını belirleyebiliriz.
İki eşleşme alıyoruz (ilk çalışmıyorsa ikinciyi denemelisiniz). İlkini indirin:
libs/libc6_2.23-0ubuntu10_amd64/libc-2.23.so
dosyasını çalışma dizinimize kopyalayın.
Bu noktada kullanılan libc kütüphanesini bilmemiz gerekiyor. Yerel bir ikiliyi istismar ettiğimiz için sadece şunu kullanacağım: /lib/x86_64-linux-gnu/libc.so.6
Bu nedenle, template.py
dosyasının başında libc değişkenini şuna değiştirin: libc = ELF("/lib/x86_64-linux-gnu/libc.so.6") #Kütüphane yolunu bildiğinizde ayarlayın
libc kütüphanesine yolu vererek, istismarın geri kalanı otomatik olarak hesaplanacaktır.
get_addr
fonksiyonu içinde libc'nin temel adresi hesaplanacaktır:
Not edin ki son libc temel adresi 00 ile bitmelidir. Eğer durumunuz böyle değilse, yanlış bir kütüphane sızdırmış olabilirsiniz.
Daha sonra, system
fonksiyonunun adresi ve adres "/bin/sh" dizesi libc'nin temel adresinden hesaplanacak ve libc kütüphanesi verilecektir.
Sonunda, /bin/sh yürütme istismarı hazırlanacak.
Let's explain this final ROP.
Son ROP (rop1
), ana fonksiyonu tekrar çağırarak sona erdi, bu yüzden yine istismar edebiliriz overflow (bu yüzden OFFSET
burada tekrar var). Sonra, "/bin/sh" (BINSH
) adresine işaret eden POP_RDI
çağırmak istiyoruz ve system fonksiyonunu (SYSTEM
) çağırmak istiyoruz çünkü "/bin/sh" adresi bir parametre olarak geçecektir.
Son olarak, çıkış fonksiyonunun adresi çağrılır böylece süreç güzel bir şekilde çıkar ve herhangi bir uyarı üretilmez.
Bu şekilde istismar bir _/bin/sh_** shell'i çalıştıracaktır.**
Ayrıca, system ve "/bin/sh" kullanmak yerine bir shell elde etmek için ONE_GADGET kullanabilirsiniz. ONE_GADGET, libc kütüphanesi içinde sadece bir ROP adresi kullanarak bir shell elde etmenin bir yolunu bulacaktır.
Ancak, genellikle bazı kısıtlamalar vardır, en yaygın ve kolayca aşılabilenler [rsp+0x30] == NULL
gibidir. RSP içindeki değerleri kontrol ettiğiniz için, kısıtlamanın aşılması için sadece biraz daha NULL değeri göndermeniz yeterlidir.
Bu güvenlik açığını istismar etmek için bir şablonu burada bulabilirsiniz:
Leaking libc - templateEğer "main" sembolü yoksa, ana kodun nerede olduğunu bulabilirsiniz:
ve adresi manuel olarak ayarlayın:
Eğer ikili dosya Puts kullanmıyorsa, bunun yerine kullanıp kullanmadığını kontrol etmelisiniz.
sh: 1: %s%s%s%s%s%s%s%s: bulunamadı
Eğer tüm istismarı oluşturduktan sonra bu hata ile karşılaşırsanız: sh: 1: %s%s%s%s%s%s%s%s: bulunamadı
"/bin/sh" adresinden 64 byte çıkarmayı deneyin:
AWS Hacking'i öğrenin ve pratik yapın:HackTricks Eğitim AWS Kırmızı Takım Uzmanı (ARTE) GCP Hacking'i öğrenin ve pratik yapın: HackTricks Eğitim GCP Kırmızı Takım Uzmanı (GRTE)