Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Binary Exploitation

yuawn
November 22, 2019

Binary Exploitation

NTU CS 2019 Fall week2 - Binary Exploitation
台大 - 計算機安全 Pwn
交大 - 程式安全
台科大 - 資訊安全實務

yuawn

November 22, 2019
Tweet

More Decks by yuawn

Other Decks in Education

Transcript

  1. Outline • ROP • ret2plt • ret2libc • Information leak

    • Stack Pivoting • ROP 萬解 - ret2csu PWNED
  2. ROP gadget • 片段可執⾏行行的 code • 結尾是 ret instruction •

    call, jmp … 等任何可以繼續控制流程的⽅方式 • How to find the gadgets? • https://github.com/JonathanSalwan/ROPgadget • https://github.com/sashs/Ropper • ⼿手動找
  3. 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 Programming 型式的攻擊。
  4. … Gadget 2: mov rbx, 66 ret … Gadget 3:

    add rax, rbx ret … main: … leave ret … Gadget 1: mov rax, 100 ret ... low address high address return address saved rbp local variables of func()
  5. … Gadget 2: mov rbx, 66 ret … Gadget 3:

    add rax, rbx ret … main: … leave ret … Gadget 1: mov rax, 100 ret ... low address high address AAAAAAAA AAAAAAAA AAAAAAAA
  6. … Gadget 2: mov rbx, 66 ret … Gadget 3:

    add rax, rbx ret … main: … leave ret … Gadget 1: mov rax, 100 ret ... low address high address Gadget 1 AAAAAAAA AAAAAAAA Gadget 2 Gadget 3
  7. … Gadget 2: mov rbx, 66 ret … Gadget 3:

    add rax, rbx ret … main: … leave ret … Gadget 1: mov rax, 100 ret ... low address high address AAAAAAAA AAAAAAAA rsp rip Gadget 1 Gadget 2 Gadget 3
  8. … Gadget 2: mov rbx, 66 ret … Gadget 3:

    add rax, rbx ret … main: … leave ret … Gadget 1: mov rax, 100 ret ... low address high address AAAAAAAA AAAAAAAA rsp rip Gadget 1 Gadget 2 Gadget 3
  9. … Gadget 2: mov rbx, 66 ret … Gadget 3:

    add rax, rbx ret … main: … leave ret … Gadget 1: mov rax, 100 ret ... low address high address AAAAAAAA AAAAAAAA rsp rip Gadget 1 Gadget 2 Gadget 3 rax = 100
  10. … Gadget 2: mov rbx, 66 ret … Gadget 3:

    add rax, rbx ret … main: … leave ret … Gadget 1: mov rax, 100 ret ... low address high address AAAAAAAA AAAAAAAA rsp rip Gadget 1 Gadget 2 Gadget 3 Control return address again.
  11. … Gadget 2: mov rbx, 66 ret … Gadget 3:

    add rax, rbx ret … main: … leave ret … Gadget 1: mov rax, 100 ret ... low address high address AAAAAAAA AAAAAAAA rsp rip Gadget 1 Gadget 2 Gadget 3
  12. … Gadget 2: mov rbx, 66 ret … Gadget 3:

    add rax, rbx ret … main: … leave ret … Gadget 1: mov rax, 100 ret ... low address high address AAAAAAAA AAAAAAAA rsp rip Gadget 1 Gadget 2 Gadget 3 rbx = 66
  13. … Gadget 2: mov rbx, 66 ret … Gadget 3:

    add rax, rbx ret … main: … leave ret … Gadget 1: mov rax, 100 ret ... low address high address AAAAAAAA AAAAAAAA rsp rip Gadget 1 Gadget 2 Gadget 3
  14. … Gadget 2: mov rbx, 66 ret … Gadget 3:

    add rax, rbx ret … main: … leave ret … Gadget 1: mov rax, 100 ret ... low address high address AAAAAAAA AAAAAAAA rsp rip Gadget 1 Gadget 2 Gadget 3 rax = 100 + 66 = 166
  15. ROP • 常常不會那麼剛好都會有我們想要的 gadget 並且是 ret 結尾。 • 想辦法組合 gadget,達成同樣的⽬目的

    • 例例如想控制 rax,沒有 pop rax; ret gadget 也⾼高機率不會剛剛好有 mov rax, <希望的值>: • 假設存在,pop rdi; ret 與 mov rax, rdi; ret,組合出控制 rax 值的 payload • 或是找到 xor rax, rax; ret 與 inc rax; ret,先將 rax 清零在⼀一直加⼀一⾄至想要的值 • 等等
  16. ROP • 存在 overflow,或任何成功 control rip 的前提下: • NX 關的情況下,我們可以撰寫執⾏行行

    execve( "/bin/sh" , 0 , 0 ) 的 shellcode 並嘗試控制 rip 跳⾄至 shellcode。 • 但 NX 開啟時,則可以透過 ROP 的⽅方式,堆疊出執⾏行行
 execve( "/bin/sh" , 0 , 0 ) ⾏行行為的 ROP Chain。
  17. ROP int execve( const char *pathname, char *const argv[], char

    *const envp[] ); rdi = address of "/bin/sh"
 rsi = 0x0 rdx = 0x0 rax = 0x3b Shellocode
  18. ROP int execve( const char *pathname, char *const argv[], char

    *const envp[] ); rdi = address of "/bin/sh"
 rsi = 0x0 rdx = 0x0 rax = 0x3b NX - Shellocode
  19. ROP int execve( const char *pathname, char *const argv[], char

    *const envp[] ); rdi = address of "/bin/sh"
 rsi = 0x0 rdx = 0x0 rax = 0x3b ROP!
  20. ROP pop rdi 0x601000 pop rsi "/bin/sh\0" mov [rdi], rsi

    pop rdx; pop rsi 0 0 pop rax 0x3b syscall rax = rbx = rcx = rdx = rdi = rsi = rsp
  21. ROP 0x400686 0x601000 pop rsi "/bin/sh\0" mov [rdi], rsi pop

    rdx; pop rsi 0 0 pop rax 0x3b syscall rsp rax = rbx = rcx = rdx = rdi = rsi = 假如 pop rdi; ret 此 gadget
 位於 0x400686
  22. ROP 0x400686 0x601000 pop rsi "/bin/sh\0" mov [rdi], rsi pop

    rdx; pop rsi 0 0 pop rax 0x3b syscall pop rdi ret rip = 0x400686 rsp rax = rbx = rcx = rdx = rdi = rsi =
  23. ROP 0x601000 pop rsi "/bin/sh\0" mov [rdi], rsi pop rdx;

    pop rsi 0 0 pop rax 0x3b syscall pop rdi ret rip rsp rax = rbx = rcx = rdx = rdi = 0x601000 rsi = pop rdi
  24. ROP 0x601000 pop rsi "/bin/sh\0" mov [rdi], rsi pop rdx;

    pop rsi 0 0 pop rax 0x3b syscall pop rdi ret rip rsp rax = rbx = rcx = rdx = rdi = 0x601000 rsi = pop rdi
  25. ROP 0x601000 pop rsi "/bin/sh\0" mov [rdi], rsi pop rdx;

    pop rsi 0 0 pop rax 0x3b syscall pop rsi ret rip rsp rax = rbx = rcx = rdx = rdi = 0x601000 rsi = pop rdi
  26. ROP 0x601000 pop rsi "/bin/sh\0" mov [rdi], rsi pop rdx;

    pop rsi 0 0 pop rax 0x3b syscall pop rsi ret rip rsp rax = rbx = rcx = rdx = rdi = 0x601000 rsi = 0x68732f6e69622f pop rdi
  27. ROP 0x601000 pop rsi "/bin/sh\0" mov [rdi], rsi pop rdx;

    pop rsi 0 0 pop rax 0x3b syscall pop rsi ret rip rsp rax = rbx = rcx = rdx = rdi = 0x601000 rsi = "/bin/sh" pop rdi
  28. ROP 0x601000 pop rsi "/bin/sh\0" mov [rdi], rsi pop rdx;

    pop rsi 0 0 pop rax 0x3b syscall rip rsp mov [rdi], rsi ret 將 "/bin/sh" 字串串
 存到 0x601000 的位置 rax = rbx = rcx = rdx = rdi = 0x601000 rsi = "/bin/sh" pop rdi
  29. ROP 0x601000 pop rsi "/bin/sh\0" mov [rdi], rsi pop rdx;

    pop rsi 0 0 pop rax 0x3b syscall rip rsp mov [rdi], rsi ret rax = rbx = rcx = rdx = rdi = ["/bin/sh"] rsi = "/bin/sh" pop rdi
  30. ROP 0x601000 pop rsi "/bin/sh\0" mov [rdi], rsi pop rdx;

    pop rsi 0 0 pop rax 0x3b syscall rip rsp pop rdx
 pop rsi
 ret rax = rbx = rcx = rdx = rdi = ["/bin/sh"] rsi = "/bin/sh" pop rdi
  31. ROP 0x601000 pop rsi "/bin/sh\0" mov [rdi], rsi pop rdx;

    pop rsi 0 0 pop rax 0x3b syscall rip rsp pop rdx
 pop rsi
 ret rax = rbx = rcx = rdx = 0x0 rdi = ["/bin/sh"] rsi = "/bin/sh" pop rdi
  32. ROP 0x601000 pop rsi "/bin/sh\0" mov [rdi], rsi pop rdx;

    pop rsi 0 0 pop rax 0x3b syscall rip rsp pop rdx
 pop rsi
 ret rax = rbx = rcx = rdx = 0x0 rdi = ["/bin/sh"] rsi = 0x0 pop rdi
  33. ROP 0x601000 pop rsi "/bin/sh\0" mov [rdi], rsi pop rdx;

    pop rsi 0 0 pop rax 0x3b syscall rip rsp rax = rbx = rcx = rdx = 0x0 rdi = ["/bin/sh"] rsi = 0x0 pop rax ret pop rdi
  34. ROP 0x601000 pop rsi "/bin/sh\0" mov [rdi], rsi pop rdx;

    pop rsi 0 0 pop rax 0x3b syscall rip rsp rax = 0x3b rbx = rcx = rdx = 0x0 rdi = ["/bin/sh"] rsi = 0x0 pop rax ret pop rdi
  35. ROP 0x601000 pop rsi "/bin/sh\0" mov [rdi], rsi pop rdx;

    pop rsi 0 0 pop rax 0x3b syscall rip rsp rax = 0x3b rbx = rcx = rdx = 0x0 rdi = ["/bin/sh"] rsi = 0x0 syscall pop rdi
  36. ROP 0x601000 pop rsi "/bin/sh\0" mov [rdi], rsi pop rdx;

    pop rsi 0 0 pop rax 0x3b syscall rip rsp rax = 0x3b rbx = rcx = rdx = 0x0 rdi = ["/bin/sh"] rsi = 0x0 syscall execve( "/bin/sh" , 0 , 0 ) Get Shell! pop rdi
  37. ROP 0x601000 pop rsi "/bin/sh\0" mov [rdi], rsi pop rdx;

    pop rsi 0 0 pop rax 0x3b syscall rip rsp rax = 0x3b rbx = rcx = rdx = 0x0 rdi = ["/bin/sh"] rsi = 0x0 syscall execve( "/bin/sh" , 0 , 0 ) Get Shell! PWNED ☠ pop rdi
  38. ret2plt • 如果想要串串的⾏行行為本⾝身就有 function 在 binary 中,例例如,binary 本⾝身有 puts(),我 們可以直接⽤用

    ROP 放好參參數直接使⽤用它,就不⽤用⽤用 ROP 去堆全部的⾏行行為。 • 在 PIE 關的情況下,即使不知道 library function address (因 ASLR),也可以透過 return 到 .plt 上來來使⽤用這個 function,這個做法即稱為 ret2plt。
  39. ret2plt • write( 1 , "Hello World" , 12 )

    pop rdi 1 pop rsi ["Hello World"] pop rdx 11 pop rax 1 syscall
  40. ret2libc • Return to libc • 倘若若能得知 library 被 map

    到的隨機起始地址 (base address),則可以計 算出 libc 中 function 的位置,便便能調⽤用 library 中的函式。
  41. ret2libc • 關鍵為 bypass ASLR,找出 libc 的隨機 base • 透過

    information leak 漏洞洞,洩漏 memory 上的內容,獲取屬於 libc segment 的 address • 此 address 會是隨機的 base address 加上⼀一固定位移植 offset (不同版 本的 libc offset 不同)
  42. ret2libc • leaked_address - offset = base_address • 例例如,洩漏出 printf@got

    中的內容為 0x7fd0f9e57e80,⽽而已知 libc 版本為 2.27,可以 透過靜態分析 (readelf -s 等) 得知 printf function 在 library 中的 offset 為 0x64e80, 扣掉 offset 後求得此次執⾏行行 libc 的隨機 base address 是 0x7fd0f9df3000 = 0x7fd0f9e57e80 - 0x64e80 • 有 base 後就可以透過加上 offset 的⽅方式得知其他 function 的 address,來來 call 它,結 合 ROP 等等。 • system() = libc_base_address + system_offset
 = 0x7fd0f9df3000 + 0x4f440
 = 0x7fd0f9e42440
  43. Stack pivoting • ROP 需要很多的空間來來放置長串串的 ROP Chain,有時候並不會有那麼多的發揮空 間,可能很短甚⾄至只能控第⼀一次 rip (function

    pointer 等等),沒有⾜足夠的空間存放 ROP payload。 • 倘若若找到其他地⽅方有⾜足夠的空間放置 ROP payload,此時可以透過運⽤用較少的 gadget 數,來來將 stack 搬移⾄至 ROP payload 的位置,再進⾏行行 ROP,此作法即為 stack pivoting 或 stack migration。
  44. Stack pivoting • 很多作法 • leave; ret • overflow 時將

    rbp 填成 ROP Chain 的 address - 8, • return address 填 leave; ret gadget • pop rsp; ret • ⼿手動找針對各種當下情況的 gadget
  45. Stack pivoting low address high address AAAAAAAA AAAAAAAA AAAAAAAA trigger

    程式漏洞洞,僅能 overflow 16 bytes 恰只能剛好蓋到 return address rsp rbp
  46. Stack pivoting ["/bin/sh"] system pop rdi low address high address

    AAAAAAAA AAAAAAAA AAAAAAAA 找到他處可以⾜足夠放置 ROP payload 的空間 rsp rbp 0x601090 0xdeadbeef
  47. Stack pivoting low address high address leave; ret 0x601098 -

    8 AAAAAAAA rsp rbp ["/bin/sh"] system pop rdi 0x601090 0xdeadbeef
  48. Stack pivoting low address high address leave; ret 0x601090 AAAAAAAA

    rsp rbp ["/bin/sh"] system pop rdi 0x601090 0xdeadbeef
  49. Stack pivoting low address high address AAAAAAAA rsp rbp leave


    ret leave; ret 0x601090 ["/bin/sh"] system pop rdi 0x601090 0xdeadbeef
  50. Stack pivoting low address high address AAAAAAAA rsp rbp leave


    ret leave; ret 0x601090 ["/bin/sh"] system pop rdi 0x601090 0xdeadbeef mov rsp, rbp
 pop rbp
  51. Stack pivoting low address high address AAAAAAAA rsp rbp leave


    ret leave; ret 0x601090 ["/bin/sh"] system pop rdi 0x601090 0xdeadbeef mov rsp, rbp
 pop rbp
  52. Stack pivoting low address high address AAAAAAAA leave; ret 0x601090

    ["/bin/sh"] system pop rdi 0x601090 0xdeadbeef leave
 ret mov rsp, rbp
 pop rbp rsp rbp
  53. Stack pivoting low address high address AAAAAAAA rsp rbp leave


    ret leave; ret 0x601090 ["/bin/sh"] system pop rdi 0x601090 0xdeadbeef
  54. Stack pivoting low address high address AAAAAAAA rsp rbp leave


    ret leave; ret 0x601090 ["/bin/sh"] system pop rdi 0x601090 0xdeadbeef
  55. Stack pivoting low address high address AAAAAAAA rsp rbp leave


    ret leave; ret 0x601090 ["/bin/sh"] system pop rdi 0x601090 0xdeadbeef
  56. Stack pivoting low address high address AAAAAAAA rsp rbp leave


    ret leave; ret 0x601090 ["/bin/sh"] system pop rdi 0x601090 0xdeadbeef
  57. Stack pivoting low address high address AAAAAAAA rsp rbp leave;

    ret 0x601090 ["/bin/sh"] system pop rdi 0x601090 0xdeadbeef leave
 ret mov rsp, rbp
 pop rbp
  58. Stack pivoting low address high address AAAAAAAA rsp rbp leave;

    ret 0x601090 ["/bin/sh"] system pop rdi 0x601090 0xdeadbeef leave
 ret mov rsp, rbp
 pop rbp
  59. Stack pivoting low address high address AAAAAAAA rbp leave; ret

    0x601090 ["/bin/sh"] system pop rdi 0x601090 0xdeadbeef leave
 ret mov rsp, rbp
 pop rbp rsp 0xdeadbeef
  60. Stack pivoting low address high address AAAAAAAA rbp leave; ret

    0x601090 ["/bin/sh"] system pop rdi 0x601090 0xdeadbeef rsp 0xdeadbeef leave
 ret
  61. Stack pivoting low address high address AAAAAAAA rbp leave; ret

    0x601090 ["/bin/sh"] system pop rdi 0x601090 0xdeadbeef rsp 0xdeadbeef ROP!!!!
  62. Stack pivoting low address high address AAAAAAAA rbp leave; ret

    0x601090 ["/bin/sh"] system pop rdi 0x601090 0xdeadbeef rsp 0xdeadbeef system( "/bin/sh" )
  63. Stack pivoting low address high address AAAAAAAA rbp leave; ret

    0x601090 ["/bin/sh"] system pop rdi 0x601090 0xdeadbeef rsp 0xdeadbeef Get shell!
  64. Stack pivoting low address high address AAAAAAAA rbp leave; ret

    0x601090 ["/bin/sh"] system pop rdi 0x601090 0xdeadbeef rsp 0xdeadbeef Get shell! PWNED ☠
  65. ret2csu • 位於 __libc_csu_init 函式中,為 compiler 編進去的 function。 • 尾部有⼀一片段

    code,很適合拿來來控制 register 放置參參數,以及 control flow。
  66. ret2csu • __libc_csu_init 00000000004006d0 <__libc_csu_init>: 4006d0: 41 57 push r15

    4006d2: 41 56 push r14 4006d4: 49 89 d7 mov r15,rdx 4006d7: 41 55 push r13 4006d9: 41 54 push r12 4006db: 4c 8d 25 2e 07 20 00 lea r12,[rip+0x20072e] 4006e2: 55 push rbp 4006e3: 48 8d 2d 2e 07 20 00 lea rbp,[rip+0x20072e] 4006ea: 53 push rbx 4006eb: 41 89 fd mov r13d,edi 4006ee: 49 89 f6 mov r14,rsi 4006f1: 4c 29 e5 sub rbp,r12 4006f4: 48 83 ec 08 sub rsp,0x8 4006f8: 48 c1 fd 03 sar rbp,0x3 4006fc: e8 f7 fd ff ff call 4004f8 <_init> 400701: 48 85 ed test rbp,rbp 400704: 74 20 je 400726 <__libc_csu_init+0x56> 400706: 31 db xor ebx,ebx 400708: 0f 1f 84 00 00 00 00 nop DWORD PTR [rax+rax*1+0x0] 40070f: 00 400710: 4c 89 fa mov rdx,r15 400713: 4c 89 f6 mov rsi,r14 400716: 44 89 ef mov edi,r13d 400719: 41 ff 14 dc call QWORD PTR [r12+rbx*8] 40071d: 48 83 c3 01 add rbx,0x1 400721: 48 39 dd cmp rbp,rbx 400724: 75 ea jne 400710 <__libc_csu_init+0x40> 400726: 48 83 c4 08 add rsp,0x8 40072a: 5b pop rbx 40072b: 5d pop rbp 40072c: 41 5c pop r12 40072e: 41 5d pop r13 400730: 41 5e pop r14 400732: 41 5f pop r15 400734: c3 ret
  67. ret2csu • gadget 00000000004006d0 <__libc_csu_init>: 4006d0: 41 57 push r15

    4006d2: 41 56 push r14 4006d4: 49 89 d7 mov r15,rdx 4006d7: 41 55 push r13 4006d9: 41 54 push r12 4006db: 4c 8d 25 2e 07 20 00 lea r12,[rip+0x20072e] 4006e2: 55 push rbp 4006e3: 48 8d 2d 2e 07 20 00 lea rbp,[rip+0x20072e] 4006ea: 53 push rbx 4006eb: 41 89 fd mov r13d,edi 4006ee: 49 89 f6 mov r14,rsi 4006f1: 4c 29 e5 sub rbp,r12 4006f4: 48 83 ec 08 sub rsp,0x8 4006f8: 48 c1 fd 03 sar rbp,0x3 4006fc: e8 f7 fd ff ff call 4004f8 <_init> 400701: 48 85 ed test rbp,rbp 400704: 74 20 je 400726 <__libc_csu_init+0x56> 400706: 31 db xor ebx,ebx 400708: 0f 1f 84 00 00 00 00 nop DWORD PTR [rax+rax*1+0x0] 40070f: 00 400710: 4c 89 fa mov rdx,r15 400713: 4c 89 f6 mov rsi,r14 400716: 44 89 ef mov edi,r13d 400719: 41 ff 14 dc call QWORD PTR [r12+rbx*8] 40071d: 48 83 c3 01 add rbx,0x1 400721: 48 39 dd cmp rbp,rbx 400724: 75 ea jne 400710 <__libc_csu_init+0x40> 400726: 48 83 c4 08 add rsp,0x8 40072a: 5b pop rbx 40072b: 5d pop rbp 40072c: 41 5c pop r12 40072e: 41 5d pop r13 400730: 41 5e pop r14 400732: 41 5f pop r15 400734: c3 ret
  68. ret2csu 400710: 4c 89 fa mov rdx,r15 400713: 4c 89

    f6 mov rsi,r14 400716: 44 89 ef mov edi,r13d 400719: 41 ff 14 dc call QWORD PTR [r12+rbx*8] 40071d: 48 83 c3 01 add rbx,0x1 400721: 48 39 dd cmp rbp,rbx 400724: 75 ea jne 400710 <__libc_csu_init+0x40> 400726: 48 83 c4 08 add rsp,0x8 40072a: 5b pop rbx 40072b: 5d pop rbp 40072c: 41 5c pop r12 40072e: 41 5d pop r13 400730: 41 5e pop r14 400732: 41 5f pop r15 400734: c3 ret
  69. ret2csu • 透過控制 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。
  70. ret2csu 400710: 4c 89 fa mov rdx,r15 400713: 4c 89

    f6 mov rsi,r14 400716: 44 89 ef mov edi,r13d 400719: 41 ff 14 dc call QWORD PTR [r12+rbx*8] 40071d: 48 83 c3 01 add rbx,0x1 400721: 48 39 dd cmp rbp,rbx 400724: 75 ea jne 400710 <__libc_csu_init+0x40> 400726: 48 83 c4 08 add rsp,0x8 40072a: 5b pop rbx 40072b: 5d pop rbp 40072c: 41 5c pop r12 40072e: 41 5d pop r13 400730: 41 5e pop r14 400732: 41 5f pop r15 400734: c3 ret