Leaking libc address with ROP
Hızlı Özet
Taşma offset'ini bulun
POP_RDI
gadget'ını,PUTS_PLT
veMAIN
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'yi hesaplayın ve sömürün
Diğer eğitimler ve uygulama ikilileri
Bu eğitim, bu eğitimde önerilen kod/ikiliyi sömürecek: https://tasteofsecurity.com/security/ret2libc-unknown-libc/ Başka yararlı eğitimler: https://made0x78.com/bseries-ret2libc/, https://guyinatuxedo.github.io/08-bof_dynamic/csaw19_babyboi/index.html
Kod
Dosya adı: vuln.c
ROP - LIBC Adres Sızdırma Şablonu
Saldırıyı indirin ve zafiyetli ikili dosya ile aynı dizine yerleştirin ve betiğe gerekli verileri verin:
pageLeaking libc - template1- Ofset Bulma
Şablon, saldırıya devam etmeden önce bir ofsete ihtiyaç duyar. Herhangi bir ofset sağlanırsa, gerekli kodu bulmak için çalıştırılacaktır (varsayılan olarak OFFSET = ""
):
Çalıştır python template.py
komutunu, programın çöktüğü bir GDB konsolu açılacaktır. Bu GDB konsolu içinde x/wx $rsp
komutunu çalıştırarak RIP'yi üzerine yazacağınız baytları alın. Son olarak, bir python konsolu kullanarak ofset değerini alın:
Ofset'i bulduktan sonra (bu durumda 40) o değeri kullanarak şablon içindeki OFFSET değişkenini değiştirin.
OFFSET = "A" * 40
Başka bir yol ise şu şekilde olabilir: pattern create 1000
-- ret'e kadar çalıştır -- pattern search $rsp
GEF'ten.
2- Gadget'ları Bulma
Şimdi, binary içinde ROP gadget'ları bulmamız gerekiyor. Bu ROP gadget'ları, kullanılan libc'yi bulmak için puts'u çağırmak ve daha sonra son saldırıyı başlatmak için kullanışlı olacaktır.
PUTS_PLT
, puts fonksiyonunu çağırmak için gereklidir.
MAIN_PLT
, bir etkileşimden sonra tekrar ana fonksiyonu çağırmak için gereklidir, aşırı akışı tekrar sömürmek için (sonsuz sayıda sömürü turu). Her ROP'un sonunda programı tekrar çağırmak için kullanılır.
POP_RDI, çağrılan fonksiyona bir parametre geçirmek için gereklidir.
Bu adımda, her şeyin yürütme sırasında pwntools tarafından bulunacağından bir şey yürütmenize gerek yoktur.
3- Libc kütüphanesini bulma
Şimdi, kullanılan libc kütüphanesinin hangi sürümü olduğunu bulma zamanı geldi. Bunu yapmak için hafızadaki puts fonksiyonunun adresini sızdıracağız ve ardından bu adreste hangi kütüphane sürümünün puts sürümünün olduğunu aramaya başlayacağız.
Bunu yapmak için, yürütülen kodun en önemli satırı:
Bu, RIP'yi üzerine yazma olasılığı olan bazı baytlar gönderecek: OFFSET
.
Daha sonra, POP_RDI
adlı gadget'ın adresini ayarlayacak, böylece bir sonraki adres (FUNC_GOT
) RDI kaydedilecek. Bu, puts'u çağırmak istediğimiz için PUTS_GOT
'un adresini RDI kaydediyoruz, çünkü bellekte puts fonksiyonunun adresi, PUTS_GOT
tarafından işaret edilen adreste kaydedilir.
Bundan sonra, PUTS_PLT
(içinde PUTS_GOT
olan RDI ile) çağrılacak, bu nedenle puts, PUTS_GOT
içindeki içeriği (bellekte puts fonksiyonunun adresi) okuyacak ve yazdıracak.
Son olarak, ana işlev tekrar çağrılır böylece taşmayı tekrar kullanabiliriz.
Bu şekilde, puts fonksiyonunu kandırdık ve bellekteki puts fonksiyonunun adresini (ki bu libc kütüphanesinin içindedir) yazdırmak için kullanıldı. Artık o adresi aldığımıza göre hangi libc sürümünün kullanıldığını arayabiliriz.
Bir yerel ikili dosyayı sömürdüğümüzden dolayı libc'nin hangi sürümünün kullanıldığını bulmamıza gerek yoktur (yalnızca /lib/x86_64-linux-gnu/libc.so.6
içinde kütüphaneyi bulun).
Ancak, uzaktan bir saldırı durumunda, nasıl bulabileceğinizi burada açıklayacağım:
3.1- Libc sürümünü arama (1)
Kullanılan kütüphaneyi arayabilirsiniz: https://libc.blukat.me/ Ayrıca, libc'nin keşfedilen sürümünü indirmenize izin verecektir
3.2- Libc sürümünü arama (2)
Ayrıca şunu yapabilirsiniz:
$ git clone https://github.com/niklasb/libc-database.git
$ cd libc-database
$ ./get
Bu biraz zaman alabilir, sabırlı olun. Bu çalışması için:
Libc sembol adı:
puts
Sızdırılan libc adresi:
0x7ff629878690
Muhtemelen kullanılan libc'yi anlayabiliriz.
İki eşleşme elde ediyoruz (ilk çalışmazsa ikinciyi denemelisiniz). İlkini indirin:
3.3- Sızıntı yapmak için diğer fonksiyonlar
libs/libc6_2.23-0ubuntu10_amd64/libc-2.23.so
dosyasından libc'yi çalışma dizinimize kopyalayın.
4- Libc adresini bulma ve sömürme
Bu noktada kullanılan libc kütüphanesini bilmemiz gerekmektedir. Bir yerel ikili dosyayı sömürdüğümüz için sadece şunu kullanacağım: /lib/x86_64-linux-gnu/libc.so.6
Bu yüzden, template.py
dosyasının başında libc değişkenini şu şekilde değiştirin: libc = ELF("/lib/x86_64-linux-gnu/libc.so.6") #Kütüphane yolunu bildiğinizde ayarlayın
Libc kütüphanesinin yolunu verdiğinizde, sömürge kalanı otomatik olarak hesaplanacaktır.
get_addr
fonksiyonu içinde libc'in taban adresi hesaplanacaktır:
Not: Son libc taban adresinin 00 ile bitmesi gerektiğini unutmayın. Aksi takdirde yanlış bir kütüphane sızdırmış olabilirsiniz.
Ardından, system
fonksiyonunun adresi ve "/bin/sh" dizesinin adresi, libc'in taban adresinden hesaplanacak ve verilen libc kütüphanesinde olacak.
Son olarak, /bin/sh yürütme açığı hazırlanıp gönderilecek:
Let's explain this final ROP.
Son ROP (rop1
) tekrar main fonksiyonunu çağırarak bitti, bu yüzden tekrar sömürülebiliriz taşma (bu yüzden OFFSET
burada tekrar). Daha sonra, POP_RDI
'yi "/bin/sh" adresine işaret edecek şekilde çağırmak istiyoruz (BINSH
) ve system fonksiyonunu (SYSTEM
) çağırmak çünkü "/bin/sh" adresi bir parametre olarak geçirilecek.
Son olarak, çıkış fonksiyonunun adresi çağrılır böylece işlem güzelce sonlanır ve herhangi bir uyarı oluşturulmaz.
Bu şekilde sömürü, bir _/bin/sh_** kabuğunu çalıştıracaktır.**
4(2)- ONE_GADGET Kullanımı
Ayrıca, system ve "/bin/sh" kullanmak yerine bir kabuk elde etmek için ONE_GADGET kullanabilirsiniz. ONE_GADGET, libc kütüphanesinde bir kabuk elde etmek için sadece bir ROP adresi kullanacak bir yol bulacaktır.
Ancak, genellikle bazı kısıtlamalar vardır, en yaygın olanları ve kolayca kaçınılabilecek olanlar [rsp+0x30] == NULL
gibi. RSP içindeki değerleri kontrol ettiğinizden, kısıtlamayı önlemek için birkaç daha fazla NULL değeri göndermeniz yeterlidir.
SIZDIRMA DOSYASI
Bu zafiyeti sömürmek için bir şablonu burada bulabilirsiniz:
pageLeaking libc - templateSık Karşılaşılan Sorunlar
MAIN_PLT = elf.symbols['main'] bulunamadı
Eğer "main" sembolü mevcut değilse. O zaman main kodunun nerede olduğunu bulabilirsiniz:
ve adresi manuel olarak ayarlayın:
Puts bulunamadı
Eğer ikili dosya Puts kullanmıyorsa, şunu kontrol etmelisiniz:
sh: 1: %s%s%s%s%s%s%s%s: not found
sh: 1: %s%s%s%s%s%s%s%s: not found
Bu hata mesajını tüm saldırıyı oluşturduktan sonra bulursanız: sh: 1: %s%s%s%s%s%s%s%s: not found
"/bin/sh" adresinden 64 bayt çıkarın:
<özet>
Sıfırdan kahraman olmaya kadar AWS hacklemeyi öğrenin htARTE (HackTricks AWS Red Team Expert)!</özet>
HackTricks'ı desteklemenin diğer yolları:
Şirketinizi HackTricks'te reklamını görmek istiyorsanız veya HackTricks'i PDF olarak indirmek istiyorsanız ABONELİK PLANLARI'na göz atın!
The PEASS Family'yi keşfedin, özel NFT'lerimiz koleksiyonumuz
Katılın 💬 Discord grubuna veya telegram grubuna veya bizi Twitter 🐦 @hacktricks_live'da takip edin.
Hacking püf noktalarınızı paylaşarak PR göndererek HackTricks](https://github.com/carlospolop/hacktricks) ve HackTricks Cloud github depolarına.
Last updated