owned this note changed a year ago
Linked with GitHub

NTU Computer Security Fall 2019

Binary Exploitatiion

Binary exploitation

  • What is PWN
    • 透過利用程式(Binary)的漏洞(Vulnerability),在執行期間控制執行流程(Control flow),進而使程式執行特定行為

Basic concepts

  • ELF(Executable and Linkable Format)
    • 執行檔
      • Example
        • exe
    • Section
      • 執行時會mapping到RAM上(Virtual memory)
      • .text, .bss, .data, .rodata, .got, .plt, .fini, etc.
    • Workflow(Static)
      • image
    • Workflow(dynamic linking)
      • image
    • Section
      • .bss
        • 存放未初始化值的全域變數(global variable)
      • .data
        • 存放具初始化值的全域變數
      • .rodata
        • 存放唯讀(read-only)資料
      • .text
        • 存放編譯後的code
      • image
    • Protections
      • PIE
        • Position-Independent Executable
      • NX
        • No-eXecute
      • Canary
        • Stack protector
      • RELRO
        • Relocation Read-Only
  • x64
    • 8 bytes alignment
    • Stack 0x10 bytes alignment
    • Assembly
      • Registers
        • rax, rbx, rcx, rdx, rdi, rsi
          • 64 bits
        • eax, ebx, ecx, edx, edi, esi
          • 32 bits
        • ax, bx, cx, dx, di, si
          • 16 bits
        • ax -> ah, al
          • 8 bits
        • RSP
          • Stack pointer register
          • 指向stack頂端(頭)
        • RBP
          • Base pointer register
          • 指向stack底端(尾)
        • RIP
          • Program counter register
          • 指向當前執行指令instruction位置
      • jmp
        • 跳至程式某一地址address執行
      • call
        • 將call完後回來緊接著要執行的下一行指令位置push到stack上儲存起來,再跳過去執行
      • leave
        • 還原至caller的stack frame
          • mov rsp, rbp
          • pop rbp
      • ret(return)
    • Calling convention
      • Pass parameters
        • rdi, rsi, rdx, rcx, r8, r9, (stack)
        • rdi, rsi, rdx, r10, r8, r9, (stack)
        • rax: store return value
      • x64: register傳參數
      • x86: stack傳參數
  • Stack frame
    • Function prologue
    • Function epilogue
    • Stack frame
      • local variables
      • [rbp] = old rbp(caller rbp)
      • [rbp + 0x8] = return address

Overflow

  • Buffer overflow
  • Stack overflow
  • Heap overflow
  • 覆蓋到理論上不應該被修改到的資料
    • Important data, Secret
    • Return address

BOF - Buffer Overflow

  • Local variables
    • Data on stack
  • gets(buf)
    • 不會檢查輸入長度
    • 可以覆蓋stack上的資料
      • 改變return address、control flow等

Canary

  • Function prologue時在stack上放置程式執行時隨機生成的8 bytes在saved rbp前
    • 第一個byte為null byte
  • Function epilogue時會拿儲存在另一segment的值檢查canary值是否相同來檢測是否發生overflow
    • 若相同才正常return
    • 否則直接終止程式(abort)
  • 每次執行canary不同,同一次的canary固定

Shellcode

  • Write assembly code and use assembler to turn to machine code

Linux Syscall

  • System call
  • 跟kernel做溝通的interface
    • instruction
      • syscall
    • rax
      • syscall number
    • Arguments
      • rdi, rsi, rdx, r10, r8, r9
    • Return value
      • rax

Shellcode: execve

  • execve
    • int execve(const char *pathname, char *const argv[], char *const envp[])
    • Spawn a shell
      • execve("/bin/sh", NULL, NULL)
      • image

NX

  • No-execute
  • Data segment不應具有執行權限
    • stack, heap
    • rw-
  • Code segment具執行權限,但不具寫入權限
    • r-x
  • image
  • seccomp

ASLR

  • Address Space Layout Randomizaion
  • Kernel的保護機制
  • 每次動態載入時,base都是隨機的
    • library
    • stack
    • heap

PIE

  • Position-Independent Executable
  • 可以看成是ELF code & data section map到virtual address時的ASLR
  • PIE開啟時,每次執行程式code base都會不同,否則固定0x400000
  • 紀錄在ELF file中

Lazy Binding

  • Dynamic linking的程式,有些使用到的library function可能因執行流程到結束都不會被執行到
  • Lazy binding機制為當程式第一次呼叫library function時,才會去尋找libc function的位置(function address)進行binding,並填入GOT表中,後續呼叫此function則直接從GOT表中獲取位置

GOT

  • Global Offset Table
  • Library的位置在載入時才決定,compiler在編譯時期亦無法得知執行時期的library function address
  • GOT為儲存library function位置的指標陣列,而lazy binding的機制,一開始不會得知真實位置,而是先填入位於plt的code

GOT Hijacking

  • 因為Lazy binding的機制,GOT為可寫區域
    • 假設程式有漏洞可以造成對GOT做寫入覆蓋其值,下一次呼叫對應的library function時則可以從中劫持,任意控制將要執行的function pointer

ROP(Return Oriented Programming Attack)

ROP gadgets

ROP:

  • NX: 見招拆招
    • 在既有的執行區域(code segment)尋找gadgets,運用這些gadgets疊成一長串的return address chain(ROP chain)
    • 透過許多片段執行行為的gadget,來串出任意代碼執行,藉此繞過NX保護機制的限制
      • Function return時,會拿走第一個return address,此時rsp指在第二個return address,並跳至第一個return address執行,接著會執行到ret instruction
      • 而第二個return address也在開始時放置好,做到繼續control flow,如此反覆來達到Return Oriented Porgramming形式的攻擊

Control Register

  • Gadget
    • pop (reg);
    • ret
      • 因為byte的數量,因此找到的機會比較搭

ROP:

  • 常常不會那麼剛好有想要的gadget且是ret結尾
    • 想辦法組合gadget,達成同樣的目的
  • 存在overflow,或任何成功control rip的前提下
    • NX關的情況,可以撰寫執行execve("/bin/sh", 0, 0)的shellcode並嘗試控制rip跳至shellcode
    • NX開的情況,可以透過ROP的方式,堆疊出執行execve("/bin/sh", 0, 0)行為的ROP chain

ret2plt(return to .plt)

  • 如果想要串的行為本身就有function在binary中,可以直接用ROP放好參數使用它
    • 不用用ROP去堆全部的行為
  • 在PIE關的情況下,即使不知道library function address(因ASLR),也可以透過return到.plt上使用此function

ret2libc(return to libc)

  • 若能得知library被map到的隨機起始地址(base address),則可以計算出libc中function的位置,便能調用library中的函式
  • 關鍵為bypass ASLR,找出libc的隨機base
    • 透過information leak漏洞,洩漏memory上的內容,獲取屬於libc segment的address
    • 此address會是隨機的base address加上一固定位移值offset
      • 不同版本的libc offset不同
    • leaked_address - offset = base_address
  • 有base後繼可以透過加上offset的方式得知其他function的address來call它,結合ROP等等

Information leak

  • Compiler開空間時,Stack上面的值不會清乾淨
    • 可以leak出來
      • 透過剛好input到沒乾淨的值的前面,可以將殘留的值leak出來
        • libc的memory

Stack pivoting(Stack migration)

  • ROP需要很多空間放置長串的ROP chain,有時並不會有那麼多空間,可能很短甚至只能控第一次rip
  • 若找到其他地方有足夠空間放置ROP payload,此時可以透過運用較少的gadget數,將stack搬移到ROP payload的位置,再進行ROP
  • 很多做法
    • leave; ret
      • Overflow時將rbp填成ROP Chain的address - 8
      • Return address填leave; ret gadget
    • pop rsp; ret
    • 手動找針對各種當下情況的gadget

ret2csu(return to __libc_csu_init)

  • 位於__libc_csu_init函式中,為compiler編進去的function
  • 尾部有一片段code,很適合拿來控制register放置參數,以及control flow
    • image
    • 透過控制rbp, rbx, r12, r13, r14, r15 registers的值,跳至Gadget開頭,r13, r14, r15分別放置前三個參數rdi, rsi, rdx
      • 此部分解決很少找到pop rdx gadget的問題
        • ROP很難控制第三個參數
    • 控制r12, rbx來指定任意記憶體位置call [r12+rbx*8]
    • 將rbx設為0,將rbp設為1,在call完後使rbx == rbp == 1,jne不會take,而繼續執行後面的連續pop register,如此可重複使用,達到任意ROP

Heap Exploitation

Heap intro

  • 在打heap時,需要先知道library的版本
    • ldd --version
  • ptmalloc2
    • glibc
    • tcmalloc: google
    • jemalloc
    • etc.
  • malloc
    • 要用多少分配多少
      • 提升記憶體分配效率及避免記憶體空間的浪費
    • void *ptr = malloc(size)
    • Workflow
      • image
    • main arena
      • 一開始malloc < 128 KB,透過brk,kernel會給132KB的heap segment(rw)
        • main arena
        • 對kernel來說已經被使用,對binary來說還沒拿到
          • 會交給glibc管理
        • image
      • ASLR: heap base
  • Chunk
    • glibc實作記憶體管理機制的資料結構(data structure)
    • malloc拿到的一塊記憶體
      • Allocated chunk
      • Free chunk
      • Top chunk
    • Size alignment
      • 0x10的倍數,malloc 0x18會拿到0x20的大小
    • 整個chunk占記憶體大小為header(0x10) + data
    • image

Chunk header

  • Allocated chunk
    • prev_size
      • 連續記憶體上一塊若是free chunk,則記錄該size
      • 若是allocated chunk則同時為它的data
    • size
      • Chunk size with 3 flags
        • PREV_INUSE§
          • 上一個chunk是否使用中
        • IS_MMAPED(M)
          • Chunk是否透過mmap出來的
        • NON_MAIN_ARENA(N)
          • 該chunk是否不屬於main arena
    • image
      • Pointer會指在user data
  • Free chunk
    • prev_size
      • 連續記憶體上一塊若是free chunk,則記錄該size
      • 若是allocated chunk則為它的data
    • size
      • 連續記憶體下一塊的P flag為0
    • fd
      • 指向同一bin中的前一塊chunk(linked list)
    • bk
      • 指向同一bin中的後一塊chunk(linked list)
    • image
  • Top chunk
    • 第一次malloc後,剩下的空間為top chunk,分配空間時視情況從top chunk切割分配
    • free Top chunk連續記憶體上一塊chunk時,若不是fastbin則會與Top chunk merge,top chunk P恆為1
    • image

bins

  • 回收free chunk的資料結構
  • 主要依據size大小分為
    • fast bin
    • small bin
    • large bin
    • unsorted bin
  • Fast bin
    • Size < 0x90 bytes
    • bin中依據size劃分為0x20, 0x30, 0x40,
      • global_max_fast = 0x80
    • Singly linked list
      • fd指向前一個,bk沒用到
    • LIFO(Last in, First out)
    • Free時不會將下一塊chunk P flag設成0
  • Small bin
    • Circular doubly linked list
    • 依據size劃分為62個bin
      • 0x20, 0x30, , 0x3f0
      • 0x20 ~ 0x80的大小與fast bin重疊,會根據機置放到fast bin或small bin
    • FIFO(First in, First out)
    • Free掉時會將下一塊chunk P設為0
  • Large bin
    • Circular doubly linked list
      • 依據大小遞減排序
    • size >= 1024 bytes(0x400)
    • 63 bins
      • 細節可以參考source code
    • header
      • fd_nextsize
      • bk_nextsize
    • image
  • Unsorted bin
    • Circular doubly linked list
    • free的chunk size大於fast bin時,不會直接放到對應的bin哩,會先丟到unsorted bin中
    • malloc fast bin size大小時會先去fast bin list裡找,若沒有則會至unsorted bin找
      • 如找到一樣大小則回傳
      • 若無但找到大小大於所需大小的chunk則切割回傳
        • 剩下的部分會丟回unsorted bin
      • 若都沒有則從top chunk切出來回傳

Vulnerability

Heap overflow

  • 在heap segment發生的overflow
  • 和stack overflow類似
    • Stack overflow目標是掌控stack上可利用資訊
      • return address等
    • Heap overflow是掌握heap中的利用目標
      • 某個chunk分配來是一個object struct,透過heap overflow overwrite進行偽造
      • 控制chunk header,並結合glibc malloc free的記憶體管理機制,做到進一步利用

UAF(Use after free)

  • free(ptr)
    • free完pointer後未將ptr清空(ptr=NULL),稱為dangling pointer
      • 有一個pointer指著一塊已經被釋放的記憶體
  • 根據不同的存取方式,有各種利用方法,可以進一步去做後續exploit的利用
    • 用來information leak,存取殘留的data
    • Struct Type Confusion
  • Double free就是因為存在dangling pointer所以造成free一塊已經釋放的chunk,一樣可以透過一些技巧達到進一步的利用
  • Information leak
    • free兩個同size的fastbin,fd指向heap,如果存在UAF,將此chunk user data印出來或任何方法得知其值,透過印出fd來leak出heap address
    • malloc一塊非fast bin size的chunk,free掉它使它被放入unsorted bin中,或任何製造出unsorted bin的方法,unsorted bin的fd與bk會是一個libc address
      • 直接UAF印出fd來leak出libc address,或是malloc拿回這塊chunk,印出殘留的fd等

Heap exploitation

Fastbin attack

  • fastbin在檢查double free時,只檢查現在linked list第一個chunk是否等於現在即將要free掉的chunk
    • 若存在double free,則可以透過free(A) free(B) free(A)的方式繞過此檢查
    • 下次再malloc此fastbin size時,會拿到chunk A,而同時chunk A依舊存在於free chunk linked list中,藉此寫入data時修改掉fd,接下來連續malloc兩次後,第三次則會回傳拿到我們偽造的address
  • Constraints
    • malloc時會檢查chunk size正不正確
      • 在目標地址+0x8的地方偽造size
      • 尋找附近存在正確size之目標位置
    • 增加可行性的利用技巧
      • address alignment weakness
      • libc address hardcode
      • 檢查size時是抓取4 bytes int

Hooks

  • glibc中存在許多function hooks,在攻擊時如果能達到arbitrary write或任意寫,hooks會是一個很好的寫入目標,來做到control flow
    • __malloc_hook
    • __free_hook
    • __realloc_hook
    • etc.
  • 在執行該function時,發現該function hoook有值,則當作function pointer跳上去執行
  • 結合fastbin attack拿到位於hooks附近位置的fake chunk,來overwrite hooks的值

One gadget

  • 跳過去即執行execve("/bin/sh", argv[], envp[])(開shell)
    • magic gadget
  • 有一些前提(constraints)要滿足
  • 常搭配hooks使用
  • https://github.com/david942j/one_gadget
  • 補充
    • 如果malloc一塊unsorted bin大小的空間,free之後假如那空間的後面連著top chunk,會被merge

Tcache(per-thread cache)

  • glibc >= 2.26
    • Ubuntu 17.10後
  • 新的機制,提升performance
    • 第一次malloc後,會先分配一塊記憶體,存放tcache_perthread_struct
      • 一個thread一個tcache_perthread_struct
      • image
  • 根據size分為不同大小的tcache
    • smallbin大小範圍的chunk都會使用tcache
    • 以fastbin來說,free時不會直接放到fastbin裡,而是放到對應的size的Tcache中,當滿7個時,再free才會放至fastbin中
      • fastbin的fd是指向整個chunk的頭(Header),而tcache fd則是指向user data
  • malloc時優先從tcache取出,tcache為空才會從原本的bin中開始找
    • 若tcache為空,而原本的bin中有剛好大小的chunk時,會從bin中填補至tcache中直到填滿,再從tcache中取出
      • tcache中的順序會與bin中相反
      • 對於fastbin來說,會先將bin中第一塊取出,才將後面做填補
  • 提升效能,而降低了安全性
    • 沒有檢查double free
    • malloc時沒有檢查size是否合法
  • 不需要偽造chunk、偽造size,就能拿到任意記憶體的位置
  • 有許多進階玩法與技巧
    • 透過漏洞掌握整個tcache_perthread_struct

Some Heap Technique

Heap Overlap

  • 可能一開始漏洞無法直接性做到太多事情
  • 透過各式偽造chunk size的方式,以及玩弄malloc free的流程,使得不同的chunk發生重疊(heap overlap)的情形
    • 假設chunk A的data與chunk B的不可寫部分重疊
      • chunk B可能是一個struct,亦或是function pointer,則可以透過chunk A來偽造,overwrite data pointer達到任意讀寫,overwrite function pointer則可以hijack control flow
      • 可以更進一步偽造chunk header,偽造heap chunk,玩弄記憶體管理機制
  • off-by-one null byte overflow
  • 某種程度上算很容易發生的漏洞
    • 如宣告size剛剛好的字元陣列,一些libc function操作會自動append null byte或自行邊界操作不當等
  • doubly linked list - unlink
  • unlink§
    • p->fd = bk
    • p->bk = fd
  • 古典作法
    • 在有漏洞的前提下,偽造p的fd, bk,透過unlink,可以對memory做寫入
      • image
  • 後來增加檢查,驗證doubly linked list的完整性
    • 指過去要能指回來
      • P->bk->fd = P
      • P->fd->bk = P
  • 後來的利用條件
    • 已知address底下存放著p指標(已知&p)
    • p為data pointer可以多次寫入,或其他同效果方法
      • image
      • 之後再對data pointer p做寫入,便可以覆蓋掉p,overwrite為任意地址
      • 再次寫入即會對目標地址寫入,達到write everywhere的效果

Unsorted bin attack

  • 在有漏洞的前提下
  • 將unsorted bin的bk填成address - 0x10,再malloc相同大小的size,address的地方會被填上libc的address,指向main_arena中
  • 無法直接性做到太多事情,可以用來間接進一步利用
    • 將一個地方填上很大的數字
    • information leak
    • 進階heap exploit技巧搭配
    • etc.

Something good

Select a repo