# 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