ROP - Return Oriented Programing
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)
Return-Oriented Programming (ROP), No-Execute (NX) veya Data Execution Prevention (DEP) gibi güvenlik önlemlerini aşmak için kullanılan ileri düzey bir istismar tekniğidir. Bir saldırgan, shellcode enjekte etmek ve çalıştırmak yerine, ikili dosyada veya yüklenmiş kütüphanelerde zaten mevcut olan kod parçalarını, yani "gadgets"'ı kullanır. Her gadget genellikle bir ret
talimatı ile biter ve verileri registerlar arasında taşımak veya aritmetik işlemler yapmak gibi küçük bir işlem gerçekleştirir. Bu gadget'ları bir araya getirerek, bir saldırgan keyfi işlemler gerçekleştirmek için bir yük oluşturabilir ve böylece NX/DEP korumalarını etkili bir şekilde aşabilir.
Kontrol Akışını Ele Geçirme: İlk olarak, bir saldırgan bir programın kontrol akışını ele geçirmelidir, genellikle bir buffer overflow kullanarak stack'teki kaydedilmiş dönüş adresini yazmak suretiyle.
Gadget Zincirleme: Saldırgan daha sonra istenen eylemleri gerçekleştirmek için gadget'ları dikkatlice seçer ve zincirler. Bu, bir fonksiyon çağrısı için argümanları ayarlamayı, fonksiyonu çağırmayı (örneğin, system("/bin/sh")
) ve gerekli temizlik veya ek işlemleri yönetmeyi içerebilir.
Yükün Çalıştırılması: Zayıf fonksiyon döndüğünde, meşru bir konuma dönmek yerine gadget zincirini çalıştırmaya başlar.
Genellikle, gadget'lar ROPgadget, ropper veya doğrudan pwntools (ROP) kullanılarak bulunabilir.
cdecl: Çağrıcı stack'i temizler. Fonksiyon argümanları stack'e ters sırayla (sağdan sola) itilir. Argümanlar stack'e sağdan sola itilir.
stdcall: cdecl'e benzer, ancak çağrılan fonksiyon stack'i temizlemekten sorumludur.
Öncelikle, ikili dosya veya yüklenmiş kütüphaneler içinde gerekli gadget'ları tanımladığımızı varsayalım. İlgilendiğimiz gadget'lar şunlardır:
pop eax; ret
: Bu gadget, stack'in en üstündeki değeri EAX
register'ına alır ve ardından döner, böylece EAX
'ı kontrol etmemizi sağlar.
pop ebx; ret
: Yukarıdaki gibi, ancak EBX
register'ı için, EBX
üzerinde kontrol sağlar.
mov [ebx], eax; ret
: EAX
'taki değeri EBX
tarafından işaret edilen bellek konumuna taşır ve ardından döner. Bu genellikle write-what-where gadget olarak adlandırılır.
Ayrıca, system()
fonksiyonunun adresine de sahibiz.
pwntools kullanarak, system('/bin/sh')
'yi çalıştırmayı hedefleyerek ROP zinciri yürütmesi için stack'i aşağıdaki gibi hazırlarız, zincirin nasıl başladığına dikkat edin:
Hizalama amaçlı bir ret
talimatı (isteğe bağlı)
system
fonksiyonunun adresi (ASLR'nin devre dışı bırakıldığını ve libc'nin bilindiğini varsayarak, daha fazla bilgi için Ret2lib)
system()
'den dönüş adresi için yer tutucu
"/bin/sh"
dizesinin adresi (system fonksiyonu için parametre)
Unix benzeri sistemlerde System V AMD64 ABI çağrı konvansiyonunu kullanır; burada ilk altı tam sayı veya işaretçi argümanı RDI
, RSI
, RDX
, RCX
, R8
ve R9
kayıtlarında iletilir. Ek argümanlar yığında iletilir. Dönüş değeri RAX
'a yerleştirilir.
Windows x64 çağrı konvansiyonu, ilk dört tam sayı veya işaretçi argümanı için RCX
, RDX
, R8
ve R9
kullanır; ek argümanlar yığında iletilir. Dönüş değeri RAX
'a yerleştirilir.
Kayıtlar: 64-bit kayıtlar RAX
, RBX
, RCX
, RDX
, RSI
, RDI
, RBP
, RSP
ve R8
'den R15
'e kadar içerir.
Amacımız için, RDI kaydını ayarlamamıza ( system() fonksiyonuna "/bin/sh" dizesini argüman olarak iletmek için) ve ardından system() fonksiyonunu çağırmamıza olanak tanıyacak gadget'lara odaklanalım. Aşağıdaki gadget'ları belirlediğimizi varsayıyoruz:
pop rdi; ret: Yığının en üstündeki değeri RDI'ye alır ve ardından döner. system() için argümanımızı ayarlamak için gereklidir.
ret: Basit bir dönüş, bazı senaryolar için yığın hizalaması için faydalıdır.
Ve system() fonksiyonunun adresini bildiğimizi biliyoruz.
Aşağıda, pwntools kullanarak x64 üzerinde system('/bin/sh') çalıştırmayı hedefleyen bir ROP zinciri kurma ve yürütme örneği bulunmaktadır:
In this example:
RDI
'yi "/bin/sh"
adresine ayarlamak için pop rdi; ret
gadget'ını kullanıyoruz.
RDI
'yi ayarladıktan sonra, zincirde system() adresi ile doğrudan system()
'e atlıyoruz.
Hedef ortamın gerektirmesi durumunda hizalama için ret_gadget
kullanılır; bu, işlevleri çağırmadan önce doğru yığın hizalamasını sağlamak için x64'te daha yaygındır.
x86-64 ABI bir call instruction yürütüldüğünde yığının 16-byte hizalı olmasını garanti eder. LIBC, performansı optimize etmek için SSE instructions (örneğin movaps) kullanır ve bu hizalamayı gerektirir. Yığın düzgün hizalanmadığında (yani RSP 16'nın katı değilse), ROP chain içinde system gibi işlevlere yapılan çağrılar başarısız olur. Bunu düzeltmek için, ROP chain'inizde system'i çağırmadan önce basitçe bir ret gadget ekleyin.
x64 ilk birkaç argüman için register'ları kullandığı için, genellikle basit işlev çağrıları için x86'dan daha az gadget gerektirir, ancak doğru gadget'ları bulmak ve zincirlemek, artan register sayısı ve daha büyük adres alanı nedeniyle daha karmaşık olabilir. x64 mimarisindeki artan register sayısı ve daha büyük adres alanı, özellikle Return-Oriented Programming (ROP) bağlamında istismar geliştirme için hem fırsatlar hem de zorluklar sunar.
Bu bilgi için aşağıdaki sayfayı kontrol edin:
Stack Canaries: Bir BOF durumunda, ROP zincirini kötüye kullanmak için dönüş işaretçilerini yazmak için yığın kanaryasını atlatmak gerekir.
Gadget Eksikliği: Yeterli gadget yoksa bir ROP zinciri oluşturmak mümkün olmayacaktır.
ROP'un, keyfi kodu yürütmek için sadece bir teknik olduğunu unutmayın. ROP'a dayalı olarak birçok Ret2XXX tekniği geliştirilmiştir:
Ret2lib: Keyfi parametrelerle yüklü bir kütüphaneden keyfi işlevleri çağırmak için ROP kullanın (genellikle system('/bin/sh')
gibi bir şey).
Ret2Syscall: ROP kullanarak bir syscall'a, örneğin execve
, çağrı hazırlamak ve keyfi komutlar yürütmek için kullanın.
EBP2Ret & EBP Zincirleme: İlki akışı kontrol etmek için EIP yerine EBP'yi kötüye kullanacak ve ikincisi Ret2lib'e benzer ancak bu durumda akış esas olarak EBP adresleri ile kontrol edilir (ancak EIP'yi kontrol etmek de gereklidir).
64 bit, Pie ve nx etkin, kanaryasız, yalnızca bir vsyscall
adresi ile RIP'i yazmak amacıyla yığındaki bir sonraki adrese geri dönmek için adresin bir kısmını sızdıran işlevin parçasını almak için kısmi bir yazma
arm64, ASLR yok, yığını çalıştırılabilir hale getirmek ve yığında shellcode'a atlamak için ROP gadget
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)