SlideShare uma empresa Scribd logo
1 de 235
Baixar para ler offline
Linux Binary Exploitation
Angelboy @ AIS3 2017
1
About me
• Angelboy

• CTF player 

• WCTF / Boston Key Party 1st

• DEFCON / HITB 2nd

• Chroot / HITCON / 217

• Blog

• blog.angelboy.tw
2
Environment
• Ubuntu 16.04 64 bit

• binutils/nasm/ncat/gdb/pwntools/ropgadget/peda

• 練習題

• http://ais3.pwnhub.tw

• 懶懶⼈人包

• https://github.com/scwuaptx/AIS3-2017

• env_setup.sh
3
Outline
• Introduction

• Section

• Execution

• x86 assembly

• buffer overflow
4
Introduction
• Reverse Engineering

• Exploitation

• Useful Tool
5
Reverse Engineering
• 正常情況下我們不容易易取得執⾏行行檔的原始碼,所以我們很常需逆向分析程式
尋找漏洞洞

• Static Analysis

• Dynamic Analysis
binary source code
6
Reverse Engineering
• Static Analysis

• Analyze program without running

• e.g.

• objdump
• Machine code to asm
7
Reverse Engineering
• Dynamic Analysis

• Analyze program with running

• e.g.

• strace
• trace all system call 

• ltrace
• trace all library call
8
Exploitation
• 利利⽤用漏洞洞來來達成攻擊者⽬目的

• ⼀一般來來說主要⽬目的在於取得程式控制權

• ⼜又稱 Pwn
Vulnerability Control flow
9
Exploitation
• Binary exploitation

• 專指與 binary 相關的漏洞洞利利⽤用

• 兩兩⼤大主流

• 本地提權

• Remote code execution
Vulnerability Control flow
10
Useful Tool
• IDA PRO - a static analysis tool
11
Useful Tool
• GDB - a dynamic analysis tool

• The GNU Project Debugger
12
Useful Tool
• Basic command

• run - 執⾏行行

• disas function name - 反組譯某個 function

• break *0x400566 - 設斷點

• info breakpoint - 查看已設定哪些中斷點

• info register 查看所有 register 狀狀態
13
Useful Tool
• Basic command

• x/wx address - 查看 address 中的內容

• w 可換成 b/h/g 分別是取 1/2/8 byte

• / 後可接數字 表⽰示⼀一次列列出幾個

• 第⼆二個 x 可換成 u/d/s/i 以不同⽅方式表⽰示

• u : unsigned int 

• d : 10 進位 

• s : 字串串 

• i : 指令
14
Useful Tool
• Basic command

• x/gx address 查看 address 中的內容

• e.g.
15
Useful Tool
• Basic command

• ni - next instruction

• si - step into

• backtrace - 顯⽰示上層所有 stack frame 的資訊

• continue
16
Useful Tool
• Basic command

• set *address=value

• 將 address 中的值設成 value ⼀一次設 4 byte

• 可將 * 換成 {char/short/long} 分別設定 1/2/8 byte 

• e.g.

• set *0x602040=0xdeadbeef

• set {int}0x602040=1337
17
Useful Tool
• Basic command

• 在有 debug symbol 下

• list : 列列出 source code

• b 可直接接⾏行行號斷點

• info local : 列列出區域變數

• print val : 印出變數 val 的值
18
Useful Tool
• Basic command

• attach pid : attach ⼀一個正在運⾏行行的 process

• 可以配合 ncat 進⾏行行 exploit 的 debug

• ncat -ve ./a.out -kl 8888

• echo 0 > /proc/sys/kernel/yama/ptrace_scope
19
Useful Tool
• GDB - PEDA

• Python Exploit Development Assistance for GDB

• https://github.com/longld/peda

• https://github.com/scwuaptx/peda
20
GDB - PEDA
• Screenshot
21
GDB - PEDA
• Some useful feature

• checksec : Check for various security options of binary

• elfsymbol : show elf .plt section

• vmmap : show memory mapping

• readelf : Get headers information from an ELF file

• find/searchmem : Search for a pattern in memory

• record : record every instruction at runtime
22
GDB - PEDA
• checksec

• 查看 binary 中有哪些保護機制
23
GDB - PEDA
• elfsymbol

• 查看 function .plt 做 ROP 時非常需要
24
GDB - PEDA
• vmmap

• 查看 process mapping

• 可觀察到每個 address 中的權限
25
GDB - PEDA
• readelf

• 查看 section 位置

• 有些攻擊⼿手法會需要

• e.g. ret2dl_resolve
26
GDB - PEDA
• find (alias searchmem)

• search memory 中的 patten

• 通常拿來來找字串串

• e.g. /bin/sh
27
GDB - PEDA
• record

• 記錄每個 instruction 讓 gdb 可回朔前⾯面的指令,在 PC 被改變後,可利利
⽤用該功能,追回原本發⽣生問題的地⽅方
28
Useful Tool
• Pwntools

• Exploit development library

• python
29
LAB 1
• sysm4gic

• 利利⽤用 debugger 獲取 flag
30
Outline
• Introduction

• Section

• Execution

• x86 assembbly
31
Section
• 在⼀一般情況下程式碼會分成 text、data 以及 bss 等 section ,並不會將
code 跟 data 混在⼀一起使⽤用
32
Section
• .text

• 存放 code 的 section

• .data

• 存放有初始值的全域變數

• .bss

• 存放沒有初始值的全域變數

• .rodata

• 存放唯讀資料的 section
33
Section
.bss
.data .rodata
34
Execution
• Binary Format

• Segment

• Execution Flow
35
Binary Format
• 執⾏行行檔的格式會根據 OS 不同,⽽而有所不同

• Linux - ELF

• Windows - PE

• 在 Binary 的開頭會有個 magic number 欄欄位,⽅方便便讓 OS 辨認是屬於什什麼
樣類型的檔案

• 在 Linux 下可以使⽤用 file 來來檢視
36
Segment
• 在程式執⾏行行時期才會有的概念念,基本上會根據讀寫執⾏行行權限及特性來來分為數
個 segment

• ⼀一般來來說可分為 rodata、data、code、stack、heap 等 segment

• data : rw-

• code : r-x

• stack : rw-

• heap : rw-
37
Execution Flow
• What happened when we execute an elf file ?

• $ ./hello

• 在⼀一般情況下程式會在 disk 中,⽽而 kernel 會通過⼀一連串串的過程來來將程式
mapping 到記憶體中去執⾏行行
38
Execution Flow
./hello
fork()
execve(“./hello”,*argv[],*envp[])
sys_execve()
do_execve() search_binary_handler()
load_elf_binary()
_start
main
kernel mode
user mode
39
Execution Flow
./hello
fork()
execve(“./hello”,*argv[],*envp[])
sys_execve()
do_execve() search_binary_handler()
load_elf_binary()
ld.so
_start
__libc_start_main _init
kernel mode
user mode
main
40
Execution Flow
• How program maps to virtual memory.

• 在 program header 中

• 記錄著哪些 segment 應該 mapping 到什什麼位置,以及該 segment 的讀寫
執⾏行行權限

• 記錄哪些 section 屬於哪些 segment

• 當 program mapping 記憶體時會根據權限的不同來來分成好幾個 segment

• ⼀一個 segment 可以包含 0 個到多個 section
41
Execution Flow
• How program maps to virtual memory.
other section
.data
.bss
.got.plt
.rodata
.text
.init
ELF Header
In disk In memory
kernel space
CODE VMA
DATA VMA
HEAP
STACK
R or RX
RW
0x400000
0x601000
0x602000
0x7fffffffe520
42
Execution Flow
• How program maps to virtual memory.

• readelf -l binary

• 查看 program header

• readelf -S binary

• 查看 section header

• readelf -d binary

• 查看 dynamic section 內容
43
Execution Flow
• How program maps to virtual memory.
權限
mapping 位置
segment 中有哪些 section
44
Execution Flow
• ld.so

• 載入 elf 所需的 shared library

• 這部分會記錄在 elf 中的 DT_NEED 中

• 初始化 GOT 

• 其他相關初始化的動作

• ex : 將 symbol table 合併到 global symbol table 等等

• 對實際運作過程有興趣可參參考 elf/rtld.c
45
Execution Flow
• 在 ld.so 執⾏行行完後會跳到 _start 開始執⾏行行主要程式
_start __libc_start_main
.init
main
.fini
exit
46
Execution Flow
• _start

• 將下列列項⽬目傳給 libc_start_main

• 環境變數起始位置

• main 的位置 (通常在第⼀一個參參數)

• .init 

• 呼叫 main 之前的初始化⼯工作

• .fini

• 程式結束前的收尾⼯工作
_start
__libc_start_main
47
Execution Flow
• _libc_start_main

• 執⾏行行 .init

• 執⾏行行 main

• 主程式部分

• 執⾏行行 .fini

• 執⾏行行 exit 結束程式
48
• Registers

• General-purpose registers

• RAX RBX RCX RDX RSI RDI- 64 bit

• EAX EBX ECX EDX ESI EDI - 32 bit

• AX BX CX DX SI DI - 16 bit
x64 assembly
ALAH
EAX
AX
RAX
49
• Registers

• r8 r9 r10 r11 r12 r13 r14 r15 - 64 bit

• r8d r9d r10d … - 32 bit

• r8w r9w r10w … -16 bit

• r8b r9b r10b … - 8 bit
x64 assembly
50
• Registers

• Stack Pointer Register

• RSP

• Base Pointer Register

• RBP

• Program Counter Register

• RIP
x64 assembly
51
x64 assembly
• Registers

• Stack Pointer

• RSP - 64 bit

• 指向 stack 頂端

• Base Pointer

• RBP - 64 bit

• 指向 stack 底端

• RSP 到 function 參參數範圍稱為該 function 的 Stack Frame
…
…
…
…
variable
return address
rbp
rbp
rsp
high
low
extra-arg
52
x64 assembly
• Registers

• Stack Pointer

• RSP - 64 bit

• 指向 stack 頂端

• Base Pointer

• RBP - 64 bit

• 指向 stack 底端

• RSP 到 function 參參數範圍稱為該 function 的 Stack Frame
high
low
…
…
…
…
variable
return address
rbp
rbp
rsp
extra-arg
stack frame
53
x64 assembly
• Registers

• Program counter register

• RIP

• 指向⽬目前程式執⾏行行的位置

• Flag register

• eflags

• 儲存指令執⾏行行結果

• Segment register

• cs ss ds es fs gs
54
x64 assembly
• AT & T

• mov %rax,%rbx

• Intel

• mov rbx,rax
55
x64 assembly
• Basic instruction

• mov

• add/sub

• and/or/xor

• push/pop

• lea

• jmp/call/ret
56
x64 assembly
• mov

• mov imm/reg/mem value to reg/mem

• mov A,B (move B to A)

• A 與 B 的 size 要相等

• ex :

• mov rax,rbx (o)

• mov rax,bx (x)

• mov rax,0xdeadbeef
57
x64 assembly
• add/sub/or/xor/and

• add/sub/or/xor/and reg,imm/reg

• add/sub/or/xor/and A,B

• A 與 B 的 size ⼀一樣要相等

• ex :

• add rbp,0x48

• sub rax,rbx
58
x64 assembly
• push/pop

• push/pop reg

• ex :

• push rax = sub rsp,8 ; mov [rsp],rax

• pop rbx = mov rbx,[rsp] ; add rsp,8
59
x64 assembly
• lea

• ex :

• lea rax, [rsp+8]
60
x64 assembly
• lea v.s. mov

• lea rax, [rsp+8] v.s mov rax,[rsp+8]

• assume 

• rax = 3 

• rsp+8 = 0x7fffffffe4c0

• [rsp+8] = 0xdeadbeef
rax = 0x7fffffffe4c0
rax = 0xdeadbeef
lea
mov
61
x64 assembly
• jmp/call/ret

• jmp 跳⾄至程式碼的某處去執⾏行行

• call rax = push 下⼀一⾏行行指令位置 ;jmp rax

• ret = pop rip
62
x64 assembly
• leave

• mov rsp,rbp

• pop rbp
63
x64 assembly
• nop

• ⼀一個 byte 不做任何事

• opcode = 0x90
64
• System call

• Instruction : syscall

• SYSCALL NUMBER: RAX

• Argument : RDI RSI RDX R10 R8 R9

• Return value : RAX
x64 assembly
65
x64 assembly
• system call table
• https://w3challs.com/syscalls/?arch=x86_64
66
x64 assembly
• Calling convention

• function call

• call : push return address to stack then jump

• function return

• ret : pop return address

• function argument

• 基本上⽤用 register 傳遞

• 依序為 rdi rsi rdx rcx r8 r9

• 依序放到 register,再去執⾏行行 function call
67
x64 assembly
• Calling convention

• function prologue

• compiler 在 function 開頭加的指令,主要在保存 rbp 分配區域變數所
需空間
push rbp
mov rbp,rsp
sub rsp,0x30
68
x64 assembly
• Calling convention

• function epilogue

• compiler 在 function 結尾加的指令,主要在利利⽤用保存的 rbp 恢復 call
function 時的 stack 狀狀態
leave
ret
69
x64 assembly
• Calling convention

• call foo(0x1337,0xdeadbee)
0x1000 mov rsi,0xdeadbee
0x100a mov rdi,0x1337
0x1014 call foo()
0x101d mov rbx,rax
…
rsp
high
low
foo() :
push rbp
mov rbp,rsp
…
leave
ret
rbp
rdi
rsi
0
0
Stack
70
x64 assembly
• Calling convention

• call foo(0x1337,0xdeadbee)
0x1000 mov rsi,0xdeadbee
0x100a mov rdi,0x1337
0x1014 call foo()
0x101d mov rbx,rax
…
rsp
high
low
foo() :
push rbp
mov rbp,rsp
…
leave
ret
rbp
rdi
rsi
0
0xdeadbee
Stack
71
x64 assembly
• Calling convention

• call foo(0x1337,0xdeadbee)
0x1000 mov rsi,0xdeadbee
0x100a mov rdi,0x1337
0x1014 call foo()
0x101d mov rbx,rax
…
rsp
high
low
foo() :
push rbp
mov rbp,rsp
…
leave
ret
rbp
rdi
rsi
0x1337
0xdeadbee
Stack
72
x64 assembly
• Calling convention

• call foo(0x1337,0xdeadbee)
0x1000 mov rsi,0xdeadbee
0x100a mov rdi,0x1337
0x1014 call foo()
0x101d mov rbx,rax
…
0x101d
rsp
high
low
foo() :
push rbp
mov rbp,rsp
…
leave
ret
rbp
rdi
rsi
0x1337
0xdeedbee
Stack
73
x64 assembly
• Calling convention

• call foo(0x1337,0xdeadbee)
0x1000 mov rsi,0xdeadbee
0x100a mov rdi,0x1337
0x1014 call foo()
0x101d mov rbx,rax
…
0x101d
old rbp
rsp
high
low
foo() :
push rbp
mov rbp,rsp
…
leave
ret
rbp
rdi
rsi
0x1337
0xdeadbee
Stack
74
x64 assembly
• Calling convention

• call foo(0x1337,0xdeadbee)
0x1000 mov rsi,0xdeadbee
0x100a mov rdi,0x1337
0x1014 call foo()
0x101d mov rbx,rax
…
0x101d
old rbp
rbp/rsp
high
low
foo() :
push rbp
mov rbp,rsp
…
leave
ret
rdi
rsi
0x1337
0xdeadbee
Stack
75
x64 assembly
• Calling convention

• call foo(0x1337,0xdeadbee)
0x1000 mov rsi,0xdeadbee
0x100a mov rdi,0x1337
0x1014 call foo()
0x101d mov rbx,rax
…
0x101d
old rbp
rbp
high
low
foo() :
push rbp
mov rbp,rsp
…
leave
ret
rdi
rsi
0x1337
0xdeadbee
Stack
rsp
76
x64 assembly
• Calling convention

• call foo(0x1337,0xdeadbee)
0x1000 mov rsi,0xdeadbee
0x100a mov rdi,0x1337
0x1014 call foo()
0x101d mov rbx,rax
…
0x101d
old rbp
rbp
high
low
foo() :
push rbp
mov rbp,rsp
…
mov rsp,rbp
pop rbp
ret
rdi
rsi
0x1337
0xdeadbee
Stack
rsp
77
x64 assembly
• Calling convention

• call foo(0x1337,0xdeadbee)
0x1000 mov rsi,0xdeadbee
0x100a mov rdi,0x1337
0x1014 call foo()
0x101d mov rbx,rax
…
0x101d
old rbp
rsp/rbp
high
low
foo() :
push rbp
mov rbp,rsp
…
mov rsp,rbp
pop rbp
ret
rdi
rsi
0x1337
0xdeadbee
Stack
78
x64 assembly
• Calling convention

• call foo(0x1337,0xdeadbee)
0x1000 mov rsi,0xdeadbee
0x100a mov rdi,0x1337
0x1014 call foo()
0x101d mov rbx,rax
…
0x101d
old rbp
rsp
high
low
foo() :
push rbp
mov rbp,rsp
…
mov rsp,rbp
pop rbp
ret
rdi
rsi
0x1337
0xdeadbee
Stack
rbp
79
x64 assembly
• Calling convention

• call foo(0x1337,0xdeadbee)
0x1000 mov rsi,0xdeadbee
0x100a mov rdi,0x1337
0x1014 call foo()
0x101d mov rbx,rax
…
0x101d
old rbp
rsp
high
low
foo() :
push rbp
mov rbp,rsp
…
mov rsp,rbp
pop rbp
ret
rdi
rsi
0x1337
0xdeadbee
Stack
rbp
80
x64 assembly
• Hello world

• nasm -felf64 hello.s -o hello.o

• ld -m elf_x86_64 hello.o -o hello
81
x64 assembly
• Shellcode

• 顧名思義,攻擊者主要注入程式碼後的⽬目的為拿到 shell ,故稱 shellcode

• 由⼀一系列列的 machine code 組成,最後⽬目的可做任何攻擊者想做的事
82
• Hello world shellcode
x64 assembly
shellcode[] = “x48x31xc0x48x31xdbx48x31xc9x48x31xd2xebx17…….x7xx6cx64”
83
x64 assembly
• 產⽣生 shellcode

• objcopy -O binary hello.bin shellcode.bin

• xxd -i shellcode.bin
84
x64 assembly
• Using Pwntool

• http://docs.pwntools.com/en/stable/asm.html

• Pwntool bunutils

• http://docs.pwntools.com/en/stable/install/binutils.html
85
x64 assembly
• pwn.asm
86
x64 assembly
• Test your shellcode

• gcc -z execstack test.c -o test
87
x64 assembly
• How to debug your shellcode

• gdb ./test
88
Practice
• orw64 

• open/read/write shellcode

• man 2 “system call”
89
Buffer Overflow
• Buffer Overflow

• Return to Text / Shellcode

• Protection

• Lazy binding

• Return to Library

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

• 依照 buffer 位置可分為

• stack base 

• ⼜又稱為 stack smashing

• data base 

• heap base
91
Buffer Overflow
92
Buffer Overflow
• Vulnerable Function

• gets

• scanf

• strcpy

• sprintf

• memcpy

• strcat

• …
93
• memory layout
Stack Overflow
return address
rbp
rbp/rsp
char buf[0x20]
read(0,buf,100)
leave
ret
high
low
94
• memory layout
Stack Overflow
return address
rbp
rbp/rsp
char buf[0x20]
read(0,buf,100)
leave
ret
high
low
95
• memory layout
Stack Overflow
return address
rbp
rbp
char buf[0x20]
read(0,buf,100)
leave
ret
high
low
rsp
buf[0x20]
96
• 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]
97
• 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]
98
• 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]
99
• 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]
100
• 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
101
Stack Overflow
• 驗證
102
Stack Overflow
• 使⽤用 gdb 觀察
103
Stack Overflow
• From crash to exploit

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

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

• EX : 

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

• Overwrite the the return address

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

• e.g. 

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

• p64(0x400646) # in pwntools
105
Return to Text
• 控制 eip 後跳到原本程式中的程式碼

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

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

• Locate the return address

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

• pwntool cyclic

• gdb-peda pattc
108
Return to Text
• Exploitation

• Write exploit

• echo -ne
“aaaaaaaabbbbbbbbccccccccddddddddeeeeeeex46x60x40x00x
00x00x00x00” > exp

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

• Write exploit
110
Return to Text
• Exploitation

• Debug exploit

• gdb$ r < exp
111
Return to Text
• Exploitation

• Debug exploit

• Use attach more would be easier
112
Practice
• bofe4sy

• Just overwrite return address
113
Return to Shellcode
• 如果在 data 段上是可執⾏行行且位置固定的話,我們也可以先在 data 段上塞入
shellcode 跳過去
114
Lab 2
• ret2sc

• Just overwrite return address and jump to shellcode
115
Protection
• ASLR

• DEP

• PIE

• StackGuard
116
Protection
• ASLR

• 記憶體位置隨機變化

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

• 查看是否有開啟 ASLR

• cat /proc/sys/kernel/randomize_va_space
117
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
118
Protection
• ASLR

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

• ⼜又稱 NX

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

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

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

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

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

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

• 該值⼜又稱 canary

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

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

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

• x86 : gs

• x64 : fs

• 因此程式在取 canary 值時都會直接以 fs/gs 做存取
125
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
126
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
127
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
128
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
129
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
130
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
131
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
132
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
133
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
134
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
135
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
136
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 !
137
Protection
• StackGuard
138
Lazy binding
• Dynamic linking 的程式在執⾏行行過程中,有些 library 的函式可能到結束都不
會執⾏行行到

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

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

• .got

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

• .got.plt

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

• 前三項有特別⽤用途

• address of .dynamic

• link_map

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

• dl_runtime_resolve

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

• 後⾯面則是程式中 .so 函式引⽤用位置
143
Global Offset Table
• layout
.dynamic
.got
.got.plt
.data
addr of .dynamic
link_map
dl_resolve
printf
put
…
144
.
.
.
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
145
.
.
.
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)
146
.
.
.
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)
147
.
.
.
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)
148
.
.
.
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)
149
.
.
.
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)
150
.
.
.
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)
151
.
.
.
call foo@plt
…
.text
printf
foo@plt+6
bar
…
..
..
call _fix_up
..
..
ret 0xc
dl_resolve
Lazy binding
.got.plt (GOT)
152
.
.
.
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)
153
.
.
.
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)
154
• 第⼆二次 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)
155
• 第⼆二次 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)
156
How to find the GOT
• objdump -R elf or readelf -r elf
157
• 為了了實作 Lazy binding 的機制 GOT 位置必須是可寫入的

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

• 也就是控制 RIP
GOT Hijacking
158
• 第⼆二次 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
159
• 第⼆二次 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
160
• 第⼆二次 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
161
• 第⼆二次 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 :)
162
RELRO
• 分成三種

• Disabled

• .got/.got.plt 都可寫

• Partial (default)

• .got 唯獨

• Fulled

• RELRO 保護下,會在 load time 時將全部 function resolve 完畢
163
Return to Library
• 在⼀一般正常情況下程式中很難會有 system 等,可以直接獲得 shell 的
function

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

• system

• execve

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

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

• GOT

• Stack 上的殘留留值

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

• heap 上的殘留留值

• free 完之後在 malloc,也不會將 heap 存的內容清空
167
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
168
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)
169
Return to Library
• 在獲得 system 位置之後,我們可以複寫 return address 跳到 system 上,
這邊要注意的是參參數也要⼀一起放上,

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

• 可利利⽤用 pop rdi ; ret 的⽅方式將參參數放到 rdi
170
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
171
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
172
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
173
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”)
174
Return to Library
• 補充:

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

• system 參參數只要 “sh” 即可,因此也可以考慮只找 “sh” 字串串
175
Lab 3
• r3t2lib
176
ROP
• 透過 ret 去執⾏行行其他包含 ret 的程式碼片段

• 這些片段⼜又稱為 gadget
177
ROP
• Why do we need ROP ?

• Bypass DEP

• Static linking can do more thing
178
ROP
• ROP chain

• 在夠長的 buffer overflow 後 stack 內容幾乎都由我們控制,我們可以藉由
ret = pop rip 指令,持續的控制 rip
gadget2
1
gadget1
high
low
rsp
retoverflow
pop rax
ret
syscall
gadget1
gadget2
179
ROP
• ROP chain

• 在夠長的 buffer overflow 後 stack 內容幾乎都由我們控制,我們可以藉由
ret = pop rip 指令,持續的控制 rip
gadget2
60
gadget1
high
low
rsp
retoverflow
pop rax
ret
syscall
gadget1
gadget2
180
ROP
• ROP chain

• 在夠長的 buffer overflow 後 stack 內容幾乎都由我們控制,我們可以藉由
ret = pop rip 指令,持續的控制 rip
gadget2
60
gadget1
high
low
rsp
retoverflow
pop rax
ret
syscall
gadget1
gadget2
181
ROP
• ROP chain

• 在夠長的 buffer overflow 後 stack 內容幾乎都由我們控制,我們可以藉由
ret = pop rip 指令,持續的控制 rip
gadget2
60
gadget1
high
low
rsp
retoverflow
pop rax
ret
syscall
gadget1
gadget2
182
ROP
• ROP chain

• 在夠長的 buffer overflow 後 stack 內容幾乎都由我們控制,我們可以藉由
ret = pop rip 指令,持續的控制 rip
gadget2
1
gadget1
high
low
rsp
retoverflow
pop rax
ret
syscall
gadget1
gadget2
exit
183
ROP
• ROP chain

• 由眾多的 ROP gadget 組成

• 藉由不同的 register 及記憶體操作,呼叫 system call 達成任意代碼執⾏行行

• 基本上就是利利⽤用 ROP gadget 來來串串出我們之前寫的 shellcode 的效果
184
ROP
• Gadget 

• read/write register/memory

• pop rax;pop rcx ; ret

• mov [rax],rcx ; ret

• system call

• syscall

• change rsp

• pop rsp ; ret

• leave ; ret
185
ROP
• Write to Register

• pop reg ; ret

• mov reg, reg ; ret

• …
186
ROP
• Write to Register

• let rax = 0xdead rbx = 0xbeef
0x401041
0xdead
0x4010fb
high
low
rsp
pop rax
ret
0x4010fb
0xbeef
pop rbx
ret
0x401041
0 0
retoverflow
rax rbx
187
ROP
• Write to Register

• let rax = 0xdead rbx = 0xbeef
0x401041
0xdead
0x4010fb
high
low
rsp
pop rax
ret
0x4010fb
0xbeef
pop rbx
ret
0x401041
0 0
retoverflow
rax rbx
188
ROP
• Write to Register

• let rax = 0xdead rbx = 0xbeef
0x401041
0xdead
0x4010fb
high
low
rsppop rax
ret
0x4010fb
0xbeef
pop rbx
ret
0x401041
0xdead 0
retoverflow
rax rbx
189
ROP
• Write to Register

• let rax = 0xdead rbx = 0xbeef
0x401041
0xdead
0x4010fb
high
low
rsp
pop rax
ret
0x4010fb
0xbeef
pop rbx
ret
0x401041
0xdead 0
retoverflow
rax rbx
190
ROP
• Write to Register

• let rax = 0xdead rbx = 0xbeef
0x401041
0xdead
0x4010fb
high
low
rsp
pop rax
ret
0x4010fb
0xbeef
pop rbx
ret
0x401041
0xdead 0xbeef
retoverflow
rax rbx
191
ROP
• Write to Memory

• mov [reg],reg

• mov [reg+xx], reg

• …
192
ROP
• Write to Memory

• let *0x602080 = 0xdeadbeef
0x4010d1
0xdeadbeef
0x40108a
high
low
rsp
pop rax
pop rbx
ret
0x40108a
0xbeef
mov [rax],rbx
ret
0x4010d1
0 0
rax rbx
0x602080
0
0x602080
retoverflow
193
ROP
• Write to Memory

• let *0x602080 = 0xdeadbeef
0x4010d1
0xdeadbeef
0x40108a
high
low
rsp
pop rax
pop rbx
ret
0x40108a
0xbeef
mov [rax],rbx
ret
0x4010d1
0 0
rax rbx
0x602080
0
0x602080
retoverflow
194
ROP
• Write to Memory

• let *0x602080 = 0xdeadbeef
0x4010d1
0xdeadbeef
0x40108a
high
low
rsp
pop rax
pop rbx
ret
0x40108a
0xbeef
mov [rax],rbx
ret
0x4010d1
0x602080 0
rax rbx
0x602080
0
0x602080
retoverflow
195
ROP
• Write to Memory

• let *0x602080 = 0xdeadbeef
0x4010d1
0xdeadbeef
0x40108a
high
low
rsp
pop rax
pop rbx
ret
0x40108a
0xbeef
mov [rax],rbx
ret
0x4010d1
0x602080 0xdeadbeef
rax rbx
0x602080
0
0x602080
retoverflow
196
ROP
• Write to Memory

• let *0x602080 = 0xdeadbeef
0x4010d1
0xdeadbeef
0x40108a
high
low
rsp
pop rax
pop rbx
ret
0x40108a
0xbeef
mov [rax],rbx
ret
0x4010d1
0x602080 0xdeadbeef
rax rbx
0x602080
0
0x602080
retoverflow
197
ROP
• Write to Memory

• let *0x602080 = 0xdeadbeef
0x4010d1
0xdeadbeef
0x40108a
high
low
rsp
pop rax
pop rbx
ret
0x40108a
0xbeef
mov [rax],rbx
ret
0x4010d1
0x602080 0xdeadbeef
rax rbx
0x602080
0xdeadbeef
0x602080
retoverflow
198
ROP
• execve(“/bin/sh”,NULL,NULL)

• write to memory

• 將 “/bin/sh” 寫入已知位置記憶體中

• 可分多次將所需字串串寫入記憶體中
/bin/das
0x602080 0x602088
hx00x00x00…
199
ROP
• execve(“/bin/sh”,NULL,NULL)

• write to register

• rax = 0x3b , rdi = address of “/bin/sh”

• rsi = 0 , rdx = 0

• syscall
200
ROP
• find gadget

• https://github.com/JonathanSalwan/ROPgadget
201
ROP
• find gadget

• ROPgadget - - binary binary

• ROPgadget - - ropchain - - binary binary

• 在 Static linking 通常可以組成功 execve 的 rop chain 但通常都很長,
需要⾃自⼰己找更更短的 gadget 來來改短⼀一點
202
Lab 4
• simplerop_revenge
203
Using ROP bypass ASLR
• 假設 dynamic 編譯的程式中有 Buffer Overflow 的漏洞洞且在沒 PIE 情況下 (
先不考慮 StackGuard 的情況)

• How to bypass ASLR and DEP ?

• Use .plt section to leak some information

• ret2plt

• 通常⼀一般的程式中都會有 put 、 send 、write 等 output function
204
Using ROP bypass ASLR
ret
code stack
high
low
rsp
205
put@plt
pop rdi
put@GOT
pop rdi
0
pop rsi
puts@GOT
……
0
rdi
0
rsi
0
rdx
Using ROP bypass ASLR
ret
pop rdi

ret
code stack
high
low
rsp
206
put@plt
pop rdi
put@GOT
pop rdi
0
pop rsi
puts@GOT
……
0
rdi
0
rsi
0
rdx
Using ROP bypass ASLR
ret
pop rdi

ret
code stack
high
low
rsp
207
put@plt
pop rdi
put@GOT
pop rdi
0
pop rsi
puts@GOT
……
put@GOT
rdi
0
rsi
0
rdx
Using ROP bypass ASLR
ret
pop rdi

ret
put@plt
code stack
high
low
rsp
208
put@plt
pop rdi
put@GOT
pop rdi
0
pop rsi
puts@GOT
……
put@GOT
rdi
0
rsi
0
rdx
Using ROP bypass ASLR
ret
pop rdi

ret
jmp *(put@GOT)
code stack
high
low
rsp
209
put@plt
pop rdi
put@GOT
pop rdi
0
pop rsi
puts@GOT
……
put@GOT
rdi
0
rsi
0
rdx
Using ROP bypass ASLR
ret
pop rdi

ret
jmp put(put@GOT)
code stack
high
low
rsp
210
put@plt
pop rdi
put@GOT
pop rdi
0
pop rsi
puts@GOT
……
put@GOT
rdi
0
rsi
0
rdx
Using ROP bypass ASLR
ret
pop rdi

ret
jmp put(put@GOT)
code stack
high
low
rsp
211
put@plt
pop rdi
put@GOT
pop rdi
0
pop rsi
puts@GOT
……
put@GOT
rdi
0
rsi
0
rdx
Information leak
Using ROP bypass ASLR
ret
pop rdi

ret
jmp put(put@GOT)
ret
code stack
high
low
rsp
212
put@plt
pop rdi
put@GOT
pop rdi
0
pop rsi
puts@GOT
……
put@GOT
rdi
0
rsi
0
rdx
Using ROP bypass ASLR
ret
pop rdi

ret
jmp put(put@GOT)
ret
pop rdi
ret
code stack
high
low
rsp
213
put@plt
pop rdi
put@GOT
pop rdi
0
pop rsi
puts@GOT
……
put@GOT
rdi
0
rsi
0
rdx
Using ROP bypass ASLR
ret
pop rdi

ret
jmp put(put@GOT)
ret
pop rdi
ret
code stack
high
low
rsp
214
put@plt
pop rdi
put@GOT
pop rdi
0
pop rsi
puts@GOT
……
0
rdi
0
rsi
0
rdx
Using ROP bypass ASLR
ret
pop rdi

ret
jmp put(put@GOT)
ret
pop rdi
ret
pop rsi
ret
code stack
high
low
rsp
215
put@plt
pop rdi
put@GOT
pop rdi
0
pop rsi
puts@GOT
……
0
rdi
0
rsi
0
rdx
Using ROP bypass ASLR
ret
pop rdi

ret
jmp put(put@GOT)
ret
pop rdi
ret
pop rsi
ret
code stack
high
low
rsp
216
puts@GOT
0
rdi
puts@GOT
rsi
0
rdx
pop rdx
read@plt
pop rdi
Address of /bin/sh
puts@plt
0x8
Using ROP bypass ASLR
ret
pop rdx
ret
code stack
high
low
rsp
217
puts@GOT
0
rdi
puts@GOT
rsi
0
rdx
pop rdx
read@plt
pop rdi
Address of /bin/sh
puts@plt
0x8
Using ROP bypass ASLR
ret
pop rdx
ret
code stack
high
low
rsp
218
puts@GOT
0
rdi
puts@GOT
rsi
8
rdx
pop rdx
read@plt
pop rdi
Address of /bin/sh
puts@plt
0x8
Using ROP bypass ASLR
ret
pop rdx
ret
jmp read@plt
code stack
high
low
rsp
219
puts@GOT
0
rdi
puts@GOT
rsi
8
rdx
pop rdx
read@plt
pop rdi
Address of /bin/sh
puts@plt
0x8
Using ROP bypass ASLR
ret
pop rdx
ret
jmp read(0,put@GOT,8)
code stack
high
low
220
puts@GOT
0
rdi
puts@GOT
rsi
8
rdx
pop rdx
read@plt
pop rdi
Address of /bin/sh
puts@plt
0x8
rsp
rsp
Using ROP bypass ASLR
ret
pop rdx
ret
jmp read(0,put@GOT,8)
code stack
high
low
rsp
221
puts@GOT
0
rdi
puts@GOT
rsi
8
rdx
pop rdx
read@plt
pop rdi
Address of /bin/sh
puts@plt
0x8
GOT Hijacking
puts -> system
Using ROP bypass ASLR
ret
pop rdx
ret
jmp read(0,put@GOT,8)
ret
code stack
high
low
222
puts@GOT
0
rdi
puts@GOT
rsi
8
rdx
pop rdx
read@plt
pop rdi
Address of /bin/sh
puts@plt
0x8
rsp
Using ROP bypass ASLR
ret
pop rdx
ret
jmp read(0,put@GOT,8)
ret
pop rdi
ret
code stack
high
low
223
puts@GOT
0
rdi
puts@GOT
rsi
8
rdx
pop rdx
read@plt
pop rdi
Address of /bin/sh
puts@plt
0x8
rsp
Using ROP bypass ASLR
ret
pop rdx
ret
jmp read(0,put@GOT,8)
ret
pop rdi
ret
code stack
high
low
224
puts@GOT
&/bin/sh
rdi
puts@GOT
rsi
8
rdx
pop rdx
read@plt
pop rdi
Address of /bin/sh
puts@plt
0x8
rsp
Using ROP bypass ASLR
ret
pop rdx
ret
jmp read(0,put@GOT,8)
ret
pop rdi
ret
jmp puts@plt
code stack
high
low
225
puts@GOT
&/bin/sh
rdi
puts@GOT
rsi
8
rdx
pop rdx
read@plt
pop rdi
Address of /bin/sh
puts@plt
0x8
rsp
Using ROP bypass ASLR
ret
pop rdx
ret
jmp read(0,put@GOT,8)
ret
pop rdi
ret
jmp *(puts@GOT)
code stack
high
low
226
puts@GOT
&/bin/sh
rdi
puts@GOT
rsi
8
rdx
pop rdx
read@plt
pop rdi
Address of /bin/sh
puts@plt
0x8
rsp
Using ROP bypass ASLR
ret
pop rdx
ret
jmp read(0,put@GOT,8)
ret
pop rdi
ret
jmp system(“/bin/sh”)
code stack
high
low
227
puts@GOT
&/bin/sh
rdi
puts@GOT
rsi
8
rdx
pop rdx
read@plt
pop rdi
Address of /bin/sh
puts@plt
0x8
rsp
Using ROP bypass ASLR
ret
pop rdx
ret
jmp read(0,put@GOT,8)
ret
pop rdi
ret
jmp system(“/bin/sh”)
code stack
high
low
228
puts@GOT
&/bin/sh
rdi
puts@GOT
rsi
8
rdx
pop rdx
read@plt
pop rdi
Address of /bin/sh
puts@plt
0x8
rsp
GET SHELL
Using ROP bypass ASLR
229
• Bypass PIE

• 必須比平常多 leak ⼀一個 code 段的位置,藉由這個值算出 code base 進
⽽而推出所有 GOT 等資訊

• 有了了 code base 之後其他就跟沒有 PIE 的情況下⼀一樣
Using ROP bypass ASLR
230
• Bypass StackGuard

• canary 只有在 function return 時做檢查

• 只檢查 canary 值時否⼀一樣

• 所以可以先想辦法 leak 出 canary 的值,塞⼀一模⼀一樣的內容就可
bypass,或是想辦法不要改到 canary 也可以
Using ROP bypass ASLR
231
• Weakness in fork

• canary and memory mappings are same as parent.
LAB 5
232
• ret2plt
Reference
• Glibc cross reference 

• Linux Cross Reference

• 程式設計師的⾃自我修養
233
Q & A
234
Thank you for listening
Mail : angelboy@chroot.org
Blog : blog.angelboy.tw
235
Twitter : scwuaptx

Mais conteúdo relacionado

Mais procurados

ROP 輕鬆談
ROP 輕鬆談ROP 輕鬆談
ROP 輕鬆談hackstuff
 
Pwning in c++ (basic)
Pwning in c++ (basic)Pwning in c++ (basic)
Pwning in c++ (basic)Angel Boy
 
Play with FILE Structure - Yet Another Binary Exploit Technique
Play with FILE Structure - Yet Another Binary Exploit TechniquePlay with FILE Structure - Yet Another Binary Exploit Technique
Play with FILE Structure - Yet Another Binary Exploit TechniqueAngel Boy
 
Tcache Exploitation
Tcache ExploitationTcache Exploitation
Tcache ExploitationAngel Boy
 
台科逆向簡報
台科逆向簡報台科逆向簡報
台科逆向簡報耀德 蔡
 
TDOH x 台科 pwn課程
TDOH x 台科 pwn課程TDOH x 台科 pwn課程
TDOH x 台科 pwn課程Weber Tsai
 
Linux Binary Exploitation - Heap Exploitation
Linux Binary Exploitation - Heap Exploitation Linux Binary Exploitation - Heap Exploitation
Linux Binary Exploitation - Heap Exploitation Angel Boy
 
Windows 10 Nt Heap Exploitation (Chinese version)
Windows 10 Nt Heap Exploitation (Chinese version)Windows 10 Nt Heap Exploitation (Chinese version)
Windows 10 Nt Heap Exploitation (Chinese version)Angel Boy
 
NTUSTxTDOH - Pwn基礎 2015/12/27
NTUSTxTDOH - Pwn基礎 2015/12/27NTUSTxTDOH - Pwn基礎 2015/12/27
NTUSTxTDOH - Pwn基礎 2015/12/27Sheng-Hao Ma
 
Windows 10 Nt Heap Exploitation (English version)
Windows 10 Nt Heap Exploitation (English version)Windows 10 Nt Heap Exploitation (English version)
Windows 10 Nt Heap Exploitation (English version)Angel Boy
 
Dalvik仮想マシンのアーキテクチャ 改訂版
Dalvik仮想マシンのアーキテクチャ 改訂版Dalvik仮想マシンのアーキテクチャ 改訂版
Dalvik仮想マシンのアーキテクチャ 改訂版Takuya Matsunaga
 
AVX-512(フォーマット)詳解
AVX-512(フォーマット)詳解AVX-512(フォーマット)詳解
AVX-512(フォーマット)詳解MITSUNARI Shigeo
 
CTF for ビギナーズ バイナリ講習資料
CTF for ビギナーズ バイナリ講習資料CTF for ビギナーズ バイナリ講習資料
CTF for ビギナーズ バイナリ講習資料SECCON Beginners
 
How Functions Work
How Functions WorkHow Functions Work
How Functions WorkSaumil Shah
 
C++でできる!OS自作入門
C++でできる!OS自作入門C++でできる!OS自作入門
C++でできる!OS自作入門uchan_nos
 
ELFの動的リンク
ELFの動的リンクELFの動的リンク
ELFの動的リンク7shi
 
組み込み関数(intrinsic)によるSIMD入門
組み込み関数(intrinsic)によるSIMD入門組み込み関数(intrinsic)によるSIMD入門
組み込み関数(intrinsic)によるSIMD入門Norishige Fukushima
 
MacOS memory allocator (libmalloc) Exploitation
MacOS memory allocator (libmalloc) ExploitationMacOS memory allocator (libmalloc) Exploitation
MacOS memory allocator (libmalloc) ExploitationAngel Boy
 

Mais procurados (20)

ROP 輕鬆談
ROP 輕鬆談ROP 輕鬆談
ROP 輕鬆談
 
Pwning in c++ (basic)
Pwning in c++ (basic)Pwning in c++ (basic)
Pwning in c++ (basic)
 
Play with FILE Structure - Yet Another Binary Exploit Technique
Play with FILE Structure - Yet Another Binary Exploit TechniquePlay with FILE Structure - Yet Another Binary Exploit Technique
Play with FILE Structure - Yet Another Binary Exploit Technique
 
Tcache Exploitation
Tcache ExploitationTcache Exploitation
Tcache Exploitation
 
台科逆向簡報
台科逆向簡報台科逆向簡報
台科逆向簡報
 
TDOH x 台科 pwn課程
TDOH x 台科 pwn課程TDOH x 台科 pwn課程
TDOH x 台科 pwn課程
 
Linux Binary Exploitation - Heap Exploitation
Linux Binary Exploitation - Heap Exploitation Linux Binary Exploitation - Heap Exploitation
Linux Binary Exploitation - Heap Exploitation
 
Windows 10 Nt Heap Exploitation (Chinese version)
Windows 10 Nt Heap Exploitation (Chinese version)Windows 10 Nt Heap Exploitation (Chinese version)
Windows 10 Nt Heap Exploitation (Chinese version)
 
NTUSTxTDOH - Pwn基礎 2015/12/27
NTUSTxTDOH - Pwn基礎 2015/12/27NTUSTxTDOH - Pwn基礎 2015/12/27
NTUSTxTDOH - Pwn基礎 2015/12/27
 
Windows 10 Nt Heap Exploitation (English version)
Windows 10 Nt Heap Exploitation (English version)Windows 10 Nt Heap Exploitation (English version)
Windows 10 Nt Heap Exploitation (English version)
 
x86
x86x86
x86
 
Dalvik仮想マシンのアーキテクチャ 改訂版
Dalvik仮想マシンのアーキテクチャ 改訂版Dalvik仮想マシンのアーキテクチャ 改訂版
Dalvik仮想マシンのアーキテクチャ 改訂版
 
Glibc malloc internal
Glibc malloc internalGlibc malloc internal
Glibc malloc internal
 
AVX-512(フォーマット)詳解
AVX-512(フォーマット)詳解AVX-512(フォーマット)詳解
AVX-512(フォーマット)詳解
 
CTF for ビギナーズ バイナリ講習資料
CTF for ビギナーズ バイナリ講習資料CTF for ビギナーズ バイナリ講習資料
CTF for ビギナーズ バイナリ講習資料
 
How Functions Work
How Functions WorkHow Functions Work
How Functions Work
 
C++でできる!OS自作入門
C++でできる!OS自作入門C++でできる!OS自作入門
C++でできる!OS自作入門
 
ELFの動的リンク
ELFの動的リンクELFの動的リンク
ELFの動的リンク
 
組み込み関数(intrinsic)によるSIMD入門
組み込み関数(intrinsic)によるSIMD入門組み込み関数(intrinsic)によるSIMD入門
組み込み関数(intrinsic)によるSIMD入門
 
MacOS memory allocator (libmalloc) Exploitation
MacOS memory allocator (libmalloc) ExploitationMacOS memory allocator (libmalloc) Exploitation
MacOS memory allocator (libmalloc) Exploitation
 

Destaque

Bug hunting through_reverse_engineering
Bug hunting through_reverse_engineeringBug hunting through_reverse_engineering
Bug hunting through_reverse_engineeringarif
 
SECCON 2016 Online CTF [Memory Analysis] Write-Up (ver.korean)
SECCON 2016 Online CTF [Memory Analysis] Write-Up (ver.korean)SECCON 2016 Online CTF [Memory Analysis] Write-Up (ver.korean)
SECCON 2016 Online CTF [Memory Analysis] Write-Up (ver.korean)Sehan Lee
 
Introduction to Reverse Engineering
Introduction to Reverse EngineeringIntroduction to Reverse Engineering
Introduction to Reverse EngineeringGopinath Chintala
 
Reverse engineering
Reverse  engineeringReverse  engineering
Reverse engineeringYuffie Valen
 
Introduction to Reverse Engineering
Introduction to Reverse EngineeringIntroduction to Reverse Engineering
Introduction to Reverse EngineeringDobromir Enchev
 
Reverse Engineering
Reverse EngineeringReverse Engineering
Reverse Engineeringdswanson
 
Reverse engineering & its application
Reverse engineering & its applicationReverse engineering & its application
Reverse engineering & its applicationmapqrs
 
Reverse engineering
Reverse engineeringReverse engineering
Reverse engineeringananya0122
 
AI and Machine Learning Demystified by Carol Smith at Midwest UX 2017
AI and Machine Learning Demystified by Carol Smith at Midwest UX 2017AI and Machine Learning Demystified by Carol Smith at Midwest UX 2017
AI and Machine Learning Demystified by Carol Smith at Midwest UX 2017Carol Smith
 

Destaque (10)

Bug hunting through_reverse_engineering
Bug hunting through_reverse_engineeringBug hunting through_reverse_engineering
Bug hunting through_reverse_engineering
 
SECCON 2016 Online CTF [Memory Analysis] Write-Up (ver.korean)
SECCON 2016 Online CTF [Memory Analysis] Write-Up (ver.korean)SECCON 2016 Online CTF [Memory Analysis] Write-Up (ver.korean)
SECCON 2016 Online CTF [Memory Analysis] Write-Up (ver.korean)
 
Introduction to Reverse Engineering
Introduction to Reverse EngineeringIntroduction to Reverse Engineering
Introduction to Reverse Engineering
 
Reverse engineering
Reverse  engineeringReverse  engineering
Reverse engineering
 
Introduction to Reverse Engineering
Introduction to Reverse EngineeringIntroduction to Reverse Engineering
Introduction to Reverse Engineering
 
Reverse engineering
Reverse engineeringReverse engineering
Reverse engineering
 
Reverse Engineering
Reverse EngineeringReverse Engineering
Reverse Engineering
 
Reverse engineering & its application
Reverse engineering & its applicationReverse engineering & its application
Reverse engineering & its application
 
Reverse engineering
Reverse engineeringReverse engineering
Reverse engineering
 
AI and Machine Learning Demystified by Carol Smith at Midwest UX 2017
AI and Machine Learning Demystified by Carol Smith at Midwest UX 2017AI and Machine Learning Demystified by Carol Smith at Midwest UX 2017
AI and Machine Learning Demystified by Carol Smith at Midwest UX 2017
 

Semelhante a Binary exploitation - AIS3

Python 于 webgame 的应用
Python 于 webgame 的应用Python 于 webgame 的应用
Python 于 webgame 的应用勇浩 赖
 
常用Mac/Linux命令分享
常用Mac/Linux命令分享常用Mac/Linux命令分享
常用Mac/Linux命令分享Yihua Huang
 
Linux基础
Linux基础Linux基础
Linux基础zhuqling
 
COSCUP 2014 : open source compiler 戰國時代的軍備競賽
COSCUP 2014 : open source compiler 戰國時代的軍備競賽COSCUP 2014 : open source compiler 戰國時代的軍備競賽
COSCUP 2014 : open source compiler 戰國時代的軍備競賽Kito Cheng
 
Linux必备知识与Unix基础文化
Linux必备知识与Unix基础文化Linux必备知识与Unix基础文化
Linux必备知识与Unix基础文化Dahui Feng
 
[3]投影片 futurewad樹莓派研習會 141204
[3]投影片 futurewad樹莓派研習會 141204[3]投影片 futurewad樹莓派研習會 141204
[3]投影片 futurewad樹莓派研習會 141204CAVEDU Education
 
R統計軟體 -安裝與使用
R統計軟體 -安裝與使用R統計軟體 -安裝與使用
R統計軟體 -安裝與使用Person Lin
 
COSCUP 2016 - LLVM 由淺入淺
COSCUP 2016 - LLVM 由淺入淺COSCUP 2016 - LLVM 由淺入淺
COSCUP 2016 - LLVM 由淺入淺宗凡 楊
 
COSCUP2016 - LLVM框架、由淺入淺
COSCUP2016 - LLVM框架、由淺入淺COSCUP2016 - LLVM框架、由淺入淺
COSCUP2016 - LLVM框架、由淺入淺hydai
 
110824 knoss-windows系统机制浅析
110824 knoss-windows系统机制浅析110824 knoss-windows系统机制浅析
110824 knoss-windows系统机制浅析Zoom Quiet
 
該怎麼樣(認真的)部署你的 Python Web 應用程式?
該怎麼樣(認真的)部署你的 Python Web 應用程式?該怎麼樣(認真的)部署你的 Python Web 應用程式?
該怎麼樣(認真的)部署你的 Python Web 應用程式?Andy Dai
 
Elastic stack day-2
Elastic stack day-2Elastic stack day-2
Elastic stack day-2YI-CHING WU
 
Lambda's CNC @FabLab 10/27/14
Lambda's CNC @FabLab 10/27/14Lambda's CNC @FabLab 10/27/14
Lambda's CNC @FabLab 10/27/14宗凡 楊
 
Lambda's CNC @FabLab 10/27/14
Lambda's CNC @FabLab 10/27/14Lambda's CNC @FabLab 10/27/14
Lambda's CNC @FabLab 10/27/14宗凡 楊
 
⼤語⾔模型 LLM 應⽤開發入⾨
⼤語⾔模型 LLM 應⽤開發入⾨⼤語⾔模型 LLM 應⽤開發入⾨
⼤語⾔模型 LLM 應⽤開發入⾨Wen-Tien Chang
 
Docker 基礎介紹與實戰
Docker 基礎介紹與實戰Docker 基礎介紹與實戰
Docker 基礎介紹與實戰Bo-Yi Wu
 

Semelhante a Binary exploitation - AIS3 (20)

Python 于 webgame 的应用
Python 于 webgame 的应用Python 于 webgame 的应用
Python 于 webgame 的应用
 
常用Mac/Linux命令分享
常用Mac/Linux命令分享常用Mac/Linux命令分享
常用Mac/Linux命令分享
 
Linux基础
Linux基础Linux基础
Linux基础
 
COSCUP 2014 : open source compiler 戰國時代的軍備競賽
COSCUP 2014 : open source compiler 戰國時代的軍備競賽COSCUP 2014 : open source compiler 戰國時代的軍備競賽
COSCUP 2014 : open source compiler 戰國時代的軍備競賽
 
Linux必备知识与Unix基础文化
Linux必备知识与Unix基础文化Linux必备知识与Unix基础文化
Linux必备知识与Unix基础文化
 
[3]投影片 futurewad樹莓派研習會 141204
[3]投影片 futurewad樹莓派研習會 141204[3]投影片 futurewad樹莓派研習會 141204
[3]投影片 futurewad樹莓派研習會 141204
 
Rootkit 101
Rootkit 101Rootkit 101
Rootkit 101
 
R統計軟體 -安裝與使用
R統計軟體 -安裝與使用R統計軟體 -安裝與使用
R統計軟體 -安裝與使用
 
COSCUP 2016 - LLVM 由淺入淺
COSCUP 2016 - LLVM 由淺入淺COSCUP 2016 - LLVM 由淺入淺
COSCUP 2016 - LLVM 由淺入淺
 
COSCUP2016 - LLVM框架、由淺入淺
COSCUP2016 - LLVM框架、由淺入淺COSCUP2016 - LLVM框架、由淺入淺
COSCUP2016 - LLVM框架、由淺入淺
 
110824 knoss-windows系统机制浅析
110824 knoss-windows系统机制浅析110824 knoss-windows系统机制浅析
110824 knoss-windows系统机制浅析
 
該怎麼樣(認真的)部署你的 Python Web 應用程式?
該怎麼樣(認真的)部署你的 Python Web 應用程式?該怎麼樣(認真的)部署你的 Python Web 應用程式?
該怎麼樣(認真的)部署你的 Python Web 應用程式?
 
Elastic stack day-2
Elastic stack day-2Elastic stack day-2
Elastic stack day-2
 
Lambda's CNC @FabLab 10/27/14
Lambda's CNC @FabLab 10/27/14Lambda's CNC @FabLab 10/27/14
Lambda's CNC @FabLab 10/27/14
 
Cnc fablab
Cnc   fablabCnc   fablab
Cnc fablab
 
Lambda's CNC @FabLab 10/27/14
Lambda's CNC @FabLab 10/27/14Lambda's CNC @FabLab 10/27/14
Lambda's CNC @FabLab 10/27/14
 
Win dbg入门
Win dbg入门Win dbg入门
Win dbg入门
 
Windbg入门
Windbg入门Windbg入门
Windbg入门
 
⼤語⾔模型 LLM 應⽤開發入⾨
⼤語⾔模型 LLM 應⽤開發入⾨⼤語⾔模型 LLM 應⽤開發入⾨
⼤語⾔模型 LLM 應⽤開發入⾨
 
Docker 基礎介紹與實戰
Docker 基礎介紹與實戰Docker 基礎介紹與實戰
Docker 基礎介紹與實戰
 

Binary exploitation - AIS3

  • 2. About me • Angelboy • CTF player • WCTF / Boston Key Party 1st • DEFCON / HITB 2nd • Chroot / HITCON / 217 • Blog • blog.angelboy.tw 2
  • 3. Environment • Ubuntu 16.04 64 bit • binutils/nasm/ncat/gdb/pwntools/ropgadget/peda • 練習題 • http://ais3.pwnhub.tw • 懶懶⼈人包 • https://github.com/scwuaptx/AIS3-2017 • env_setup.sh 3
  • 4. Outline • Introduction • Section • Execution • x86 assembly • buffer overflow 4
  • 5. Introduction • Reverse Engineering • Exploitation • Useful Tool 5
  • 7. Reverse Engineering • Static Analysis • Analyze program without running • e.g. • objdump • Machine code to asm 7
  • 8. Reverse Engineering • Dynamic Analysis • Analyze program with running • e.g. • strace • trace all system call • ltrace • trace all library call 8
  • 10. Exploitation • Binary exploitation • 專指與 binary 相關的漏洞洞利利⽤用 • 兩兩⼤大主流 • 本地提權 • Remote code execution Vulnerability Control flow 10
  • 11. Useful Tool • IDA PRO - a static analysis tool 11
  • 12. Useful Tool • GDB - a dynamic analysis tool • The GNU Project Debugger 12
  • 13. Useful Tool • Basic command • run - 執⾏行行 • disas function name - 反組譯某個 function • break *0x400566 - 設斷點 • info breakpoint - 查看已設定哪些中斷點 • info register 查看所有 register 狀狀態 13
  • 14. Useful Tool • Basic command • x/wx address - 查看 address 中的內容 • w 可換成 b/h/g 分別是取 1/2/8 byte • / 後可接數字 表⽰示⼀一次列列出幾個 • 第⼆二個 x 可換成 u/d/s/i 以不同⽅方式表⽰示 • u : unsigned int • d : 10 進位 • s : 字串串 • i : 指令 14
  • 15. Useful Tool • Basic command • x/gx address 查看 address 中的內容 • e.g. 15
  • 16. Useful Tool • Basic command • ni - next instruction • si - step into • backtrace - 顯⽰示上層所有 stack frame 的資訊 • continue 16
  • 17. Useful Tool • Basic command • set *address=value • 將 address 中的值設成 value ⼀一次設 4 byte • 可將 * 換成 {char/short/long} 分別設定 1/2/8 byte • e.g. • set *0x602040=0xdeadbeef • set {int}0x602040=1337 17
  • 18. Useful Tool • Basic command • 在有 debug symbol 下 • list : 列列出 source code • b 可直接接⾏行行號斷點 • info local : 列列出區域變數 • print val : 印出變數 val 的值 18
  • 19. Useful Tool • Basic command • attach pid : attach ⼀一個正在運⾏行行的 process • 可以配合 ncat 進⾏行行 exploit 的 debug • ncat -ve ./a.out -kl 8888 • echo 0 > /proc/sys/kernel/yama/ptrace_scope 19
  • 20. Useful Tool • GDB - PEDA • Python Exploit Development Assistance for GDB • https://github.com/longld/peda • https://github.com/scwuaptx/peda 20
  • 21. GDB - PEDA • Screenshot 21
  • 22. GDB - PEDA • Some useful feature • checksec : Check for various security options of binary • elfsymbol : show elf .plt section • vmmap : show memory mapping • readelf : Get headers information from an ELF file • find/searchmem : Search for a pattern in memory • record : record every instruction at runtime 22
  • 23. GDB - PEDA • checksec • 查看 binary 中有哪些保護機制 23
  • 24. GDB - PEDA • elfsymbol • 查看 function .plt 做 ROP 時非常需要 24
  • 25. GDB - PEDA • vmmap • 查看 process mapping • 可觀察到每個 address 中的權限 25
  • 26. GDB - PEDA • readelf • 查看 section 位置 • 有些攻擊⼿手法會需要 • e.g. ret2dl_resolve 26
  • 27. GDB - PEDA • find (alias searchmem) • search memory 中的 patten • 通常拿來來找字串串 • e.g. /bin/sh 27
  • 28. GDB - PEDA • record • 記錄每個 instruction 讓 gdb 可回朔前⾯面的指令,在 PC 被改變後,可利利 ⽤用該功能,追回原本發⽣生問題的地⽅方 28
  • 29. Useful Tool • Pwntools • Exploit development library • python 29
  • 30. LAB 1 • sysm4gic • 利利⽤用 debugger 獲取 flag 30
  • 31. Outline • Introduction • Section • Execution • x86 assembbly 31
  • 32. Section • 在⼀一般情況下程式碼會分成 text、data 以及 bss 等 section ,並不會將 code 跟 data 混在⼀一起使⽤用 32
  • 33. Section • .text • 存放 code 的 section • .data • 存放有初始值的全域變數 • .bss • 存放沒有初始值的全域變數 • .rodata • 存放唯讀資料的 section 33
  • 35. Execution • Binary Format • Segment • Execution Flow 35
  • 36. Binary Format • 執⾏行行檔的格式會根據 OS 不同,⽽而有所不同 • Linux - ELF • Windows - PE • 在 Binary 的開頭會有個 magic number 欄欄位,⽅方便便讓 OS 辨認是屬於什什麼 樣類型的檔案 • 在 Linux 下可以使⽤用 file 來來檢視 36
  • 37. Segment • 在程式執⾏行行時期才會有的概念念,基本上會根據讀寫執⾏行行權限及特性來來分為數 個 segment • ⼀一般來來說可分為 rodata、data、code、stack、heap 等 segment • data : rw- • code : r-x • stack : rw- • heap : rw- 37
  • 38. Execution Flow • What happened when we execute an elf file ? • $ ./hello • 在⼀一般情況下程式會在 disk 中,⽽而 kernel 會通過⼀一連串串的過程來來將程式 mapping 到記憶體中去執⾏行行 38
  • 41. Execution Flow • How program maps to virtual memory. • 在 program header 中 • 記錄著哪些 segment 應該 mapping 到什什麼位置,以及該 segment 的讀寫 執⾏行行權限 • 記錄哪些 section 屬於哪些 segment • 當 program mapping 記憶體時會根據權限的不同來來分成好幾個 segment • ⼀一個 segment 可以包含 0 個到多個 section 41
  • 42. Execution Flow • How program maps to virtual memory. other section .data .bss .got.plt .rodata .text .init ELF Header In disk In memory kernel space CODE VMA DATA VMA HEAP STACK R or RX RW 0x400000 0x601000 0x602000 0x7fffffffe520 42
  • 43. Execution Flow • How program maps to virtual memory. • readelf -l binary • 查看 program header • readelf -S binary • 查看 section header • readelf -d binary • 查看 dynamic section 內容 43
  • 44. Execution Flow • How program maps to virtual memory. 權限 mapping 位置 segment 中有哪些 section 44
  • 45. Execution Flow • ld.so • 載入 elf 所需的 shared library • 這部分會記錄在 elf 中的 DT_NEED 中 • 初始化 GOT • 其他相關初始化的動作 • ex : 將 symbol table 合併到 global symbol table 等等 • 對實際運作過程有興趣可參參考 elf/rtld.c 45
  • 46. Execution Flow • 在 ld.so 執⾏行行完後會跳到 _start 開始執⾏行行主要程式 _start __libc_start_main .init main .fini exit 46
  • 47. Execution Flow • _start • 將下列列項⽬目傳給 libc_start_main • 環境變數起始位置 • main 的位置 (通常在第⼀一個參參數) • .init • 呼叫 main 之前的初始化⼯工作 • .fini • 程式結束前的收尾⼯工作 _start __libc_start_main 47
  • 48. Execution Flow • _libc_start_main • 執⾏行行 .init • 執⾏行行 main • 主程式部分 • 執⾏行行 .fini • 執⾏行行 exit 結束程式 48
  • 49. • Registers • General-purpose registers • RAX RBX RCX RDX RSI RDI- 64 bit • EAX EBX ECX EDX ESI EDI - 32 bit • AX BX CX DX SI DI - 16 bit x64 assembly ALAH EAX AX RAX 49
  • 50. • Registers • r8 r9 r10 r11 r12 r13 r14 r15 - 64 bit • r8d r9d r10d … - 32 bit • r8w r9w r10w … -16 bit • r8b r9b r10b … - 8 bit x64 assembly 50
  • 51. • Registers • Stack Pointer Register • RSP • Base Pointer Register • RBP • Program Counter Register • RIP x64 assembly 51
  • 52. x64 assembly • Registers • Stack Pointer • RSP - 64 bit • 指向 stack 頂端 • Base Pointer • RBP - 64 bit • 指向 stack 底端 • RSP 到 function 參參數範圍稱為該 function 的 Stack Frame … … … … variable return address rbp rbp rsp high low extra-arg 52
  • 53. x64 assembly • Registers • Stack Pointer • RSP - 64 bit • 指向 stack 頂端 • Base Pointer • RBP - 64 bit • 指向 stack 底端 • RSP 到 function 參參數範圍稱為該 function 的 Stack Frame high low … … … … variable return address rbp rbp rsp extra-arg stack frame 53
  • 54. x64 assembly • Registers • Program counter register • RIP • 指向⽬目前程式執⾏行行的位置 • Flag register • eflags • 儲存指令執⾏行行結果 • Segment register • cs ss ds es fs gs 54
  • 55. x64 assembly • AT & T • mov %rax,%rbx • Intel • mov rbx,rax 55
  • 56. x64 assembly • Basic instruction • mov • add/sub • and/or/xor • push/pop • lea • jmp/call/ret 56
  • 57. x64 assembly • mov • mov imm/reg/mem value to reg/mem • mov A,B (move B to A) • A 與 B 的 size 要相等 • ex : • mov rax,rbx (o) • mov rax,bx (x) • mov rax,0xdeadbeef 57
  • 58. x64 assembly • add/sub/or/xor/and • add/sub/or/xor/and reg,imm/reg • add/sub/or/xor/and A,B • A 與 B 的 size ⼀一樣要相等 • ex : • add rbp,0x48 • sub rax,rbx 58
  • 59. x64 assembly • push/pop • push/pop reg • ex : • push rax = sub rsp,8 ; mov [rsp],rax • pop rbx = mov rbx,[rsp] ; add rsp,8 59
  • 60. x64 assembly • lea • ex : • lea rax, [rsp+8] 60
  • 61. x64 assembly • lea v.s. mov • lea rax, [rsp+8] v.s mov rax,[rsp+8] • assume • rax = 3 • rsp+8 = 0x7fffffffe4c0 • [rsp+8] = 0xdeadbeef rax = 0x7fffffffe4c0 rax = 0xdeadbeef lea mov 61
  • 62. x64 assembly • jmp/call/ret • jmp 跳⾄至程式碼的某處去執⾏行行 • call rax = push 下⼀一⾏行行指令位置 ;jmp rax • ret = pop rip 62
  • 63. x64 assembly • leave • mov rsp,rbp • pop rbp 63
  • 64. x64 assembly • nop • ⼀一個 byte 不做任何事 • opcode = 0x90 64
  • 65. • System call • Instruction : syscall • SYSCALL NUMBER: RAX • Argument : RDI RSI RDX R10 R8 R9 • Return value : RAX x64 assembly 65
  • 66. x64 assembly • system call table • https://w3challs.com/syscalls/?arch=x86_64 66
  • 67. x64 assembly • Calling convention • function call • call : push return address to stack then jump • function return • ret : pop return address • function argument • 基本上⽤用 register 傳遞 • 依序為 rdi rsi rdx rcx r8 r9 • 依序放到 register,再去執⾏行行 function call 67
  • 68. x64 assembly • Calling convention • function prologue • compiler 在 function 開頭加的指令,主要在保存 rbp 分配區域變數所 需空間 push rbp mov rbp,rsp sub rsp,0x30 68
  • 69. x64 assembly • Calling convention • function epilogue • compiler 在 function 結尾加的指令,主要在利利⽤用保存的 rbp 恢復 call function 時的 stack 狀狀態 leave ret 69
  • 70. x64 assembly • Calling convention • call foo(0x1337,0xdeadbee) 0x1000 mov rsi,0xdeadbee 0x100a mov rdi,0x1337 0x1014 call foo() 0x101d mov rbx,rax … rsp high low foo() : push rbp mov rbp,rsp … leave ret rbp rdi rsi 0 0 Stack 70
  • 71. x64 assembly • Calling convention • call foo(0x1337,0xdeadbee) 0x1000 mov rsi,0xdeadbee 0x100a mov rdi,0x1337 0x1014 call foo() 0x101d mov rbx,rax … rsp high low foo() : push rbp mov rbp,rsp … leave ret rbp rdi rsi 0 0xdeadbee Stack 71
  • 72. x64 assembly • Calling convention • call foo(0x1337,0xdeadbee) 0x1000 mov rsi,0xdeadbee 0x100a mov rdi,0x1337 0x1014 call foo() 0x101d mov rbx,rax … rsp high low foo() : push rbp mov rbp,rsp … leave ret rbp rdi rsi 0x1337 0xdeadbee Stack 72
  • 73. x64 assembly • Calling convention • call foo(0x1337,0xdeadbee) 0x1000 mov rsi,0xdeadbee 0x100a mov rdi,0x1337 0x1014 call foo() 0x101d mov rbx,rax … 0x101d rsp high low foo() : push rbp mov rbp,rsp … leave ret rbp rdi rsi 0x1337 0xdeedbee Stack 73
  • 74. x64 assembly • Calling convention • call foo(0x1337,0xdeadbee) 0x1000 mov rsi,0xdeadbee 0x100a mov rdi,0x1337 0x1014 call foo() 0x101d mov rbx,rax … 0x101d old rbp rsp high low foo() : push rbp mov rbp,rsp … leave ret rbp rdi rsi 0x1337 0xdeadbee Stack 74
  • 75. x64 assembly • Calling convention • call foo(0x1337,0xdeadbee) 0x1000 mov rsi,0xdeadbee 0x100a mov rdi,0x1337 0x1014 call foo() 0x101d mov rbx,rax … 0x101d old rbp rbp/rsp high low foo() : push rbp mov rbp,rsp … leave ret rdi rsi 0x1337 0xdeadbee Stack 75
  • 76. x64 assembly • Calling convention • call foo(0x1337,0xdeadbee) 0x1000 mov rsi,0xdeadbee 0x100a mov rdi,0x1337 0x1014 call foo() 0x101d mov rbx,rax … 0x101d old rbp rbp high low foo() : push rbp mov rbp,rsp … leave ret rdi rsi 0x1337 0xdeadbee Stack rsp 76
  • 77. x64 assembly • Calling convention • call foo(0x1337,0xdeadbee) 0x1000 mov rsi,0xdeadbee 0x100a mov rdi,0x1337 0x1014 call foo() 0x101d mov rbx,rax … 0x101d old rbp rbp high low foo() : push rbp mov rbp,rsp … mov rsp,rbp pop rbp ret rdi rsi 0x1337 0xdeadbee Stack rsp 77
  • 78. x64 assembly • Calling convention • call foo(0x1337,0xdeadbee) 0x1000 mov rsi,0xdeadbee 0x100a mov rdi,0x1337 0x1014 call foo() 0x101d mov rbx,rax … 0x101d old rbp rsp/rbp high low foo() : push rbp mov rbp,rsp … mov rsp,rbp pop rbp ret rdi rsi 0x1337 0xdeadbee Stack 78
  • 79. x64 assembly • Calling convention • call foo(0x1337,0xdeadbee) 0x1000 mov rsi,0xdeadbee 0x100a mov rdi,0x1337 0x1014 call foo() 0x101d mov rbx,rax … 0x101d old rbp rsp high low foo() : push rbp mov rbp,rsp … mov rsp,rbp pop rbp ret rdi rsi 0x1337 0xdeadbee Stack rbp 79
  • 80. x64 assembly • Calling convention • call foo(0x1337,0xdeadbee) 0x1000 mov rsi,0xdeadbee 0x100a mov rdi,0x1337 0x1014 call foo() 0x101d mov rbx,rax … 0x101d old rbp rsp high low foo() : push rbp mov rbp,rsp … mov rsp,rbp pop rbp ret rdi rsi 0x1337 0xdeadbee Stack rbp 80
  • 81. x64 assembly • Hello world • nasm -felf64 hello.s -o hello.o • ld -m elf_x86_64 hello.o -o hello 81
  • 82. x64 assembly • Shellcode • 顧名思義,攻擊者主要注入程式碼後的⽬目的為拿到 shell ,故稱 shellcode • 由⼀一系列列的 machine code 組成,最後⽬目的可做任何攻擊者想做的事 82
  • 83. • Hello world shellcode x64 assembly shellcode[] = “x48x31xc0x48x31xdbx48x31xc9x48x31xd2xebx17…….x7xx6cx64” 83
  • 84. x64 assembly • 產⽣生 shellcode • objcopy -O binary hello.bin shellcode.bin • xxd -i shellcode.bin 84
  • 85. x64 assembly • Using Pwntool • http://docs.pwntools.com/en/stable/asm.html • Pwntool bunutils • http://docs.pwntools.com/en/stable/install/binutils.html 85
  • 87. x64 assembly • Test your shellcode • gcc -z execstack test.c -o test 87
  • 88. x64 assembly • How to debug your shellcode • gdb ./test 88
  • 89. Practice • orw64 • open/read/write shellcode • man 2 “system call” 89
  • 90. Buffer Overflow • Buffer Overflow • Return to Text / Shellcode • Protection • Lazy binding • Return to Library • Return-Oriented Programming 90
  • 91. Buffer Overflow • 程式設計師未對 buffer 做長度檢查,造成可以讓攻擊者輸入過長的字串串,覆 蓋記憶體上的其他資料,嚴重時更更可控制程式流程 • 依照 buffer 位置可分為 • stack base • ⼜又稱為 stack smashing • data base • heap base 91
  • 93. Buffer Overflow • Vulnerable Function • gets • scanf • strcpy • sprintf • memcpy • strcat • … 93
  • 94. • memory layout Stack Overflow return address rbp rbp/rsp char buf[0x20] read(0,buf,100) leave ret high low 94
  • 95. • memory layout Stack Overflow return address rbp rbp/rsp char buf[0x20] read(0,buf,100) leave ret high low 95
  • 96. • memory layout Stack Overflow return address rbp rbp char buf[0x20] read(0,buf,100) leave ret high low rsp buf[0x20] 96
  • 97. • 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] 97
  • 98. • 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] 98
  • 99. • 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] 99
  • 100. • 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] 100
  • 101. • 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 101
  • 103. Stack Overflow • 使⽤用 gdb 觀察 103
  • 104. Stack Overflow • From crash to exploit • 隨意任意輸入⼀一堆資料應該只能造成 crash • 需適當的構造資料,就可巧妙的控制程式流程 • EX : • 適當得構造 return address 就可在函數返回時,跳到攻擊者的程式碼 104
  • 105. Stack Overflow • From crash to exploit • Overwrite the the return address • 因 x86 底下是 little-endian 的,所以填入 address 時,需要反過來來填入 • e.g. • 假設要填入 0x00400646 就需要填入 x46x06x40x00x00x00x00x000 • p64(0x400646) # in pwntools 105
  • 106. Return to Text • 控制 eip 後跳到原本程式中的程式碼 • 以 bofeasy 範例例來來說,我們可以跳到 l33t 這個 function • 可以 objdump 來來找尋函式真正位置 106
  • 108. Return to Text • Exploitation • Locate the return address • 可⽤用 aaaaaaaabbbbbbbb…… 八個⼀一組的字來來定位 return address • pwntool cyclic • gdb-peda pattc 108
  • 109. Return to Text • Exploitation • Write exploit • echo -ne “aaaaaaaabbbbbbbbccccccccddddddddeeeeeeex46x60x40x00x 00x00x00x00” > exp • cat exp - | ./bofeasy 109
  • 110. Return to Text • Exploitation • Write exploit 110
  • 111. Return to Text • Exploitation • Debug exploit • gdb$ r < exp 111
  • 112. Return to Text • Exploitation • Debug exploit • Use attach more would be easier 112
  • 113. Practice • bofe4sy • Just overwrite return address 113
  • 114. Return to Shellcode • 如果在 data 段上是可執⾏行行且位置固定的話,我們也可以先在 data 段上塞入 shellcode 跳過去 114
  • 115. Lab 2 • ret2sc • Just overwrite return address and jump to shellcode 115
  • 116. Protection • ASLR • DEP • PIE • StackGuard 116
  • 117. Protection • ASLR • 記憶體位置隨機變化 • 每次執⾏行行程式時,stack 、heap、library 位置都不⼀一樣 • 查看是否有開啟 ASLR • cat /proc/sys/kernel/randomize_va_space 117
  • 118. 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 118
  • 119. Protection • ASLR • 使⽤用 ldd (可看執⾏行行時載入的 library 及其位置) 觀察 address 變化 119
  • 120. Protection • DEP • ⼜又稱 NX • 可寫的不可執⾏行行,可執⾏行行的不可寫 120
  • 122. Protection • PIE ( Position Independent Execution ) • gcc 在預設情況下不會開啟,編譯時加上 -fPIC -pie 就可以開啟 • 在沒開啟的情況下程式的 data 段及 code 段會是固定的 • ⼀一但開啟之後 data 及 code 也會跟著 ASLR ,因此前⾯面說的 ret2text/ shellcode 沒有固定位置可以跳,就變得困難許多 122
  • 123. • objdump 觀察 pie 開啟的 binary • code address 變成只剩下 offset 執⾏行行後會加上 code base 才是真正在記 憶體中的位置 Protection 123
  • 124. Protection • StackGuard • 在程式執⾏行行是隨機⽣生成⼀一亂數 function call 時會塞入 stack 中,在 function return 時會檢查是否該值有被更更動,⼀一旦發現被更更動就結束該程 式 • 該值⼜又稱 canary • 非常有效地阻擋了了 stack overflow 的攻擊 • ⽬目前預設情況下是開啟的 124
  • 125. Protection • StackGuard • canary 的值在執⾏行行期間都會先放在,⼀一個稱為 tls 的區段中的 tcbhead_t 結構中,⽽而在 x86/x64 架構下恆有⼀一個暫存器指向 tls 段的 tcbhead_t 結 構 • x86 : gs • x64 : fs • 因此程式在取 canary 值時都會直接以 fs/gs 做存取 125
  • 126. 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 126
  • 127. 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 127
  • 128. 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 128
  • 129. 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 129
  • 130. 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 130
  • 131. 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 131
  • 132. 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 132
  • 133. 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 133
  • 134. 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 134
  • 135. 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 135
  • 136. 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 136
  • 137. 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 ! 137
  • 139. Lazy binding • Dynamic linking 的程式在執⾏行行過程中,有些 library 的函式可能到結束都不 會執⾏行行到 • 所以 ELF 採取 Lazy binding 的機制,在第⼀一次 call library 函式時,才會去 尋找函式真正的位置進⾏行行 binding 139
  • 140. Global Offset Table • library 的位置再載入後才決定,因此無法在 compile 後,就知道 library 中 的 function 在哪,該跳去哪 • GOT 為⼀一個函式指標陣列列,儲存其他 library 中,function 的位置,但因 Lazy binding 的機制,並不會⼀一開始就把正確的位置填上,⽽而是填上⼀一段 plt 位置的 code 140
  • 141. Global Offset Table • 當執⾏行行到 library 的 function 時才會真正去尋找 function ,最後再把 GOT 中的位置填上真正 function 的位置 141
  • 142. Global Offset Table • 分成兩兩部分 • .got • 保存全域變數引⽤用位置 • .got.plt • 保存函式引⽤用位置 142
  • 143. Global Offset Table • .got.plt • 前三項有特別⽤用途 • address of .dynamic • link_map • ⼀一個將有引⽤用到的 library 所串串成的 linked list ,function resolve 時也會⽤用到 • dl_runtime_resolve • ⽤用來來找出函式位置的函式 • 後⾯面則是程式中 .so 函式引⽤用位置 143
  • 144. Global Offset Table • layout .dynamic .got .got.plt .data addr of .dynamic link_map dl_resolve printf put … 144
  • 145. . . . 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 145
  • 146. . . . 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) 146
  • 147. . . . 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) 147
  • 148. . . . 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) 148
  • 149. . . . 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) 149
  • 150. . . . 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) 150
  • 151. . . . 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) 151
  • 153. . . . 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) 153
  • 154. . . . 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) 154
  • 155. • 第⼆二次 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) 155
  • 156. • 第⼆二次 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) 156
  • 157. How to find the GOT • objdump -R elf or readelf -r elf 157
  • 158. • 為了了實作 Lazy binding 的機制 GOT 位置必須是可寫入的 • 如果程式有存在任意更更改位置的漏洞洞,便便可改寫 GOT ,造成程式流程的改 變 • 也就是控制 RIP GOT Hijacking 158
  • 159. • 第⼆二次 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 159
  • 160. • 第⼆二次 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 160
  • 161. • 第⼆二次 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 161
  • 162. • 第⼆二次 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 :) 162
  • 163. RELRO • 分成三種 • Disabled • .got/.got.plt 都可寫 • Partial (default) • .got 唯獨 • Fulled • RELRO 保護下,會在 load time 時將全部 function resolve 完畢 163
  • 164. Return to Library • 在⼀一般正常情況下程式中很難會有 system 等,可以直接獲得 shell 的 function • 在 DEP/NX 的保護下我們也無法直接填入 shellcode 去執⾏行行我們的程式碼 164
  • 165. Return to Library • ⽽而在 Dynamic Linking 情況下,⼤大部份程式都會載入 libc ,libc 中有非常多 好⽤用的 function 可以達成我們的⽬目的 • system • execve • … 165
  • 166. Return to Library • 但⼀一般情況下都會因為 ASLR 關係,導致每次 libc 載入位置不固定 • 所以我們通常都需要 information leak 的漏洞洞來來或取 libc 的 base address 進⽽而算出 system 等 function 位置,再將程式導過去 166
  • 167. Return to Library • 通常可以獲得 libc 位置的地⽅方 • GOT • Stack 上的殘留留值 • function return 後並不會將 stack 中的內容清除 • heap 上的殘留留值 • free 完之後在 malloc,也不會將 heap 存的內容清空 167
  • 168. 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 168
  • 169. 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) 169
  • 170. Return to Library • 在獲得 system 位置之後,我們可以複寫 return address 跳到 system 上, 這邊要注意的是參參數也要⼀一起放上, • 但在 x86-64 Linux 上傳遞參參數是⽤用 register 傳遞的,第⼀一個參參數會放在 rdi 所以我們必須想辦法將 /bin/sh 的位置放在 rdi 上 • 可利利⽤用 pop rdi ; ret 的⽅方式將參參數放到 rdi 170
  • 171. 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 171
  • 172. 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 172
  • 173. 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 173
  • 174. 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”) 174
  • 175. Return to Library • 補充: • “/bin/sh” 字串串位置也可以在 libc 中找到,因此當程式中沒有該字串串,可 從 libc 裡⾯面找 • system 參參數只要 “sh” 即可,因此也可以考慮只找 “sh” 字串串 175
  • 177. ROP • 透過 ret 去執⾏行行其他包含 ret 的程式碼片段 • 這些片段⼜又稱為 gadget 177
  • 178. ROP • Why do we need ROP ? • Bypass DEP • Static linking can do more thing 178
  • 179. ROP • ROP chain • 在夠長的 buffer overflow 後 stack 內容幾乎都由我們控制,我們可以藉由 ret = pop rip 指令,持續的控制 rip gadget2 1 gadget1 high low rsp retoverflow pop rax ret syscall gadget1 gadget2 179
  • 180. ROP • ROP chain • 在夠長的 buffer overflow 後 stack 內容幾乎都由我們控制,我們可以藉由 ret = pop rip 指令,持續的控制 rip gadget2 60 gadget1 high low rsp retoverflow pop rax ret syscall gadget1 gadget2 180
  • 181. ROP • ROP chain • 在夠長的 buffer overflow 後 stack 內容幾乎都由我們控制,我們可以藉由 ret = pop rip 指令,持續的控制 rip gadget2 60 gadget1 high low rsp retoverflow pop rax ret syscall gadget1 gadget2 181
  • 182. ROP • ROP chain • 在夠長的 buffer overflow 後 stack 內容幾乎都由我們控制,我們可以藉由 ret = pop rip 指令,持續的控制 rip gadget2 60 gadget1 high low rsp retoverflow pop rax ret syscall gadget1 gadget2 182
  • 183. ROP • ROP chain • 在夠長的 buffer overflow 後 stack 內容幾乎都由我們控制,我們可以藉由 ret = pop rip 指令,持續的控制 rip gadget2 1 gadget1 high low rsp retoverflow pop rax ret syscall gadget1 gadget2 exit 183
  • 184. ROP • ROP chain • 由眾多的 ROP gadget 組成 • 藉由不同的 register 及記憶體操作,呼叫 system call 達成任意代碼執⾏行行 • 基本上就是利利⽤用 ROP gadget 來來串串出我們之前寫的 shellcode 的效果 184
  • 185. ROP • Gadget • read/write register/memory • pop rax;pop rcx ; ret • mov [rax],rcx ; ret • system call • syscall • change rsp • pop rsp ; ret • leave ; ret 185
  • 186. ROP • Write to Register • pop reg ; ret • mov reg, reg ; ret • … 186
  • 187. ROP • Write to Register • let rax = 0xdead rbx = 0xbeef 0x401041 0xdead 0x4010fb high low rsp pop rax ret 0x4010fb 0xbeef pop rbx ret 0x401041 0 0 retoverflow rax rbx 187
  • 188. ROP • Write to Register • let rax = 0xdead rbx = 0xbeef 0x401041 0xdead 0x4010fb high low rsp pop rax ret 0x4010fb 0xbeef pop rbx ret 0x401041 0 0 retoverflow rax rbx 188
  • 189. ROP • Write to Register • let rax = 0xdead rbx = 0xbeef 0x401041 0xdead 0x4010fb high low rsppop rax ret 0x4010fb 0xbeef pop rbx ret 0x401041 0xdead 0 retoverflow rax rbx 189
  • 190. ROP • Write to Register • let rax = 0xdead rbx = 0xbeef 0x401041 0xdead 0x4010fb high low rsp pop rax ret 0x4010fb 0xbeef pop rbx ret 0x401041 0xdead 0 retoverflow rax rbx 190
  • 191. ROP • Write to Register • let rax = 0xdead rbx = 0xbeef 0x401041 0xdead 0x4010fb high low rsp pop rax ret 0x4010fb 0xbeef pop rbx ret 0x401041 0xdead 0xbeef retoverflow rax rbx 191
  • 192. ROP • Write to Memory • mov [reg],reg • mov [reg+xx], reg • … 192
  • 193. ROP • Write to Memory • let *0x602080 = 0xdeadbeef 0x4010d1 0xdeadbeef 0x40108a high low rsp pop rax pop rbx ret 0x40108a 0xbeef mov [rax],rbx ret 0x4010d1 0 0 rax rbx 0x602080 0 0x602080 retoverflow 193
  • 194. ROP • Write to Memory • let *0x602080 = 0xdeadbeef 0x4010d1 0xdeadbeef 0x40108a high low rsp pop rax pop rbx ret 0x40108a 0xbeef mov [rax],rbx ret 0x4010d1 0 0 rax rbx 0x602080 0 0x602080 retoverflow 194
  • 195. ROP • Write to Memory • let *0x602080 = 0xdeadbeef 0x4010d1 0xdeadbeef 0x40108a high low rsp pop rax pop rbx ret 0x40108a 0xbeef mov [rax],rbx ret 0x4010d1 0x602080 0 rax rbx 0x602080 0 0x602080 retoverflow 195
  • 196. ROP • Write to Memory • let *0x602080 = 0xdeadbeef 0x4010d1 0xdeadbeef 0x40108a high low rsp pop rax pop rbx ret 0x40108a 0xbeef mov [rax],rbx ret 0x4010d1 0x602080 0xdeadbeef rax rbx 0x602080 0 0x602080 retoverflow 196
  • 197. ROP • Write to Memory • let *0x602080 = 0xdeadbeef 0x4010d1 0xdeadbeef 0x40108a high low rsp pop rax pop rbx ret 0x40108a 0xbeef mov [rax],rbx ret 0x4010d1 0x602080 0xdeadbeef rax rbx 0x602080 0 0x602080 retoverflow 197
  • 198. ROP • Write to Memory • let *0x602080 = 0xdeadbeef 0x4010d1 0xdeadbeef 0x40108a high low rsp pop rax pop rbx ret 0x40108a 0xbeef mov [rax],rbx ret 0x4010d1 0x602080 0xdeadbeef rax rbx 0x602080 0xdeadbeef 0x602080 retoverflow 198
  • 199. ROP • execve(“/bin/sh”,NULL,NULL) • write to memory • 將 “/bin/sh” 寫入已知位置記憶體中 • 可分多次將所需字串串寫入記憶體中 /bin/das 0x602080 0x602088 hx00x00x00… 199
  • 200. ROP • execve(“/bin/sh”,NULL,NULL) • write to register • rax = 0x3b , rdi = address of “/bin/sh” • rsi = 0 , rdx = 0 • syscall 200
  • 201. ROP • find gadget • https://github.com/JonathanSalwan/ROPgadget 201
  • 202. ROP • find gadget • ROPgadget - - binary binary • ROPgadget - - ropchain - - binary binary • 在 Static linking 通常可以組成功 execve 的 rop chain 但通常都很長, 需要⾃自⼰己找更更短的 gadget 來來改短⼀一點 202
  • 204. Using ROP bypass ASLR • 假設 dynamic 編譯的程式中有 Buffer Overflow 的漏洞洞且在沒 PIE 情況下 ( 先不考慮 StackGuard 的情況) • How to bypass ASLR and DEP ? • Use .plt section to leak some information • ret2plt • 通常⼀一般的程式中都會有 put 、 send 、write 等 output function 204
  • 205. Using ROP bypass ASLR ret code stack high low rsp 205 put@plt pop rdi put@GOT pop rdi 0 pop rsi puts@GOT …… 0 rdi 0 rsi 0 rdx
  • 206. Using ROP bypass ASLR ret pop rdi
 ret code stack high low rsp 206 put@plt pop rdi put@GOT pop rdi 0 pop rsi puts@GOT …… 0 rdi 0 rsi 0 rdx
  • 207. Using ROP bypass ASLR ret pop rdi
 ret code stack high low rsp 207 put@plt pop rdi put@GOT pop rdi 0 pop rsi puts@GOT …… put@GOT rdi 0 rsi 0 rdx
  • 208. Using ROP bypass ASLR ret pop rdi
 ret put@plt code stack high low rsp 208 put@plt pop rdi put@GOT pop rdi 0 pop rsi puts@GOT …… put@GOT rdi 0 rsi 0 rdx
  • 209. Using ROP bypass ASLR ret pop rdi
 ret jmp *(put@GOT) code stack high low rsp 209 put@plt pop rdi put@GOT pop rdi 0 pop rsi puts@GOT …… put@GOT rdi 0 rsi 0 rdx
  • 210. Using ROP bypass ASLR ret pop rdi
 ret jmp put(put@GOT) code stack high low rsp 210 put@plt pop rdi put@GOT pop rdi 0 pop rsi puts@GOT …… put@GOT rdi 0 rsi 0 rdx
  • 211. Using ROP bypass ASLR ret pop rdi
 ret jmp put(put@GOT) code stack high low rsp 211 put@plt pop rdi put@GOT pop rdi 0 pop rsi puts@GOT …… put@GOT rdi 0 rsi 0 rdx Information leak
  • 212. Using ROP bypass ASLR ret pop rdi
 ret jmp put(put@GOT) ret code stack high low rsp 212 put@plt pop rdi put@GOT pop rdi 0 pop rsi puts@GOT …… put@GOT rdi 0 rsi 0 rdx
  • 213. Using ROP bypass ASLR ret pop rdi
 ret jmp put(put@GOT) ret pop rdi ret code stack high low rsp 213 put@plt pop rdi put@GOT pop rdi 0 pop rsi puts@GOT …… put@GOT rdi 0 rsi 0 rdx
  • 214. Using ROP bypass ASLR ret pop rdi
 ret jmp put(put@GOT) ret pop rdi ret code stack high low rsp 214 put@plt pop rdi put@GOT pop rdi 0 pop rsi puts@GOT …… 0 rdi 0 rsi 0 rdx
  • 215. Using ROP bypass ASLR ret pop rdi
 ret jmp put(put@GOT) ret pop rdi ret pop rsi ret code stack high low rsp 215 put@plt pop rdi put@GOT pop rdi 0 pop rsi puts@GOT …… 0 rdi 0 rsi 0 rdx
  • 216. Using ROP bypass ASLR ret pop rdi
 ret jmp put(put@GOT) ret pop rdi ret pop rsi ret code stack high low rsp 216 puts@GOT 0 rdi puts@GOT rsi 0 rdx pop rdx read@plt pop rdi Address of /bin/sh puts@plt 0x8
  • 217. Using ROP bypass ASLR ret pop rdx ret code stack high low rsp 217 puts@GOT 0 rdi puts@GOT rsi 0 rdx pop rdx read@plt pop rdi Address of /bin/sh puts@plt 0x8
  • 218. Using ROP bypass ASLR ret pop rdx ret code stack high low rsp 218 puts@GOT 0 rdi puts@GOT rsi 8 rdx pop rdx read@plt pop rdi Address of /bin/sh puts@plt 0x8
  • 219. Using ROP bypass ASLR ret pop rdx ret jmp read@plt code stack high low rsp 219 puts@GOT 0 rdi puts@GOT rsi 8 rdx pop rdx read@plt pop rdi Address of /bin/sh puts@plt 0x8
  • 220. Using ROP bypass ASLR ret pop rdx ret jmp read(0,put@GOT,8) code stack high low 220 puts@GOT 0 rdi puts@GOT rsi 8 rdx pop rdx read@plt pop rdi Address of /bin/sh puts@plt 0x8 rsp
  • 221. rsp Using ROP bypass ASLR ret pop rdx ret jmp read(0,put@GOT,8) code stack high low rsp 221 puts@GOT 0 rdi puts@GOT rsi 8 rdx pop rdx read@plt pop rdi Address of /bin/sh puts@plt 0x8 GOT Hijacking puts -> system
  • 222. Using ROP bypass ASLR ret pop rdx ret jmp read(0,put@GOT,8) ret code stack high low 222 puts@GOT 0 rdi puts@GOT rsi 8 rdx pop rdx read@plt pop rdi Address of /bin/sh puts@plt 0x8 rsp
  • 223. Using ROP bypass ASLR ret pop rdx ret jmp read(0,put@GOT,8) ret pop rdi ret code stack high low 223 puts@GOT 0 rdi puts@GOT rsi 8 rdx pop rdx read@plt pop rdi Address of /bin/sh puts@plt 0x8 rsp
  • 224. Using ROP bypass ASLR ret pop rdx ret jmp read(0,put@GOT,8) ret pop rdi ret code stack high low 224 puts@GOT &/bin/sh rdi puts@GOT rsi 8 rdx pop rdx read@plt pop rdi Address of /bin/sh puts@plt 0x8 rsp
  • 225. Using ROP bypass ASLR ret pop rdx ret jmp read(0,put@GOT,8) ret pop rdi ret jmp puts@plt code stack high low 225 puts@GOT &/bin/sh rdi puts@GOT rsi 8 rdx pop rdx read@plt pop rdi Address of /bin/sh puts@plt 0x8 rsp
  • 226. Using ROP bypass ASLR ret pop rdx ret jmp read(0,put@GOT,8) ret pop rdi ret jmp *(puts@GOT) code stack high low 226 puts@GOT &/bin/sh rdi puts@GOT rsi 8 rdx pop rdx read@plt pop rdi Address of /bin/sh puts@plt 0x8 rsp
  • 227. Using ROP bypass ASLR ret pop rdx ret jmp read(0,put@GOT,8) ret pop rdi ret jmp system(“/bin/sh”) code stack high low 227 puts@GOT &/bin/sh rdi puts@GOT rsi 8 rdx pop rdx read@plt pop rdi Address of /bin/sh puts@plt 0x8 rsp
  • 228. Using ROP bypass ASLR ret pop rdx ret jmp read(0,put@GOT,8) ret pop rdi ret jmp system(“/bin/sh”) code stack high low 228 puts@GOT &/bin/sh rdi puts@GOT rsi 8 rdx pop rdx read@plt pop rdi Address of /bin/sh puts@plt 0x8 rsp GET SHELL
  • 229. Using ROP bypass ASLR 229 • Bypass PIE • 必須比平常多 leak ⼀一個 code 段的位置,藉由這個值算出 code base 進 ⽽而推出所有 GOT 等資訊 • 有了了 code base 之後其他就跟沒有 PIE 的情況下⼀一樣
  • 230. Using ROP bypass ASLR 230 • Bypass StackGuard • canary 只有在 function return 時做檢查 • 只檢查 canary 值時否⼀一樣 • 所以可以先想辦法 leak 出 canary 的值,塞⼀一模⼀一樣的內容就可 bypass,或是想辦法不要改到 canary 也可以
  • 231. Using ROP bypass ASLR 231 • Weakness in fork • canary and memory mappings are same as parent.
  • 233. Reference • Glibc cross reference • Linux Cross Reference • 程式設計師的⾃自我修養 233
  • 235. Thank you for listening Mail : angelboy@chroot.org Blog : blog.angelboy.tw 235 Twitter : scwuaptx