---
# System prepended metadata

title: 2020 程安 Pwn 筆記1
tags: [程式安全]

---

# 2020 程安 Pwn 筆記1
###### tags: `程式安全` 

## Shellcode: 
- 比較炫砲的machine code名字XD
	- 因為通常希望跑完可以獲得shell所以叫shellcode

### Calling Convention
- AMD64 : 
	- userspace function: 
		- rdi rsi rdx <font color='red'>rcx</font> r8 r9
	- system call:         
		- rdi rsi rdx <font color='red'>r10</font> r8 r9 
		- <font color='red'>rcx</font>存放userspace的rip,然後才跳進kernel mode load kernel space的rip

		- `strace`指令可以dump出binary使用到的所有system call

### Mitigation -- NX
- NX(**N**o e**X**ecute)
    - 任何segment都不可以同時有<font color='red'>寫跟執行</font>的權限

### Bypass NX
- 使用`mmap` system call 來assign一個特定權限的區塊
    - ex 
    ```c=
    #include <sys/mman.h>
    #include <stddef.h> //for def NULL

    int main(){
        void (*shell)() = mmap(NULL, 0x100, PROT_EXEC|PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1 ,0); 
        //map a rwx space for 0x100 byte
        //PROT_EXEC :可執行. PROT_READ :可讀. PROT_WRITE :可寫
        return 0;	
    }
    ```
    - 執行`mmap`前
    ![](https://i.imgur.com/aVhP4tN.png)
    - 執行`mmap`後: 可以發現多了一段rwx權限的
    ![](https://i.imgur.com/kAh6HH7.png)

- 或是用`mprotect` system call來修改權限(Protection)
    
## Buffer Overflow
- 因為沒有檢查輸入長度,輸入比buffer大的長度造成overflow
    - ex. `gets(buf)`, `scanf(%s, buf)`等危險函數
        沒有檢查輸入長度,就會造成bof
    - 可以蓋掉return address,讓程式crash或執行到攻擊者想要執行的指令

### Mitigation -- Canary
- 在`old rbp`及`local variable`中間`(rbp-0x8)`塞一個從`fs+0x28`拿出來的隨機值,在程式`ret`之前進行檢查,如果不一樣就crash
- <font color='red'>canary的第一個byte一定是'\x00'</font>

### Bypass Canary
1. 在runtime時leak canary
    - canary的第一個byte是00,而<font color='red'>printf是用`'\x00'`截斷</font>,因此蓋掉這個byte,會把canary後面的7byte也印出來
3. 如果buf不是線性的往下寫(ex可以跳到某個index開始寫),可以跳過canary所在的位置

### ROP(Return Oriented Programming)
- 現在的CTF題或現實環境幾乎都會開`NX` $\rightarrow$ 無法寫shellcode來get shell
也不會像某些簡單CTF題有個shell function可以直接使用
而且通常會開`Canary`的保護機制 
 $\Rightarrow$ 假設我們可以bypass Canary,該怎麼get shell?

- 

- ROP chain: 由多個rop gadget組成
    - rop gadget:
        因為x64的assembly長度不固定,machine code使用dynamic抓長度,因此就算gadget是在某個指令的中間,只要符合對應的machine code就可以執行
    - 每個rop gadget都以`ret`指令結尾,用來串起下一個gadget
    - 把return address蓋成rop chain的第一個gadget

#### Mitigation -- ASLR and PIE
- ASLR(address space layout randomization)
    - 由<font color='red'>系統</font>決定 ` /proc/sys/kernel/randomize_va_space`
    - 0: 沒有ASLR
      1: share library, stack位置不固定
      2: share library, stack, heap位置不固定
    - 其實就是在前面加上一段不定長度的空間

- PIE(Position independent executable)
    - 由binary自行決定(compile時下`gcc -fpie -pie`)
    - 在.text段前加上一段不定長度的空間

- 目地都是要讓攻擊者找不到gadget的真正位置,無法做ROP

#### bypass ASLR/PIE
- leak出那段random offset的長度
	- stack上殘存的`libc function的address - vmmap看到的libc base` = 該function在libc中的`offset`
	再利用bof leak出每次執行的`libc function address - offset`就是該次的libc base

### GOT (Global offset Table)
- 當有ASLR時,library每次都會被load在不同address
	- 要怎麼讓他在執行時可以找到?

- Overview
![](https://i.imgur.com/vGT9toe.png)

1. GOT table中,哪個function在哪個offset是固定的
2. call funcA時會跳到funcA@plt上
```c=
funcA@plt
   push [.got+0x10] //0x10為funcA在GOT中的offset
   