Binary exploitation basic 1
ELF
- Executable and Linkable Format
- 執行檔ex. exe
- section
- 執行時會mapping到RAM上(virtual memory)
- .text .bss .data .rodata .got .plt .fini
ELF - SECTION
.bss : 存放未初始化值的全域變數 (global variable)
.data : 存放具初始化值的全域變數
.rodata : 存放唯讀(read only)資料
.text : 存放編譯後的code

x64 Assembly

- Registers
RSP- Stack Pointer Registers- 指向stack頂端(頭)
RBP- Base Pointer Registers- 指向stack底端(尾)
RIP- Register Instruction Pointer- 指向當前執行指令instruction位置
jmp- 跳至程式某一個地址A(address)執行- jmp A = mov rip, A
call- 將call完後回來緊接著要執行下一行指令位置push到stack上儲存起來,在跳過去執行- call A = push next_rip
mov rip, A - 兩個instruction
- call func = push next-rip
- jmp func
- next-rip 會push到stack上
- call A = push next_rip
leave- 還原至caller的stack frame- mov rsp, rbp
pop rbp - 兩個instruction
- leave = mov rsp, rbp
- pop rbp ; rbp會指到stack的位置
- mov rsp, rbp
ret(return)- pop rip
- 會把rsp指向的值塞到rip
compiler前面三行通常都為:
1 | func: |

x64 calling convention
Pass parameters- rdi, rsi, rcx, r8, r9, (stack)
- rdi, rsi, rdx, r10, r8, r9 (stack)
- rax - store return value
x64- register 傳參x86- stack 傳參
Stack Frame

overflow
- Buffer overflow
- Stack overflow
- Heap overflow
- 覆蓋到理論上不應該被修改到的資料
- Import data, Secret
- Return address
BOF (Buffer overflow)
- Local variables
- Data on stack
- gets(buf)
- gets()不會去檢查輸入的長度
- 控制位於stack上的變數值
- int c = 0xdeadbeef
- int d = 0xfaceb00c
- long e = 0x4141414141414141
- 控制敏感資料
- Control flow
- Return address
- ret
- rip = 0x4141414141414141
- Control rip
Canary (Stack protector)


- function prologue的時候會在stack的上面放random 8 bytes在saved rbp前, 第一個byte為null
- function prologue的時候會儲存另一個segment的值去檢查canary是否相同, 以此檢測是否overflow, 如果相同才會做ret, 否則abort
- 每次的canary不同, 同一次的canary固定
- 如需關掉canary請搭配這個參數: -fno-stack-protector
- 如果發生buf的話可以用x/
gx $rsp查看stack的狀況
從gets輸入0x30(48)個bytes會剛好抵達rbp指的地方

- mov rax, QWORD PTR fs:0x28 ; 把另一個segment address的東西拿出來, QWORD(8 bytes)
- mov QWORD PTR [rbp-0x8], rax ; rax放到rbp-0x8的地方, 所以就剛好在rbp前面的8個bytes
- mov rdx, QWORD PTR [rbp-0x8] ; 把rbp-0x8的值丟到rdx
- xor rdx, QWORD PTR fs:0x28 ; 做比較, 如果是0代表一樣, 會跳過 __stack_chk_fail()去做正常的ret (je 4005fb <main+0x41>)
但如果1就會call stack_chk_fail, 就會abort

NX
- No-Execute
- Data segment不應該有執行權限
- stack heap
- rw-
- Code segment有執行的權限, 但不能寫入
- r-x
就算塞了shellcode到data
就算知道位址在哪裡
還是會crash, 因為rip指到一個不可執行的地方
ASLR(Address Space Layout Randomization)保護機制
- kernel的保護機制
- 每次載入base都是隨機的
- library
- stack
- heap
舉例來說 我使用ldd
每次library被map到的address都不一樣

PIE保護機制:
- 可以看成是ELF code base & data section map到virtual address的ASLR
- 每次執行code base都會不同, 否則固定0x400000
- 會記錄到ELF file中
Lazy Binding
- Dynamic linking的程式, 有些有用到的library function可能從頭到尾都不會被用到
- 它的機制是程式第一次呼叫library function的時候, 才會做第一次的尋找library function的位置(function address)進行binding, 並且填到GOT表中, 之後要呼叫這個function就會直接從GOT表中獲取它的位置
GOT
- LIBRARY的位置再載入的時候才決定的, compiler在編譯的時候沒辦法知道執行時的library function address
- GOT是儲存library function位置的指標陣列, 而lazy binding是, 一開始不會得知真實的位置, 而是要先填入位於plt的code
GOT Hijacking
- 由於Lazy binding的機制, 使得GOT變成可寫的區域
- 如果程式有漏洞可以造成對GOT做寫入覆蓋其值, 下一次呼叫對應的library function時就可以從中劫持, 任意控制將要執行的function pointer