SlideShare a Scribd company logo
Linux Binary Exploitation
Stack base buffer overflow

angelboy@chroot.org
Outline
• Buffer Overflow

• Return to Text / Shellcode

• Protection

• Lazy binding

• Return to Library
Outline
• Buffer Overflow

• Return to Text / Shellcode

• Protection

• Lazy binding

• Return to Library
Buffer Overflow
• 程式設計師未對 buffer 做長度檢查,造成可以讓攻擊者輸入過長的字串串,覆
蓋記憶體上的其他資料,嚴重時更更可控制程式流程

• 依照 buffer 位置可分為

• stack base 

• ⼜又稱為 stack smashing

• data base 

• heap base
Buffer Overflow
Buffer Overflow
• Vulnerable Function

• gets

• scanf

• strcpy

• sprintf

• memcpy

• strcat

• …
• memory layout
Stack Overflow
return address
rbp
rbp/rsp
char buf[0x20]
read(0,buf,100)
leave
ret
high
low
• memory layout
Stack Overflow
return address
rbp
rbp/rsp
char buf[0x20]
read(0,buf,100)
leave
ret
high
low
• memory layout
Stack Overflow
return address
rbp
rbp
char buf[0x20]
read(0,buf,100)
leave
ret
high
low
rsp
buf[0x20]
• memory layout
Stack Overflow
aaaaaaaa
aaaaaaaa
aaaaaaaa
aaaaaaaa
aaaaaaaa (ret)
aaaaaaaa (rbp)
rbp
char buf[0x20]
read(0,buf,100)
leave
ret
high
low
rsp
buf[0x20]
• memory layout
Stack Overflow
aaaaaaaa
aaaaaaaa
aaaaaaaa
aaaaaaaa
aaaaaaaa (ret)
aaaaaaaa (rbp)
rbpchar buf[0x20]
read(0,buf,100)
mov rsp,rbp
pop rbp
ret
high
low
rsp
buf[0x20]
• memory layout
Stack Overflow
aaaaaaaa
aaaaaaaa
aaaaaaaa
aaaaaaaa
aaaaaaaa (ret)
aaaaaaaa (rbp)
rbp/rspchar buf[0x20]
read(0,buf,100)
mov rsp,rbp
pop rbp
ret
high
low
buf[0x20]
• memory layout
Stack Overflow
aaaaaaaa
aaaaaaaa
aaaaaaaa
aaaaaaaa
aaaaaaaa (ret)
aaaaaaaa (rbp)
rsp
char buf[0x20]
read(0,buf,100)
mov rsp,rbp
pop rbp
ret
high
low
buf[0x20]
• memory layout
Stack Overflow
aaaaaaaa
aaaaaaaa
aaaaaaaa
aaaaaaaa
aaaaaaaa (ret)
aaaaaaaa (rbp)
rspchar buf[0x20]
read(0,buf,100)
mov rsp,rbp
pop rbp
ret
high
low
buf[0x20]RIP = 0x6161616161616161
Stack Overflow
• 驗證
Stack Overflow
• 使⽤用 gdb 觀察
Stack Overflow
• From crash to exploit

• 隨意任意輸入⼀一堆資料應該只能造成 crash

• 需適當的構造資料,就可巧妙的控制程式流程

• EX : 

• 適當得構造 return address 就可在函數返回時,跳到攻擊者的程式碼
Stack Overflow
• From crash to exploit

• Overwrite the the return address

• 因 x86 底下是 little-endian 的,所以填入 address 時,需要反過來來填入

• e.g. 

• 假設要填入 0x00400646 就需要填入
x46x06x40x00x00x00x00x000

• p64(0x400646) # in pwntools
Outline
• Buffer Overflow

• Return to Text / Shellcode

• Protection

• Lazy binding

• Return to Library
Return to Text
• 控制 eip 後跳到原本程式中的程式碼

• 以 bofeasy 範例例來來說,我們可以跳到 l33t 這個 function

• 可以 objdump 來來找尋函式真正位置
Return to Text
Return to Text
• Exploitation

• Locate the return address

• 可⽤用 aaaaaaaabbbbbbbb…… 八個⼀一組的字來來定位 return address

• pwntool cyclic

• gdb-peda pattc
Return to Text
• Exploitation

• Write exploit

• echo -ne
“aaaaaaaabbbbbbbbccccccccddddddddeeeeeeex46x60x40x00x
00x00x00x00” > exp

• cat exp - | ./bofeasy
Return to Text
• Exploitation

• Write exploit
Return to Text
• Exploitation

• Debug exploit

• gdb$ r < exp
Return to Text
• Exploitation

• Debug exploit

• Use attach more would be easier
Return to Shellcode
• 如果在 data 段上是可執⾏行行且位置固定的話,我們也可以先在 data 段上塞入
shellcode 跳過去
Outline
• Buffer Overflow

• Return to Text / Shellcode

• Protection

• Lazy binding

• Return to Library
Protection
• ASLR

• DEP

• PIE

• StackGuard
Protection
• ASLR

• 記憶體位置隨機變化

• 每次執⾏行行程式時,stack 、heap、library 位置都不⼀一樣

• 查看是否有開啟 ASLR

• cat /proc/sys/kernel/randomize_va_space
Protection
• ASLR
kernel space
CODE VMA
DATA VMA
HEAP
STACK
Library
kernel space
CODE VMA
DATA VMA
HEAP
STACK
Library
kernel space
CODE VMA
DATA VMA
HEAP
STACK
Library
Protection
• ASLR

• 使⽤用 ldd (可看執⾏行行時載入的 library 及其位置) 觀察 address 變化
Protection
• DEP

• ⼜又稱 NX

• 可寫的不可執⾏行行,可執⾏行行的不可寫
Protection
Protection
• PIE ( Position Independent Execution )

• gcc 在預設情況下不會開啟,編譯時加上 -fPIC -pie 就可以開啟

• 在沒開啟的情況下程式的 data 段及 code 段會是固定的

• ⼀一但開啟之後 data 及 code 也會跟著 ASLR ,因此前⾯面說的 ret2text/
shellcode 沒有固定位置可以跳,就變得困難許多
• objdump 觀察 pie 開啟的 binary

• code address 變成只剩下 offset 執⾏行行後會加上 code base 才是真正在記
憶體中的位置
Protection
Protection
• StackGuard

• 在程式執⾏行行是隨機⽣生成⼀一亂數 function call 時會塞入 stack 中,在
function return 時會檢查是否該值有被更更動,⼀一旦發現被更更動就結束該程
式

• 該值⼜又稱 canary

• 非常有效地阻擋了了 stack overflow 的攻擊

• ⽬目前預設情況下是開啟的
Protection
• StackGuard

• canary 的值在執⾏行行期間都會先放在,⼀一個稱為 tls 的區段中的 tcbhead_t
結構中,⽽而在 x86/x64 架構下恆有⼀一個暫存器指向 tls 段的 tcbhead_t 結
構

• x86 : gs

• x64 : fs

• 因此程式在取 canary 值時都會直接以 fs/gs 做存取
Protection
• StackGuard
return address
rsp
push rbp
mov rbp,rsp
sub rsp, 0x40
mov [rbp-0x8],fs:0x28
…
mov rax,[rbp-0x8]
cmp rax,fs:0x28
jne stack_check_fail
leave
ret
fs:0x28
High
lowcanary
Protection
• StackGuard
…
return address
rbp
rsp
push rbp
mov rbp,rsp
sub rsp, 0x40
mov [rbp-0x8],fs:0x28
…
mov rax,[rbp-0x8]
cmp rax,fs:0x28
jne stack_check_fail
leave
ret
rbp
High
lowfs:0x28 canary
Protection
• StackGuard
…
return address
rbp
rsp
push rbp
mov rbp,rsp
sub rsp, 0x40
mov [rbp-0x8],fs:0x28
…
mov rax,[rbp-0x8]
cmp rax,fs:0x28
jne stack_check_fail
leave
ret
rbp
High
low
canary
fs:0x28 canary
Protection
• StackGuard
…
return address
rbp
rsp
push rbp
mov rbp,rsp
sub rsp, 0x40
mov [rbp-0x8],fs:0x28
…
mov rax,[rbp-0x8]
cmp rax,fs:0x28
jne stack_check_fail
leave
ret
rbp
High
low
canary
fs:0x28 canary
Protection
• StackGuard
…
return address
rbp
rsp
push rbp
mov rbp,rsp
sub rsp, 0x40
mov [rbp-0x8],fs:0x28
…
mov rax,[rbp-0x8]
cmp rax,fs:0x28
jne stack_check_fail
leave
ret
rbp
High
low
canary
fs:0x28 canary rax canary
Protection
• StackGuard
…
return address
rbp
rsp
push rbp
mov rbp,rsp
sub rsp, 0x40
mov [rbp-0x8],fs:0x28
…
mov rax,[rbp-0x8]
cmp rax,fs:0x28
jne stack_check_fail
leave
ret
rbp
High
low
canary
fs:0x28 canary rax canary
Protection
• StackGuard
…
return address
rbp
rsp
push rbp
mov rbp,rsp
sub rsp, 0x40
mov [rbp-0x8],fs:0x28
…
mov rax,[rbp-0x8]
cmp rax,fs:0x28
jne stack_check_fail
leave
ret
rbp
High
low
canary
fs:0x28 canary rax canary
Protection
• StackGuard - overflow
…
return address
rbp
rsp
push rbp
mov rbp,rsp
sub rsp, 0x40
mov [rbp-0x8],fs:0x28
…
mov rax,[rbp-0x8]
cmp rax,fs:0x28
jne stack_check_fail
leave
ret
rbp
High
low
canary
fs:0x28 canary
Protection
• StackGuard - overflow
aaaaaaaa
aaaaaaaa
aaaaaaaa
aaaaaaaa
aaaaaaaa
aaaaaaaa
aaaaaaaa
aaaaaaaa
rsp
push rbp
mov rbp,rsp
sub rsp, 0x40
mov [rbp-0x8],fs:0x28
…
mov rax,[rbp-0x8]
cmp rax,fs:0x28
jne stack_check_fail
leave
ret
rbp
High
low
aaaaaaaa
fs:0x28 canary
Protection
• StackGuard - overflow
aaaaaaaa
aaaaaaaa
aaaaaaaa
aaaaaaaa
aaaaaaaa
aaaaaaaa
aaaaaaaa
aaaaaaaa
rsp
push rbp
mov rbp,rsp
sub rsp, 0x40
mov [rbp-0x8],fs:0x28
…
mov rax,[rbp-0x8]
cmp rax,fs:0x28
jne stack_check_fail
leave
ret
rbp
High
low
aaaaaaaa
fs:0x28 canary rax aaaaaaaa
Protection
• StackGuard - overflow
aaaaaaaa
aaaaaaaa
aaaaaaaa
aaaaaaaa
aaaaaaaa
aaaaaaaa
aaaaaaaa
aaaaaaaa
rsp
push rbp
mov rbp,rsp
sub rsp, 0x40
mov [rbp-0x8],fs:0x28
…
mov rax,[rbp-0x8]
cmp rax,fs:0x28
jne stack_check_fail
leave
ret
rbp
High
low
aaaaaaaa
fs:0x28 canary rax aaaaaaaa
Protection
• StackGuard - overflow
aaaaaaaa
aaaaaaaa
aaaaaaaa
aaaaaaaa
aaaaaaaa
aaaaaaaa
aaaaaaaa
aaaaaaaa
rsp
push rbp
mov rbp,rsp
sub rsp, 0x40
mov [rbp-0x8],fs:0x28
…
mov rax,[rbp-0x8]
cmp rax,fs:0x28
jne stack_check_fail
leave
ret
rbp
High
low
aaaaaaaa
fs:0x28 canary rax aaaaaaaa
Abort !
Protection
• StackGuard
Outline
• Buffer Overflow

• Return to Text / Shellcode

• Protection

• Lazy binding

• Return to Library
Lazy binding
• Dynamic linking 的程式在執⾏行行過程中,有些 library 的函式可能到結束都不
會執⾏行行到

• 所以 ELF 採取 Lazy binding 的機制,在第⼀一次 call library 函式時,才會去
尋找函式真正的位置進⾏行行 binding
Global Offset Table
• library 的位置再載入後才決定,因此無法在 compile 後,就知道 library 中
的 function 在哪,該跳去哪

• GOT 為⼀一個函式指標陣列列,儲存其他 library 中,function 的位置,但因
Lazy binding 的機制,並不會⼀一開始就把正確的位置填上,⽽而是填上⼀一段
plt 位置的 code
Global Offset Table
• 當執⾏行行到 library 的 function 時才會真正去尋找 function ,最後再把 GOT
中的位置填上真正 function 的位置
Global Offset Table
• 分成兩兩部分

• .got

• 保存全域變數引⽤用位置

• .got.plt

• 保存函式引⽤用位置
Global Offset Table
• .got.plt

• 前三項有特別⽤用途

• address of .dynamic

• link_map

• ⼀一個將有引⽤用到的 library 所串串成的 linked list ,function resolve 時也會⽤用到

• dl_runtime_resolve

• ⽤用來來找出函式位置的函式

• 後⾯面則是程式中 .so 函式引⽤用位置
Global Offset Table
• layout
.dynamic
.got
.got.plt
.data
addr of .dynamic
link_map
dl_resolve
printf
put
…
.
.
.
call foo@plt
…
Lazy binding
.text
jmp *(foo@GOT)
push index
jmp PLT0
foo@plt
.got.plt (GOT)
printf
foo@plt+6
bar
…
push *(GOT + 8)
jmp *(GOT + 0x10)
PLT0
.
.
.
call foo@plt
…
.text
jmp *(foo@GOT)
push index
jmp PLT0
foo@plt
printf
foo@plt+6
bar
…
push *(GOT + 8)
jmp *(GOT + 0x10)
PLT0
Lazy binding
.got.plt (GOT)
.
.
.
call foo@plt
…
.text
jmp *(foo@GOT)
push index
jmp PLT0
foo@plt
printf
foo@plt+6
bar
…
push *(GOT + 8)
jmp *(GOT + 0x10)
PLT0
因 foo 還沒 call 過
所以 foo 在 .got.plt 中所存的值
會是.plt中的下⼀一⾏行行指令位置
所以看起來來會像沒有 jmp 過
Lazy binding
.got.plt (GOT)
.
.
.
call foo@plt
…
.text
jmp *(foo@GOT)
push index
jmp PLT0
foo@plt
printf
foo@plt+6
bar
…
push *(GOT + 8)
jmp *(GOT + 0x10)
PLT0
Lazy binding
.got.plt (GOT)
.
.
.
call foo@plt
…
.text
jmp *(foo@GOT)
push index
jmp PLT0
foo@plt
printf
foo@plt+6
bar
…
push *(GOT + 8)
jmp *(GOT + 0x10)
PLT0
Lazy binding
.got.plt (GOT)
.
.
.
call foo@plt
…
.text
jmp *(foo@GOT)
push index
jmp PLT0
foo@plt
printf
foo@plt+6
bar
…
push *(GOT + 8)
jmp *(GOT + 0x10)
PLT0
push link_map
Lazy binding
.got.plt (GOT)
.
.
.
call foo@plt
…
.text
jmp *(foo@GOT)
push index
jmp PLT0
foo@plt
printf
foo@plt+6
bar
…
push *(GOT + 8)
jmp *(GOT + 0x10)
PLT0
jmp dl_runtime_resolve
dl_runtime_resolve (link_map,index)
Lazy binding
.got.plt (GOT)
.
.
.
call foo@plt
…
.text
printf
foo@plt+6
bar
…
..
..
call _fix_up
..
..
ret 0xc
dl_resolve
Lazy binding
.got.plt (GOT)
.
.
.
call foo@plt
…
.text
printf
foo@plt+6
bar
…
..
..
call _fix_up
..
..
ret 0xc
dl_resolve
foo 找到 foo 在 library 的位置後
會填回 .got.plt
Lazy binding
.got.plt (GOT)
.
.
.
call foo@plt
…
Lazy binding
.text
printf
foo@plt+6
bar
…
..
..
call _fix_up
..
..
ret 0xc
dl_resolve
foo
return to foo
.got.plt (GOT)
• 第⼆二次 call foo 時
.
.
.
call foo@plt
…
.text
jmp *(foo@GOT)
push index
jmp PLT0
foo@plt
printf
foo@plt+6
bar
…
push *(GOT + 8)
jmp *(GOT + 0x10)
PLT0
Lazy binding
foo
.got.plt (GOT)
• 第⼆二次 call foo 時
.
.
.
call foo@plt
…
.text
jmp *(foo@GOT)
push index
jmp PLT0
foo@plt
printf
foo@plt+6
bar
…
push *(GOT + 8)
jmp *(GOT + 0x10)
PLT0
Lazy binding
foo
Jmp to foo function
.got.plt (GOT)
How to find the GOT
• objdump -R elf or readelf -r elf
• 為了了實作 Lazy binding 的機制 GOT 位置必須是可寫入的

• 如果程式有存在任意更更改位置的漏洞洞,便便可改寫 GOT ,造成程式流程的改
變

• 也就是控制 RIP
GOT Hijacking
• 第⼆二次 call foo 時
.
vulnerability
.
call foo@plt
…
.text
jmp *(foo@GOT)
push index
jmp PLT0
foo@plt
.got.plt
printf
foo@plt+6
bar
…
push *(GOT + 8)
jmp *(GOT + 0x10)
PLT0
GOT Hijacking
foo
• 第⼆二次 call foo 時
.
vulnerability
.
call foo@plt
…
.text
jmp *(foo@GOT)
push index
jmp PLT0
foo@plt
.got.plt
printf
foo@plt+6
bar
…
push *(GOT + 8)
jmp *(GOT + 0x10)
PLT0
GOT Hijacking
system
• 第⼆二次 call foo 時
.
.
.
call foo@plt
…
.text
jmp *(foo@GOT)
push index
jmp PLT0
foo@plt
.got.plt
printf
foo@plt+6
bar
…
push *(GOT + 8)
jmp *(GOT + 0x10)
PLT0
GOT Hijacking
system
• 第⼆二次 call foo 時
.
.
.
call foo@plt
…
.text
jmp *(foo@GOT)
push index
jmp PLT0
foo@plt
.got.plt
printf
foo@plt+6
bar
…
push *(GOT + 4)
jmp *(GOT + 8)
PLT0
GOT Hijacking
system
Jump to system :)
RELRO
• 分成三種

• Disabled

• .got/.got.plt 都可寫

• Partial (default)

• .got 唯獨

• Fulled

• RELRO 保護下,會在 load time 時將全部 function resolve 完畢
Outline
• Buffer Overflow

• Return to Text / Shellcode

• Protection

• Lazy binding

• Return to Library
Return to Library
• 在⼀一般正常情況下程式中很難會有 system 等,可以直接獲得 shell 的
function

• 在 DEP/NX 的保護下我們也無法直接填入 shellcode 去執⾏行行我們的程式碼
Return to Library
• ⽽而在 Dynamic Linking 情況下,⼤大部份程式都會載入 libc ,libc 中有非常多
好⽤用的 function 可以達成我們的⽬目的

• system

• execve

• …
Return to Library
• 但⼀一般情況下都會因為 ASLR 關係,導致每次 libc 載入位置不固定

• 所以我們通常都需要 information leak 的漏洞洞來來或取 libc 的 base address
進⽽而算出 system 等 function 位置,再將程式導過去
Return to Library
• 通常可以獲得 libc 位置的地⽅方

• GOT

• Stack 上的殘留留值

• function return 後並不會將 stack 中的內容清除

• heap 上的殘留留值

• free 完之後在 malloc,也不會將 heap 存的內容清空
Return to Library
• ⽽而⼀一般情況下的 ASLR 都是整個 library image ⼀一起移動,因此只要有 leak
出 libc 中的位址,通常都可以算出 libc

• 我們可利利⽤用 objdump -T libc.so.6 | grep function 來來找尋想找的 function 在
libc 中的 offset

• 如果我們獲得 printf 位置,可先找尋 printf 在 libc 中的 offset 以及想要利利⽤用
的 function offset
Return to Library
• printf : 0x7ffff7a62800 (0x55800)

• libc base : 0x7ffff7a62800 - 0x55800 = 0x7ffff7a0d000

• system : 0x7ffff7a0d000 + 0x45390 = 0x7ffff7a52390
CODE VMA
DATA VMA
STACK
Library
system (base + 0x45390)
printf (0x7ffff7a62800)
base (0x7ffff7a62800)
Return to Library
• 在獲得 system 位置之後,我們可以複寫 return address 跳到 system 上,
這邊要注意的是參參數也要⼀一起放上,

• 但在 x86-64 Linux 上傳遞參參數是⽤用 register 傳遞的,第⼀一個參參數會放在 rdi
所以我們必須想辦法將 /bin/sh 的位置放在 rdi 上

• 可利利⽤用 pop rdi ; ret 的⽅方式將參參數放到 rdi
Return to Library
address of /bin/sh
new ret
system
aaaaaaaa
aaaaaaaa
aaaaaaaa
rsp
stack overflow ret
address of pop rdi
ret
pop rdi
ret
Return to Library
address of /bin/sh
new ret
system
aaaaaaaa
aaaaaaaa
aaaaaaaa
rsp
stack overflow ret
address of pop rdi
ret
pop rdi
ret
Return to Library
address of /bin/sh
new ret
system
aaaaaaaa
aaaaaaaa
aaaaaaaa
rsp
stack overflow ret
address of pop rdi
ret
pop rdi
ret
rdi address of /bin/sh
Return to Library
address of /bin/sh
new ret
system
aaaaaaaa
aaaaaaaa
aaaaaaaa
rsp
stack overflow ret
address of pop rdi
ret
pop rdi
ret
rdi address of /bin/sh
system(“/bin/sh”)
Return to Library
• 補充:

• “/bin/sh” 字串串位置也可以在 libc 中找到,因此當程式中沒有該字串串,可
從 libc 裡⾯面找

• system 參參數只要 “sh” 即可,因此也可以考慮只找 “sh” 字串串
Reference
• Glibc cross reference 

• 程式設計師的⾃自我修養
Q & A

More Related Content

PDF
Sigreturn Oriented Programming
PDF
Advanced heap exploitaion
PDF
Linux Binary Exploitation - Return-oritend Programing
PDF
ROP 輕鬆談
PDF
Binary exploitation - AIS3
PDF
Pwning in c++ (basic)
PDF
Heap exploitation
PDF
Linux binary Exploitation - Basic knowledge
Sigreturn Oriented Programming
Advanced heap exploitaion
Linux Binary Exploitation - Return-oritend Programing
ROP 輕鬆談
Binary exploitation - AIS3
Pwning in c++ (basic)
Heap exploitation
Linux binary Exploitation - Basic knowledge

What's hot (20)

PDF
Linux Binary Exploitation - Heap Exploitation
PDF
Execution
PDF
Return to dlresolve
PDF
Play with FILE Structure - Yet Another Binary Exploit Technique
PDF
twlkh-linux-vsyscall-and-vdso
PDF
Instruction Combine in LLVM
PDF
Kernel Recipes 2019 - Faster IO through io_uring
PDF
LLVM Register Allocation (2nd Version)
PDF
MacOS memory allocator (libmalloc) Exploitation - Chinese Version
PDF
A whirlwind tour of the LLVM optimizer
PDF
Windows 10 Nt Heap Exploitation (English version)
PDF
MacOS memory allocator (libmalloc) Exploitation
PDF
Master Canary Forging: 新しいスタックカナリア回避手法の提案 by 小池 悠生 - CODE BLUE 2015
PDF
Tcache Exploitation
PDF
TDOH x 台科 pwn課程
PDF
Surviving the Java Deserialization Apocalypse // OWASP AppSecEU 2016
ODP
How to get LBR contents on Intel x86
PDF
台科逆向簡報
PDF
GDB Rocks!
PDF
Part II: LLVM Intermediate Representation
Linux Binary Exploitation - Heap Exploitation
Execution
Return to dlresolve
Play with FILE Structure - Yet Another Binary Exploit Technique
twlkh-linux-vsyscall-and-vdso
Instruction Combine in LLVM
Kernel Recipes 2019 - Faster IO through io_uring
LLVM Register Allocation (2nd Version)
MacOS memory allocator (libmalloc) Exploitation - Chinese Version
A whirlwind tour of the LLVM optimizer
Windows 10 Nt Heap Exploitation (English version)
MacOS memory allocator (libmalloc) Exploitation
Master Canary Forging: 新しいスタックカナリア回避手法の提案 by 小池 悠生 - CODE BLUE 2015
Tcache Exploitation
TDOH x 台科 pwn課程
Surviving the Java Deserialization Apocalypse // OWASP AppSecEU 2016
How to get LBR contents on Intel x86
台科逆向簡報
GDB Rocks!
Part II: LLVM Intermediate Representation
Ad

Similar to Linux Binary Exploitation - Stack buffer overflow (20)

PPT
常用Mac/Linux命令分享
PDF
Buffer pool implementaion inno db vs oracle
PPTX
为啥别读HotSpot VM的源码(2012-03-03)
PDF
淘宝主备数据库自动切换
PPTX
HBase
PDF
Rootkit 101
PPTX
Hbase介绍
PDF
Pegasus: Designing a Distributed Key Value System (Arch summit beijing-2016)
PDF
Bypat博客出品-服务器运维集群方法总结2
PPT
数据库高可用架构
PDF
Bypat博客出品-服务器运维集群方法总结
PDF
Hantuo openstack
PPTX
Nosql三步曲
PDF
数据库内核分享——第一期
PDF
主库自动切换 V2.0
PDF
MySQL自动切换设计与实现
PDF
Golang 高性能实战
PDF
千呼萬喚始出來的 Java SE 7
PPTX
Kafka in Depth
PDF
Cephfs架构解读和测试分析
常用Mac/Linux命令分享
Buffer pool implementaion inno db vs oracle
为啥别读HotSpot VM的源码(2012-03-03)
淘宝主备数据库自动切换
HBase
Rootkit 101
Hbase介绍
Pegasus: Designing a Distributed Key Value System (Arch summit beijing-2016)
Bypat博客出品-服务器运维集群方法总结2
数据库高可用架构
Bypat博客出品-服务器运维集群方法总结
Hantuo openstack
Nosql三步曲
数据库内核分享——第一期
主库自动切换 V2.0
MySQL自动切换设计与实现
Golang 高性能实战
千呼萬喚始出來的 Java SE 7
Kafka in Depth
Cephfs架构解读和测试分析
Ad

Linux Binary Exploitation - Stack buffer overflow

  • 2. Outline • Buffer Overflow • Return to Text / Shellcode • Protection • Lazy binding • Return to Library
  • 3. Outline • Buffer Overflow • Return to Text / Shellcode • Protection • Lazy binding • Return to Library
  • 4. Buffer Overflow • 程式設計師未對 buffer 做長度檢查,造成可以讓攻擊者輸入過長的字串串,覆 蓋記憶體上的其他資料,嚴重時更更可控制程式流程 • 依照 buffer 位置可分為 • stack base • ⼜又稱為 stack smashing • data base • heap base
  • 6. Buffer Overflow • Vulnerable Function • gets • scanf • strcpy • sprintf • memcpy • strcat • …
  • 7. • memory layout Stack Overflow return address rbp rbp/rsp char buf[0x20] read(0,buf,100) leave ret high low
  • 8. • memory layout Stack Overflow return address rbp rbp/rsp char buf[0x20] read(0,buf,100) leave ret high low
  • 9. • memory layout Stack Overflow return address rbp rbp char buf[0x20] read(0,buf,100) leave ret high low rsp buf[0x20]
  • 10. • memory layout Stack Overflow aaaaaaaa aaaaaaaa aaaaaaaa aaaaaaaa aaaaaaaa (ret) aaaaaaaa (rbp) rbp char buf[0x20] read(0,buf,100) leave ret high low rsp buf[0x20]
  • 11. • memory layout Stack Overflow aaaaaaaa aaaaaaaa aaaaaaaa aaaaaaaa aaaaaaaa (ret) aaaaaaaa (rbp) rbpchar buf[0x20] read(0,buf,100) mov rsp,rbp pop rbp ret high low rsp buf[0x20]
  • 12. • memory layout Stack Overflow aaaaaaaa aaaaaaaa aaaaaaaa aaaaaaaa aaaaaaaa (ret) aaaaaaaa (rbp) rbp/rspchar buf[0x20] read(0,buf,100) mov rsp,rbp pop rbp ret high low buf[0x20]
  • 13. • memory layout Stack Overflow aaaaaaaa aaaaaaaa aaaaaaaa aaaaaaaa aaaaaaaa (ret) aaaaaaaa (rbp) rsp char buf[0x20] read(0,buf,100) mov rsp,rbp pop rbp ret high low buf[0x20]
  • 14. • memory layout Stack Overflow aaaaaaaa aaaaaaaa aaaaaaaa aaaaaaaa aaaaaaaa (ret) aaaaaaaa (rbp) rspchar buf[0x20] read(0,buf,100) mov rsp,rbp pop rbp ret high low buf[0x20]RIP = 0x6161616161616161
  • 17. Stack Overflow • From crash to exploit • 隨意任意輸入⼀一堆資料應該只能造成 crash • 需適當的構造資料,就可巧妙的控制程式流程 • EX : • 適當得構造 return address 就可在函數返回時,跳到攻擊者的程式碼
  • 18. Stack Overflow • From crash to exploit • Overwrite the the return address • 因 x86 底下是 little-endian 的,所以填入 address 時,需要反過來來填入 • e.g. • 假設要填入 0x00400646 就需要填入 x46x06x40x00x00x00x00x000 • p64(0x400646) # in pwntools
  • 19. Outline • Buffer Overflow • Return to Text / Shellcode • Protection • Lazy binding • Return to Library
  • 20. Return to Text • 控制 eip 後跳到原本程式中的程式碼 • 以 bofeasy 範例例來來說,我們可以跳到 l33t 這個 function • 可以 objdump 來來找尋函式真正位置
  • 22. Return to Text • Exploitation • Locate the return address • 可⽤用 aaaaaaaabbbbbbbb…… 八個⼀一組的字來來定位 return address • pwntool cyclic • gdb-peda pattc
  • 23. Return to Text • Exploitation • Write exploit • echo -ne “aaaaaaaabbbbbbbbccccccccddddddddeeeeeeex46x60x40x00x 00x00x00x00” > exp • cat exp - | ./bofeasy
  • 24. Return to Text • Exploitation • Write exploit
  • 25. Return to Text • Exploitation • Debug exploit • gdb$ r < exp
  • 26. Return to Text • Exploitation • Debug exploit • Use attach more would be easier
  • 27. Return to Shellcode • 如果在 data 段上是可執⾏行行且位置固定的話,我們也可以先在 data 段上塞入 shellcode 跳過去
  • 28. Outline • Buffer Overflow • Return to Text / Shellcode • Protection • Lazy binding • Return to Library
  • 29. Protection • ASLR • DEP • PIE • StackGuard
  • 30. Protection • ASLR • 記憶體位置隨機變化 • 每次執⾏行行程式時,stack 、heap、library 位置都不⼀一樣 • 查看是否有開啟 ASLR • cat /proc/sys/kernel/randomize_va_space
  • 31. Protection • ASLR kernel space CODE VMA DATA VMA HEAP STACK Library kernel space CODE VMA DATA VMA HEAP STACK Library kernel space CODE VMA DATA VMA HEAP STACK Library
  • 32. Protection • ASLR • 使⽤用 ldd (可看執⾏行行時載入的 library 及其位置) 觀察 address 變化
  • 33. Protection • DEP • ⼜又稱 NX • 可寫的不可執⾏行行,可執⾏行行的不可寫
  • 35. Protection • PIE ( Position Independent Execution ) • gcc 在預設情況下不會開啟,編譯時加上 -fPIC -pie 就可以開啟 • 在沒開啟的情況下程式的 data 段及 code 段會是固定的 • ⼀一但開啟之後 data 及 code 也會跟著 ASLR ,因此前⾯面說的 ret2text/ shellcode 沒有固定位置可以跳,就變得困難許多
  • 36. • objdump 觀察 pie 開啟的 binary • code address 變成只剩下 offset 執⾏行行後會加上 code base 才是真正在記 憶體中的位置 Protection
  • 37. Protection • StackGuard • 在程式執⾏行行是隨機⽣生成⼀一亂數 function call 時會塞入 stack 中,在 function return 時會檢查是否該值有被更更動,⼀一旦發現被更更動就結束該程 式 • 該值⼜又稱 canary • 非常有效地阻擋了了 stack overflow 的攻擊 • ⽬目前預設情況下是開啟的
  • 38. Protection • StackGuard • canary 的值在執⾏行行期間都會先放在,⼀一個稱為 tls 的區段中的 tcbhead_t 結構中,⽽而在 x86/x64 架構下恆有⼀一個暫存器指向 tls 段的 tcbhead_t 結 構 • x86 : gs • x64 : fs • 因此程式在取 canary 值時都會直接以 fs/gs 做存取
  • 39. Protection • StackGuard return address rsp push rbp mov rbp,rsp sub rsp, 0x40 mov [rbp-0x8],fs:0x28 … mov rax,[rbp-0x8] cmp rax,fs:0x28 jne stack_check_fail leave ret fs:0x28 High lowcanary
  • 40. Protection • StackGuard … return address rbp rsp push rbp mov rbp,rsp sub rsp, 0x40 mov [rbp-0x8],fs:0x28 … mov rax,[rbp-0x8] cmp rax,fs:0x28 jne stack_check_fail leave ret rbp High lowfs:0x28 canary
  • 41. Protection • StackGuard … return address rbp rsp push rbp mov rbp,rsp sub rsp, 0x40 mov [rbp-0x8],fs:0x28 … mov rax,[rbp-0x8] cmp rax,fs:0x28 jne stack_check_fail leave ret rbp High low canary fs:0x28 canary
  • 42. Protection • StackGuard … return address rbp rsp push rbp mov rbp,rsp sub rsp, 0x40 mov [rbp-0x8],fs:0x28 … mov rax,[rbp-0x8] cmp rax,fs:0x28 jne stack_check_fail leave ret rbp High low canary fs:0x28 canary
  • 43. Protection • StackGuard … return address rbp rsp push rbp mov rbp,rsp sub rsp, 0x40 mov [rbp-0x8],fs:0x28 … mov rax,[rbp-0x8] cmp rax,fs:0x28 jne stack_check_fail leave ret rbp High low canary fs:0x28 canary rax canary
  • 44. Protection • StackGuard … return address rbp rsp push rbp mov rbp,rsp sub rsp, 0x40 mov [rbp-0x8],fs:0x28 … mov rax,[rbp-0x8] cmp rax,fs:0x28 jne stack_check_fail leave ret rbp High low canary fs:0x28 canary rax canary
  • 45. Protection • StackGuard … return address rbp rsp push rbp mov rbp,rsp sub rsp, 0x40 mov [rbp-0x8],fs:0x28 … mov rax,[rbp-0x8] cmp rax,fs:0x28 jne stack_check_fail leave ret rbp High low canary fs:0x28 canary rax canary
  • 46. Protection • StackGuard - overflow … return address rbp rsp push rbp mov rbp,rsp sub rsp, 0x40 mov [rbp-0x8],fs:0x28 … mov rax,[rbp-0x8] cmp rax,fs:0x28 jne stack_check_fail leave ret rbp High low canary fs:0x28 canary
  • 47. Protection • StackGuard - overflow aaaaaaaa aaaaaaaa aaaaaaaa aaaaaaaa aaaaaaaa aaaaaaaa aaaaaaaa aaaaaaaa rsp push rbp mov rbp,rsp sub rsp, 0x40 mov [rbp-0x8],fs:0x28 … mov rax,[rbp-0x8] cmp rax,fs:0x28 jne stack_check_fail leave ret rbp High low aaaaaaaa fs:0x28 canary
  • 48. Protection • StackGuard - overflow aaaaaaaa aaaaaaaa aaaaaaaa aaaaaaaa aaaaaaaa aaaaaaaa aaaaaaaa aaaaaaaa rsp push rbp mov rbp,rsp sub rsp, 0x40 mov [rbp-0x8],fs:0x28 … mov rax,[rbp-0x8] cmp rax,fs:0x28 jne stack_check_fail leave ret rbp High low aaaaaaaa fs:0x28 canary rax aaaaaaaa
  • 49. Protection • StackGuard - overflow aaaaaaaa aaaaaaaa aaaaaaaa aaaaaaaa aaaaaaaa aaaaaaaa aaaaaaaa aaaaaaaa rsp push rbp mov rbp,rsp sub rsp, 0x40 mov [rbp-0x8],fs:0x28 … mov rax,[rbp-0x8] cmp rax,fs:0x28 jne stack_check_fail leave ret rbp High low aaaaaaaa fs:0x28 canary rax aaaaaaaa
  • 50. Protection • StackGuard - overflow aaaaaaaa aaaaaaaa aaaaaaaa aaaaaaaa aaaaaaaa aaaaaaaa aaaaaaaa aaaaaaaa rsp push rbp mov rbp,rsp sub rsp, 0x40 mov [rbp-0x8],fs:0x28 … mov rax,[rbp-0x8] cmp rax,fs:0x28 jne stack_check_fail leave ret rbp High low aaaaaaaa fs:0x28 canary rax aaaaaaaa Abort !
  • 52. Outline • Buffer Overflow • Return to Text / Shellcode • Protection • Lazy binding • Return to Library
  • 53. Lazy binding • Dynamic linking 的程式在執⾏行行過程中,有些 library 的函式可能到結束都不 會執⾏行行到 • 所以 ELF 採取 Lazy binding 的機制,在第⼀一次 call library 函式時,才會去 尋找函式真正的位置進⾏行行 binding
  • 54. Global Offset Table • library 的位置再載入後才決定,因此無法在 compile 後,就知道 library 中 的 function 在哪,該跳去哪 • GOT 為⼀一個函式指標陣列列,儲存其他 library 中,function 的位置,但因 Lazy binding 的機制,並不會⼀一開始就把正確的位置填上,⽽而是填上⼀一段 plt 位置的 code
  • 55. Global Offset Table • 當執⾏行行到 library 的 function 時才會真正去尋找 function ,最後再把 GOT 中的位置填上真正 function 的位置
  • 56. Global Offset Table • 分成兩兩部分 • .got • 保存全域變數引⽤用位置 • .got.plt • 保存函式引⽤用位置
  • 57. Global Offset Table • .got.plt • 前三項有特別⽤用途 • address of .dynamic • link_map • ⼀一個將有引⽤用到的 library 所串串成的 linked list ,function resolve 時也會⽤用到 • dl_runtime_resolve • ⽤用來來找出函式位置的函式 • 後⾯面則是程式中 .so 函式引⽤用位置
  • 58. Global Offset Table • layout .dynamic .got .got.plt .data addr of .dynamic link_map dl_resolve printf put …
  • 59. . . . call foo@plt … Lazy binding .text jmp *(foo@GOT) push index jmp PLT0 foo@plt .got.plt (GOT) printf foo@plt+6 bar … push *(GOT + 8) jmp *(GOT + 0x10) PLT0
  • 60. . . . call foo@plt … .text jmp *(foo@GOT) push index jmp PLT0 foo@plt printf foo@plt+6 bar … push *(GOT + 8) jmp *(GOT + 0x10) PLT0 Lazy binding .got.plt (GOT)
  • 61. . . . call foo@plt … .text jmp *(foo@GOT) push index jmp PLT0 foo@plt printf foo@plt+6 bar … push *(GOT + 8) jmp *(GOT + 0x10) PLT0 因 foo 還沒 call 過 所以 foo 在 .got.plt 中所存的值 會是.plt中的下⼀一⾏行行指令位置 所以看起來來會像沒有 jmp 過 Lazy binding .got.plt (GOT)
  • 62. . . . call foo@plt … .text jmp *(foo@GOT) push index jmp PLT0 foo@plt printf foo@plt+6 bar … push *(GOT + 8) jmp *(GOT + 0x10) PLT0 Lazy binding .got.plt (GOT)
  • 63. . . . call foo@plt … .text jmp *(foo@GOT) push index jmp PLT0 foo@plt printf foo@plt+6 bar … push *(GOT + 8) jmp *(GOT + 0x10) PLT0 Lazy binding .got.plt (GOT)
  • 64. . . . call foo@plt … .text jmp *(foo@GOT) push index jmp PLT0 foo@plt printf foo@plt+6 bar … push *(GOT + 8) jmp *(GOT + 0x10) PLT0 push link_map Lazy binding .got.plt (GOT)
  • 65. . . . call foo@plt … .text jmp *(foo@GOT) push index jmp PLT0 foo@plt printf foo@plt+6 bar … push *(GOT + 8) jmp *(GOT + 0x10) PLT0 jmp dl_runtime_resolve dl_runtime_resolve (link_map,index) Lazy binding .got.plt (GOT)
  • 67. . . . call foo@plt … .text printf foo@plt+6 bar … .. .. call _fix_up .. .. ret 0xc dl_resolve foo 找到 foo 在 library 的位置後 會填回 .got.plt Lazy binding .got.plt (GOT)
  • 68. . . . call foo@plt … Lazy binding .text printf foo@plt+6 bar … .. .. call _fix_up .. .. ret 0xc dl_resolve foo return to foo .got.plt (GOT)
  • 69. • 第⼆二次 call foo 時 . . . call foo@plt … .text jmp *(foo@GOT) push index jmp PLT0 foo@plt printf foo@plt+6 bar … push *(GOT + 8) jmp *(GOT + 0x10) PLT0 Lazy binding foo .got.plt (GOT)
  • 70. • 第⼆二次 call foo 時 . . . call foo@plt … .text jmp *(foo@GOT) push index jmp PLT0 foo@plt printf foo@plt+6 bar … push *(GOT + 8) jmp *(GOT + 0x10) PLT0 Lazy binding foo Jmp to foo function .got.plt (GOT)
  • 71. How to find the GOT • objdump -R elf or readelf -r elf
  • 72. • 為了了實作 Lazy binding 的機制 GOT 位置必須是可寫入的 • 如果程式有存在任意更更改位置的漏洞洞,便便可改寫 GOT ,造成程式流程的改 變 • 也就是控制 RIP GOT Hijacking
  • 73. • 第⼆二次 call foo 時 . vulnerability . call foo@plt … .text jmp *(foo@GOT) push index jmp PLT0 foo@plt .got.plt printf foo@plt+6 bar … push *(GOT + 8) jmp *(GOT + 0x10) PLT0 GOT Hijacking foo
  • 74. • 第⼆二次 call foo 時 . vulnerability . call foo@plt … .text jmp *(foo@GOT) push index jmp PLT0 foo@plt .got.plt printf foo@plt+6 bar … push *(GOT + 8) jmp *(GOT + 0x10) PLT0 GOT Hijacking system
  • 75. • 第⼆二次 call foo 時 . . . call foo@plt … .text jmp *(foo@GOT) push index jmp PLT0 foo@plt .got.plt printf foo@plt+6 bar … push *(GOT + 8) jmp *(GOT + 0x10) PLT0 GOT Hijacking system
  • 76. • 第⼆二次 call foo 時 . . . call foo@plt … .text jmp *(foo@GOT) push index jmp PLT0 foo@plt .got.plt printf foo@plt+6 bar … push *(GOT + 4) jmp *(GOT + 8) PLT0 GOT Hijacking system Jump to system :)
  • 77. RELRO • 分成三種 • Disabled • .got/.got.plt 都可寫 • Partial (default) • .got 唯獨 • Fulled • RELRO 保護下,會在 load time 時將全部 function resolve 完畢
  • 78. Outline • Buffer Overflow • Return to Text / Shellcode • Protection • Lazy binding • Return to Library
  • 79. Return to Library • 在⼀一般正常情況下程式中很難會有 system 等,可以直接獲得 shell 的 function • 在 DEP/NX 的保護下我們也無法直接填入 shellcode 去執⾏行行我們的程式碼
  • 80. Return to Library • ⽽而在 Dynamic Linking 情況下,⼤大部份程式都會載入 libc ,libc 中有非常多 好⽤用的 function 可以達成我們的⽬目的 • system • execve • …
  • 81. Return to Library • 但⼀一般情況下都會因為 ASLR 關係,導致每次 libc 載入位置不固定 • 所以我們通常都需要 information leak 的漏洞洞來來或取 libc 的 base address 進⽽而算出 system 等 function 位置,再將程式導過去
  • 82. Return to Library • 通常可以獲得 libc 位置的地⽅方 • GOT • Stack 上的殘留留值 • function return 後並不會將 stack 中的內容清除 • heap 上的殘留留值 • free 完之後在 malloc,也不會將 heap 存的內容清空
  • 83. Return to Library • ⽽而⼀一般情況下的 ASLR 都是整個 library image ⼀一起移動,因此只要有 leak 出 libc 中的位址,通常都可以算出 libc • 我們可利利⽤用 objdump -T libc.so.6 | grep function 來來找尋想找的 function 在 libc 中的 offset • 如果我們獲得 printf 位置,可先找尋 printf 在 libc 中的 offset 以及想要利利⽤用 的 function offset
  • 84. Return to Library • printf : 0x7ffff7a62800 (0x55800) • libc base : 0x7ffff7a62800 - 0x55800 = 0x7ffff7a0d000 • system : 0x7ffff7a0d000 + 0x45390 = 0x7ffff7a52390 CODE VMA DATA VMA STACK Library system (base + 0x45390) printf (0x7ffff7a62800) base (0x7ffff7a62800)
  • 85. Return to Library • 在獲得 system 位置之後,我們可以複寫 return address 跳到 system 上, 這邊要注意的是參參數也要⼀一起放上, • 但在 x86-64 Linux 上傳遞參參數是⽤用 register 傳遞的,第⼀一個參參數會放在 rdi 所以我們必須想辦法將 /bin/sh 的位置放在 rdi 上 • 可利利⽤用 pop rdi ; ret 的⽅方式將參參數放到 rdi
  • 86. Return to Library address of /bin/sh new ret system aaaaaaaa aaaaaaaa aaaaaaaa rsp stack overflow ret address of pop rdi ret pop rdi ret
  • 87. Return to Library address of /bin/sh new ret system aaaaaaaa aaaaaaaa aaaaaaaa rsp stack overflow ret address of pop rdi ret pop rdi ret
  • 88. Return to Library address of /bin/sh new ret system aaaaaaaa aaaaaaaa aaaaaaaa rsp stack overflow ret address of pop rdi ret pop rdi ret rdi address of /bin/sh
  • 89. Return to Library address of /bin/sh new ret system aaaaaaaa aaaaaaaa aaaaaaaa rsp stack overflow ret address of pop rdi ret pop rdi ret rdi address of /bin/sh system(“/bin/sh”)
  • 90. Return to Library • 補充: • “/bin/sh” 字串串位置也可以在 libc 中找到,因此當程式中沒有該字串串,可 從 libc 裡⾯面找 • system 參參數只要 “sh” 即可,因此也可以考慮只找 “sh” 字串串
  • 91. Reference • Glibc cross reference • 程式設計師的⾃自我修養
  • 92. Q & A