Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Master of ROP:PWN Advanced
Search
YJK
June 13, 2025
0
8
Master of ROP:PWN Advanced
YJK
June 13, 2025
Tweet
Share
More Decks by YJK
See All by YJK
From 0 to Shell PWN Basic
yjk0805
0
6
Basic Reverse-逆要做什麼@THUHC
yjk0805
0
14
Reproducing Vulnerability in IoT@HackerSir StudyGroup
yjk0805
0
21
你 PWN 不動我@HackerSir 10th
yjk0805
0
11
Reverse 0x1@HackerSir 10th
yjk0805
0
13
Reverse 0x2@HackerSir 10th
yjk0805
0
9
不要亂 PWN 我@HackerSir 10th
yjk0805
0
14
Assembly@HackerSir 10th
yjk0805
0
11
Featured
See All Featured
Sharpening the Axe: The Primacy of Toolmaking
bcantrill
44
2.4k
Evolution of real-time – Irina Nazarova, EuRuKo, 2024
irinanazarova
8
800
Documentation Writing (for coders)
carmenintech
72
4.9k
Site-Speed That Sticks
csswizardry
10
670
The Web Performance Landscape in 2024 [PerfNow 2024]
tammyeverts
8
680
Chrome DevTools: State of the Union 2024 - Debugging React & Beyond
addyosmani
7
720
How to Think Like a Performance Engineer
csswizardry
24
1.7k
Building Better People: How to give real-time feedback that sticks.
wjessup
367
19k
Save Time (by Creating Custom Rails Generators)
garrettdimon
PRO
31
1.3k
Making Projects Easy
brettharned
116
6.3k
The World Runs on Bad Software
bkeepers
PRO
69
11k
A Modern Web Designer's Workflow
chriscoyier
694
190k
Transcript
Master of ROP:PWN Advanced YJK @ HackerSir
Whoami • YJK • 逢甲大學黑客社學術部長 • AIS3 Junior 2024 助教
• MyFirstCTF 2024 銅質獎 • 2022 & 2023 T 貓盃資安基礎實務能力競賽 佳作 • ICPC 2023 Taoyuan Regional High Honors • Pwn & Reverse & IoT Security & 演算法
Environment • ubuntu:22.04 • 可以自己架環境 • 內含 pwndbg、pwngdb、pwntools、常用工具... • environment
01 03 02 ROP ret2libc ret2plt Outline 04 Stack Pivoting
ROP 01 Basic ROP concept、static linked ROP
Demo • 編譯選項 ◦ gcc test.c -o dynamic ◦ gcc
test.c -o static -static
Demo • 編譯選項 ◦ gcc test.c -o dynamic ◦ gcc
test.c -o static -static • 觀察一下 ◦ file ◦ ls ◦ objdump ◦ gdb
file
ls
ASM
差異 • static 很大,dynamic 很小 • static linking 會將所有程式碼包進去 ◦
call 到任何外部 function 都會包進去 ▪ scanf、printf… • 浪費空間
ASM
Dynamic Linking • 一個程式會呼叫許多 library function • libc.so • .so、.dll
• 上週提到的 plt、got 就是如此 • 需要使用時再呼叫 libc • 可以重複利用,不浪費空間
ROP • ROP (Return Oriented Programming) • 重複利用編譯的程式碼繞過 NX •
透過多段可以執行的 gadget 串出 rop chain • 控制執行流程
ROP Gadgets • 片段可執行的程式 • 通常結尾為 ret 或是 jump <addr>
• 較常利用 ◦ 可以控制 register ◦ 可以寫入資料 ◦ syscall • 如何找到 gadget ◦ ROPgadget Tool
Control Register • pop rax; ret pop rax 0x3b ret
Control Register • rax = 0x3b pop rax 0x3b ret
Control Register • 繼續串 gadget pop rax 0x3b ret
ROP 原理 • Overflow 前 old rbp Return address
ROP 原理 • Overflow 並串成右方後 • 0x419afc:pop rax ; ret
• 0x40a48d:pop rsi ; ret • 0x402020:pop rdi ; ret AAAAAAAA 0x419afc (pop rax ; ret) 0x3b 0x40a48d (pop rsi ; ret) 0 0x402020 (pop rdi ; ret) 0 ……
ROP 原理 • 0x419afc:pop rax ; ret AAAAAAAA 0x419afc (pop
rax ; ret) 0x3b 0x40a48d (pop rsi ; ret) 0 0x402020 (pop rdi ; ret) 0 ……
ROP 原理 • 0x419afc:pop rax ; ret • rax =
0x3b AAAAAAAA 0x419afc (pop rax ; ret) 0x3b 0x40a48d (pop rsi ; ret) 0 0x402020 (pop rdi ; ret) 0 ……
ROP 原理 • 0x40a48d:pop rsi ; ret AAAAAAAA 0x419afc (pop
rax ; ret) 0x3b 0x40a48d (pop rsi ; ret) 0 0x402020 (pop rdi ; ret) 0 ……
ROP 原理 • 0x40a48d:pop rsi ; ret • rsi =
0 AAAAAAAA 0x419afc (pop rax ; ret) 0x3b 0x40a48d (pop rsi ; ret) 0 0x402020 (pop rdi ; ret) 0 ……
ROP 原理 • 0x402020:pop rdi ; ret AAAAAAAA 0x419afc (pop
rax ; ret) 0x3b 0x40a48d (pop rsi ; ret) 0 0x402020 (pop rdi ; ret) 0 ……
ROP 原理 • 0x402020:pop rdi ; ret • rdi =
0 AAAAAAAA 0x419afc (pop rax ; ret) 0x3b 0x40a48d (pop rsi ; ret) 0 0x402020 (pop rdi ; ret) 0 ……
ROP 原理 • 執行到最後 Register 會變成 • rax:0x3b • rsi:0
• rdi:0 AAAAAAAA 0x419afc (pop rax ; ret) 0x3b 0x40a48d (pop rsi ; ret) 0 0x402020 (pop rdi ; ret) 0 ……
ROP 原理 • 執行到最後 Register 會變成 • rax:0x3b • rsi:0
• rdi:0 • 串成可以成功 ROP 的樣子 AAAAAAAA 0x419afc (pop rax ; ret) 0x3b 0x40a48d (pop rsi ; ret) 0 0x402020 (pop rdi ; ret) 0 ……
Practice • rop
Static ROP • static linking binary • 先將 ROP Gadget
全部找出來存到檔案 ◦ ROPgadget --binary <binary> > gadget • 利用 grep 找到想要的 gadget ◦ cat gadget | grep "pop rdi"
Static ROP • 常用 ◦ pop <reg>;ret 控制 register ◦
mov qword ptr [reg], reg ; ret; 寫入 memory ◦ syscall
Static ROP • 目標:execve(“/bin/sh”, argv, envp) • Linux System Call
Table NR Syscall references %rax arg0 (%rdi) arg1 (%rsi) arg2 (%rdx) 59 execve man/cs/ 0x3b const char *filename const char *const *argv const char *const *envp
整理 • execve 的 argv、envp 可以放 NULL • 用 mov
qword ptr [reg], reg ; ret; 寫 “/bin/sh” ◦ 用 gdb 開 vmmap 找可寫區域
整理 • execve 的 argv、envp 可以放 NULL • 用 mov
qword ptr [reg], reg ; ret; 寫 “/bin/sh” ◦ 用 gdb 開 vmmap 找可寫區域 • 用 pop <reg> ; ret ; 調整 register • 最後 syscall
整理 • syscall number = rax = 0x3b • rdi
= &"/bin/sh" (pointer to string "/bin/sh") • rsi = 0 • rdx = 0
solution • Static linked、No PIE • 無腦 ROPgadget 直接找 •
理論上絕對會有適合的 gadget 可以用
偷吃步 • 利用 ROPgadget 生成 ROP chain • ROPgadget --binary
<file> --ropchain • 有機會長出很白癡的 ROP chain
ret2libc 02 Use glibc function to ROP、one_gadget
Change libc • Remote、Local 環境可能不同 • libc 和 linker version
影響 offset 程度較大 • 盡量讓 Local、Remote 環境一致 ◦ 換 libc、linker • 過去的題目可能不會給 libc ◦ libc database
沒給 libc 有給 Dockerfile • 把題目架起來 ◦ docker-compose up -d
沒給 libc 有給 Dockerfile • 把題目架起來 ◦ docker-compose up -d
◦ docker exec -it [ID] /bin/bash 開 shell
沒給 libc 有給 Dockerfile • 把題目架起來 ◦ docker-compose up -d
◦ docker exec -it [ID] /bin/bash 開 shell ◦ ldd [執行檔] 查看 libc、ld 路徑 ◦ docker cp [ID]:[路徑] .
沒給 libc 有給 Dockerfile • 注意檔案有沒有 link 到其他地方
patchelf • 可以自己編 Debug Symbol ◦ https://hackmd.io/@u1f383/S1CNu-1SO • 將 ld
跟 libc patch 到執行檔 • dynamic linking 會 link 到指定 ld / libc • https://github.com/NixOS/patchelf • patchelf --replace-needed libc.so.6 ./[libc] --set-interpreter ./[ld] ./[執行檔]
確認狀態 • gdb ./[執行檔] • 跑起來看 vmmap 路徑、ldd 確認
return to libc • 透過 libc 裡面的 gadgets、現存 function •
execve("/bin/sh", argv, envp)? ◦ system("/bin/sh")
return to libc • system("/bin/sh") ◦ pop rdi ; ret
◦ &"/bin/sh" (pointer to string "/bin/sh") ◦ system • &"/bin/sh"? ◦ 正好 libc 裡面也有 ◦ strings -a -t x <path to libc> | grep /bin/sh
return to libc • 優點 ◦ 比手動做 syscall 簡單很多 ◦
gadgets 數量少很多 • 缺點 ◦ 有 ASLR -> 需要 leak libc base
Practice • ret2libc
solution • 可以隨意輸入、讀取任意 index 的內容 ◦ Out of bound (OOB)
read、write ◦ 可以 leak libc base 或各種資訊 ◦ gdb 看會是哪個 index 可能有所需內容 ◦ 不斷輸入不同 index 看有沒有 libc address ◦ 減去 offset • system("/bin/sh") • SIGSEGV????
One gadget • ret2libc 疊出 system("/bin/sh") 還是太長?
One gadget • rbp useless? No ◦ one gadget 和
stack pivoting 會用到 • 使 gadgets 的長度最短 • 只需控制 rbp 和 return address • one_gadget • david942j - 一發入魂 One Gadget RCE
One gadget • libc 有呼叫 execve("/bin/sh", argv, envp) 片段 •
可以開啟 shell • system(cmd) ◦ fork() + execve("/bin/sh", ["sh","-c",cmd], environ) ◦ 跳到 execve("/bin/sh", ["sh","-c",cmd], environ)
Usage • one_gadget ./libc.so.6
Practice • ret2libc_adv
solution • 可以 overflow 的部分空間變小,其餘相同 • 能 overflow 的部分只到 rbp
跟 return address ◦ oob to leak libc base ◦ 選好 rbp ◦ return address -> one_gadget
ret2plt 03 Use plt、got leak libc base and ROP
ret2plt • 沒有足夠的 gadgets 使用 • 無法 leak libc •
無解????
ret2plt • 看一下 write(1, "string", 7) pop rdi 0x1 pop
rsi ["string"] pop rdx 0x7 pop rax 0x1 syscall
ret2plt • 看一下 write(1, "string", 7) • puts("string") pop rdi
["string"] puts@plt
ret2plt • 看一下 write(1, "string", 7) • puts("string") • 都可以輸出字串
pop rdi ["string"] puts@plt
ret2plt • 看一下 write(1, "string", 7) • puts("string") • 都可以輸出字串
• system("/bin/sh") pop rdi ["/bin/sh"] system@plt
Practice • ret2plt
solution • 有 system@plt、gets • 沒有 Canary 和 PIE •
pop rdi、gets@plt 將 /bin/sh 寫到 BSS • 再用 pop rdi 將 BSS 的資料傳給 system@plt
plt to libc • GOT 如果解析完會有 library function address •
如果用 GOT 當參數傳給輸出 function (printf、puts) • puts(got_address) • 成功拿到某個 function 在 libc 的 address • 需要減掉 offset,才會是 base address
Practice • ret2plt_adv
solution • 有 read 的 overflow,可以 control flow • 動態鏈結
-> gadgets 不夠 -> 用 libc -> leak libc • 沒有 format string bug、OOB • 有 puts -> ret2plt leak libc
stack pivoting 04 A trick to control flow
stack pivoting • 沒有足夠的長度或方法 leak libc、堆 ROP chain • 沒辦法
PWN???
stack pivoting • 沒有足夠的長度或方法 leak libc、堆 ROP chain • 沒辦法
PWN??? • stack pivoting (Stack Migration)
stack pivoting • 分次將 ROP chain 寫在指定區域 • 將 stack
移過去執行 • Stack 由 rsp 控制 -> 控制 rsp ◦ leave ; ret ◦ leave -> mov rsp , rbp ; pop rbp ; ◦ ret -> pop rip; • 把 return address 蓋成 leave; ret;
Demo • rbp 是 0x7ffe65dea290、rsp 是 0x7ffe65dea280
Demo • rbp 是 0x7ffe65dea290、rsp 是 0x7ffe65dea280 • leave 後,rbp
換成 save rbp、rsp 變 rbp + 0x8
Demo • rbp 是 0x7ffe65dea290、rsp 是 0x7ffe65dea280 • leave 後,rbp
換成 save rbp、rsp 變 rbp + 0x8 • 再 leave 一次,rsp 就會再改變
Practice • stack_pivoting
solution • 有全域變數 name 可以寫入內容 • 有 message 可以輸入並存在 buffer
overflow • 編譯參數使用了 –static 有很多 gadgets • 不能直接透過 return address 堆 ROP • 將 ROP chain 寫在 name,利用 stack pivoting ROP
問題 • 如果沒有足夠空間可以堆 ROP 呢?
問題 • 如果沒有足夠空間可以堆 ROP 呢? • 只要有其中一塊可以堆 gadgets • 直接透過不斷的
stack pivoting 製造出來
Reference • NTU Computer Security Fall 2019 • NCKUCTF (成大資安社)
• frozenkp-Stack Migration
None