Leaking libc address with ROP
Last updated
Last updated
AWS Hacking öğrenin ve pratik yapın:HackTricks Training AWS Red Team Expert (ARTE) GCP Hacking öğ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, bunu 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.
The 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 exploit edebiliriz (sonsuz exploit 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 hiçbir şey çalıştırmanıza gerek yoktur, çünkü her şey pwntools tarafından yürütme sırasında bulunacaktır.
Artık hangi sürümde libc kütüphanesinin kullanıldığını bulma zamanı. Bunu yapmak için, puts fonksiyonunun bellek adresini leak edeceğiz ve ardından bu adreste hangi kütüphane sürümü olduğ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 ve ona PUTS_GOT
'ın adresini geçmektir çünkü puts fonksiyonunun bellek içindeki 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 okuyacak (puts fonksiyonunun bellek içindeki adresi) ve yazdıracaktır.
Son olarak, ana fonksiyon tekrar çağrılır böylece taşmayı tekrar istismar edebiliriz.
Bu şekilde, puts fonksiyonunu belirli bir adresi yazdırması için kandırdık (bu adres libc kütüphanesinin içindedir). 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 bul).
Ancak, uzaktan bir istismar durumunda burada nasıl bulabileceğinizi 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 izin verecektir.
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, geri kalan istismar 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 ve gönderilecek:
Son ROP'u açıklayalım.
Son ROP (rop1
), ana fonksiyonu tekrar çağırarak sona erdi, bu yüzden yine istismar edebiliriz overflow (bu yüzden OFFSET
burada tekrar var). Ardından, "/bin/sh" (BINSH
) adresine işaret eden POP_RDI
'yi ç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 işlem 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 kaçınması kolay olanlar [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. O zaman 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)