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

Linux Pwn 101

adr
July 07, 2017

Linux Pwn 101

adr

July 07, 2017
Tweet

More Decks by adr

Other Decks in Technology

Transcript

  1. aaaddress1 // hackingWeekend 課程環境 • Ubuntu GNOME 訓練平台虛擬機⼀一份(*.ova) • GCC

    編譯 • GDB+PEDA 調試練習 • x86 ELF 練習題⽬目 • 關掉 ASLR • 練習題⽬目原始碼(*.C) • 虛擬機帳號 pwn 密碼 pwn
  2. aaaddress1 // hackingWeekend Pwn基礎知識篇章 1. 逆向⼯工程基礎(⼀一):記憶體 2. 逆向⼯工程基礎(⼆二):機械碼 3. 逆向⼯工程基礎(三):組合語⾔言

    • nasm 練習(⼀一) hello hacker! • nasm 練習(⼆二)sys_execve(/bin/sh) 4. 逆向⼯工程基礎(四):x86 Calling Convetion 5. gdb+peda 6. ipython+pwntools
  3. aaaddress1 // hackingWeekend Pwn實戰練習篇章 • Pwn 實例例: AIS3 Pwn1 •

    Pwn1 實戰練習: Touch Cat • Pwn2 實戰練習: bof • Pwn3 實戰練習: Secret Keeper
  4. aaaddress1 // hackingWeekend Bonus 篇章 1. Intel Syntax v.s. AT&T

    Syntax 2. ELF 架構、GOT、PLT 函數呼叫關係
  5. aaaddress1 // hackingWeekend 編譯/ 中介碼/ 直譯 • 編譯為原⽣生機械碼(Native)
 C、C++、Objective-C、Swfit、Go •

    編譯為中介碼(Intermediate Language, aka IL)
 .NET(C#, VB)、Java、Python(pyc) • 直譯(interpreting)
 Python、Ruby、Javascript、VBScript
  6. aaaddress1 // hackingWeekend 編譯/ 中介碼/ 直譯 • 編譯為原⽣生機械碼(Native)
 C、C++、Objective-C、Swfit、Go 原始碼

    執⾏行行檔 (機械碼) 逆向⼯工程理理解 從逆向⼯工程上只能理理解⼤大致上運作的過程, 並無法真正取得開發者的原始碼
  7. aaaddress1 // hackingWeekend 記憶體 addr 0 1 2 3 4

    5 6 7 8 9 A B C D E F 100 11 110 120 • 記憶體由⼀一個個格⼦子組成,每個格⼦子⼤大⼩小為 1 byte • 1 byte 可儲存 0 ~ 255 的數值(也就是 0x00 ~ 0xFF) • 每個格⼦子都有對應的記憶體地址編號 0x11 被存放在 0x100 的格⼦子上
  8. aaaddress1 // hackingWeekend 記憶體 addr 0 1 2 3 4

    5 6 7 8 9 A B C D E F 100 11 22 110 120 • 記憶體由⼀一個個格⼦子組成,每個格⼦子⼤大⼩小為 1 byte • 每個格⼦子都有對應的記憶體地址編號 0x22 被存放在 0x10F 的格⼦子上
  9. aaaddress1 // hackingWeekend 記憶體 addr 0 1 2 3 4

    5 6 7 8 9 A B C D E F 100 11 22 110 120 33 • 記憶體由⼀一個個格⼦子組成,每個格⼦子⼤大⼩小為 1 byte • 每個格⼦子都有對應的記憶體地址編號 0x33 被存放在 0x123 的格⼦子上
  10. aaaddress1 // hackingWeekend 記憶體 (int) addr 0 1 2 3

    4 5 6 7 8 9 A B C D E F 100 110 120 printf("size of int = %i\n", sizeof(int)); // size of int = 4
  11. aaaddress1 // hackingWeekend 記憶體 (int) addr 0 1 2 3

    4 5 6 7 8 9 A B C D E F 100 110 EF BE AD DE 120 int* ptr = (int *)(0x116); printf("data = %x\n", *ptr); // data = 0xDEADBEEF
  12. aaaddress1 // hackingWeekend 記憶體 (int) addr 0 1 2 3

    4 5 6 7 8 9 A B C D E F 100 110 EF BE AD DE 120 int* ptr = (int *)(0x116); printf("data = %x\n", *ptr); // data = 0xDEADBEEF little-endian
  13. aaaddress1 // hackingWeekend 記憶體 (int) 問題 addr 0 1 2

    3 4 5 6 7 8 9 A B C D E F 100 110 EF BE AD DE 120 int* ptr = (int *)(0x117); *ptr = 0xDEADBEEF;
  14. aaaddress1 // hackingWeekend 記憶體 (int) 問題 addr 0 1 2

    3 4 5 6 7 8 9 A B C D E F 100 110 EF EF BE AD DE 120 int* ptr = (int *)(0x117); *ptr = 0xDEADBEEF;
  15. aaaddress1 // hackingWeekend 記憶體 (array) addr 0 1 2 3

    4 5 6 7 8 9 A B C D E F 100 110 A4 A3 A2 A1 B1 B2 B3 B4 CC CC 120 CC CC int arr[3] = { 0xA1A2A3A4, 0xB4B3B2B1, 0xCCCCCCCC };
  16. aaaddress1 // hackingWeekend • ⼤大端序(big-endian)
 記憶體中擺放: AA BB CC DD


    
 • ⼩小端序(little-endian)
 記憶體中擺放: DD CC BB AA 位元組順序 以數值 0xAABBCCDD 為例例 https://zh.wikipedia.org/wiki/字节序
  17. aaaddress1 // hackingWeekend 機械碼 0 1 2 3 4 5

    6 7 8 9 A B C D E F 100 55 8B EC 83 EC 08 C7 45 F8 00 00 00 00 C7 45 FC 110 00 00 00 00 C7 45 F8 01 00 00 00 EB 09 8B 45 F8 120 83 C0 01 89 45 F8 8B 4D F8 3B 4D 08 7F 0B 8B 55 130 FC 03 55 F8 89 55 FC EB E4 8B 45 FC 50 68 30 60 140 40 00 E8 62 00 00 00 83 C4 08 8B E5 5D C3 在記憶體裡⾯面看得到的機械碼長得像這樣 (沒錯,就是那個經過編譯器處理理原始碼過後產⽣生的東⻄西)
  18. aaaddress1 // hackingWeekend 機械碼 0 1 2 3 4 5

    6 7 8 9 A B C D E F 100 55 8B EC 83 EC 08 C7 45 F8 00 00 00 00 C7 45 FC 110 00 00 00 00 C7 45 F8 01 00 00 00 EB 09 8B 45 F8 120 83 C0 01 89 45 F8 8B 4D F8 3B 4D 08 7F 0B 8B 55 130 FC 03 55 F8 89 55 FC EB E4 8B 45 FC 50 68 30 60 140 40 00 E8 62 00 00 00 83 C4 08 8B E5 5D C3 看不懂嗎?
  19. aaaddress1 // hackingWeekend 機械碼 0 1 2 3 4 5

    6 7 8 9 A B C D E F 100 55 8B EC 83 EC 08 C7 45 F8 00 00 00 00 C7 45 FC 110 00 00 00 00 C7 45 F8 01 00 00 00 EB 09 8B 45 F8 120 83 C0 01 89 45 F8 8B 4D F8 3B 4D 08 7F 0B 8B 55 130 FC 03 55 F8 89 55 FC EB E4 8B 45 FC 50 68 30 60 140 40 00 E8 62 00 00 00 83 C4 08 8B E5 5D C3 執⾏行行緒由 0x100 開始運⾏行行,fetch 到第⼀一個 byte 為 0x55
  20. aaaddress1 // hackingWeekend 機械碼 0 1 2 3 4 5

    6 7 8 9 A B C D E F 100 55 8B EC 83 EC 08 C7 45 F8 00 00 00 00 C7 45 FC 110 00 00 00 00 C7 45 F8 01 00 00 00 EB 09 8B 45 F8 120 83 C0 01 89 45 F8 8B 4D F8 3B 4D 08 7F 0B 8B 55 130 FC 03 55 F8 89 55 FC EB E4 8B 45 FC 50 68 30 60 140 40 00 E8 62 00 00 00 83 C4 08 8B E5 5D C3 反查 0x55 在 FF 乘法表上為 push ebp,接著讀下⼀一個指令
  21. aaaddress1 // hackingWeekend 機械碼 0 1 2 3 4 5

    6 7 8 9 A B C D E F 100 55 8B EC 83 EC 08 C7 45 F8 00 00 00 00 C7 45 FC 110 00 00 00 00 C7 45 F8 01 00 00 00 EB 09 8B 45 F8 120 83 C0 01 89 45 F8 8B 4D F8 3B 4D 08 7F 0B 8B 55 130 FC 03 55 F8 89 55 FC EB E4 8B 45 FC 50 68 30 60 140 40 00 E8 62 00 00 00 83 C4 08 8B E5 5D C3 反查 0x55 在 FF 乘法表上為 push ebp,接著讀下⼀一個指令
  22. aaaddress1 // hackingWeekend 機械碼 0 1 2 3 4 5

    6 7 8 9 A B C D E F 100 55 8B EC 83 EC 08 C7 45 F8 00 00 00 00 C7 45 FC 110 00 00 00 00 C7 45 F8 01 00 00 00 EB 09 8B 45 F8 120 83 C0 01 89 45 F8 8B 4D F8 3B 4D 08 7F 0B 8B 55 130 FC 03 55 F8 89 55 FC EB E4 8B 45 FC 50 68 30 60 140 40 00 E8 62 00 00 00 83 C4 08 8B E5 5D C3 fetch 到 0x8B 為 mov Gv, Ev,讀取到下⼀一個 byte 為 0xEC, 可以得知 8B, EC 的意思對應為:mov ebp, esp
  23. aaaddress1 // hackingWeekend void print_sum(int num_in) { int i =

    0, sum = 0; for (i = 1; i <= num_in; i++) sum += i; printf("sum: %i\n", sum); } 開發者的程式碼
  24. aaaddress1 // hackingWeekend .text:00401006 mov [ebp+var_8], 0 .text:0040100D mov [ebp+var_4],

    0 .text:00401014 mov [ebp+var_8], 1 .text:0040101B jmp short loc_401026 .text:0040101D loc_40101D: .text:0040101D mov eax, [ebp+var_8] .text:00401020 add eax, 1 .text:00401023 mov [ebp+var_8], eax .text:00401026 loc_401026: .text:00401026 mov ecx, [ebp+var_8] .text:00401029 cmp ecx, [ebp+arg_0] .text:0040102C jg short loc_401039 .text:0040102E mov edx, [ebp+var_4] .text:00401031 add edx, [ebp+var_8] .text:00401034 mov [ebp+var_4], edx .text:00401037 jmp short loc_40101D .text:00401039 loc_401039: .text:00401039 mov eax, [ebp+var_4] .text:0040103C push eax .text:0040103D push offset aSumI ; "sum: %i\n" .text:00401042 call _printf 組合語⾔言
  25. aaaddress1 // hackingWeekend 暫存器公定⽤用法 ⼤大家約好必須這樣做(ㄩㄇ) EAX EBX ECX EDX ESI

    EDI ESP EBP EIP 指向堆疊(Stack) 指向下⼀一⾏行行指令地址 當層函數的堆疊基礎指標
  26. aaaddress1 // hackingWeekend EAX EBX ECX EDX ESI EDI ESP

    EBP EIP 很常拿來來被當⽬目標 Index ⽤用 (特別是字串串拷⾙貝) 很常被拿來來當來來源 Index ⽤用 (特別是字串串拷⾙貝) 慣性被拿來來當暫時⽤用變數 與函數回傳值 暫存器不成⽂文約定... ⼤大家很愛這麼做,但事實上沒特別規定這樣做 很常被拿來來儲存某個指標 被當計數器⽤用
  27. aaaddress1 // hackingWeekend EAX EBX ECX EDX ESI EDI ESP

    EBP EIP 很常拿來來被當⽬目標 Index ⽤用 (特別是字串串拷⾙貝) 很常被拿來來當來來源 Index ⽤用 (特別是字串串拷⾙貝) 慣性被拿來來當暫時⽤用變數 與函數回傳值 暫存器不成⽂文約定... 不要問我為什什麼,我真的不知道XD(不⽤用死記) 很常被拿來來儲存某個指標 被當計數器⽤用
  28. aaaddress1 // hackingWeekend 組合語⾔言 • 指令集定義在那張 FF 指令表上(⼤大部分啦) • 指令形式如下


    opcode arg1, arg2, arg3 • 常⾒見見指令如 add、sub、mul、div(加減乘除) • add eax, ebx //eax = (eax + ebx) • [arg] 即為將 arg 當作 pointer ⽤用(*arg)
  29. aaaddress1 // hackingWeekend • mov eax, ebx
 //eax = ebx

    • mov [eax], ebx 
 mov dword ptr [eax], ebx
 // *(dword*)eax = ebx • mov [ax], bx
 mov word ptr [ax], bx
 // *(word*)eax = bx • mov [al], bl
 mov byte ptr [al], bl
 // *((byte*)eax) = bl 基本運算 搬移
  30. aaaddress1 // hackingWeekend 舉個 mov eax , 0xDEADBEEF mov [eax],

    0xEA7C0FEE addr 0 1 2 3 4 5 6 7 8 9 A B C D E F DEADBEEF EE 0F 7C EA
  31. aaaddress1 // hackingWeekend • add eax, ebx //eax += ebx

    • sub eax, ebx //eax -= ebx • inc eax //eax ++ • dec eax //eax -- 基本運算 加法、減法
  32. aaaddress1 // hackingWeekend • cmp eax, ebx // T =

    eax - ebx • je 0xdead // if (T==0) EIP=0xdead • jl 0xbeef // if (T <0) EIP=0xbeef • jg 0xf00d // if (T >0) EIP=0xf00d • jle 0xb00c // if (T<=0) EIP=0xb00c • jmp 0xcafe // EIP = 0xcafe 基本運算 比對、跳轉
  33. aaaddress1 // hackingWeekend 基本運算 無號數乘法 mov eax, 0x02 mov edx,

    0x03 mul edx 結果: eax = 6, edx = 0 mov eax, 0x02 mov edx, 0x03 mul eax 結果: eax = 4, edx = 0 mul 將 eax 乘 乘數 後,答案為 8bytes ⾼高 4bytes 寫入 edx、低 4bytes 寫入 eax
  34. aaaddress1 // hackingWeekend 基本運算 無號數乘法 mov eax, 0x02 mov edx,

    0xFFFFFFFF mul edx 結果: eax = 0xFFFFFFFE, edx = 0x00000001, Carry = 1, Overflow = 1 mul 將 eax 乘 乘數 後,答案為 8bytes ⾼高 4bytes 寫入 edx、低 4bytes 寫入 eax
  35. aaaddress1 // hackingWeekend 基本運算 有號數乘法 mov eax, 0x02 mov edx,

    0x03 imul edx 結果: eax = 6, edx = 0 mov eax, -2 mov edx, 3 imul eax 結果: eax = 0xFFFFFFFA, edx = 0xFFFFFFFF imul 將 eax 乘 乘數 後,答案為 8bytes ⾼高 4bytes 寫入 edx、低 4bytes 寫入 eax
  36. aaaddress1 // hackingWeekend 基本運算 無號數除法 mov eax, 0x7 mov ecx,

    0x2 mov edx, 0x0 div ecx 結果: eax = 3, edx = 1, ecx = 2 div 將 eax 除 除數 後,答案為 8bytes 結果寫入 eax,餘數寫入 edx *使⽤用 div 前記得將 edx 清為 0
  37. aaaddress1 // hackingWeekend 基本運算 有號數除法 mov eax, 0x7 mov ecx,

    0x2 mov edx, 0x0 idiv ecx 結果: eax = 3, edx = 1, ecx = 2 idiv 將 eax 除 除數 後,答案為 8bytes 結果寫入 eax,餘數寫入 edx *使⽤用 idiv 前記得將 edx 清為 0
  38. aaaddress1 // hackingWeekend 堆疊(Stack) 堆疊 堆疊 1 2 3 12FFF8

    12FFF4 12FFF0 記憶體位址 push 1 push 2 push 3
  39. aaaddress1 // hackingWeekend 堆疊(Stack) 堆疊 1 2 3 12FFF8 12FFF4

    12FFF0 記憶體位址 越早推入堆疊的資料所在的記憶體地址越⾼高; 越晚推入堆疊的資料所在的記憶體地址越低。
  40. aaaddress1 // hackingWeekend 堆疊(Stack) push 01 = sub esp, 4;

    mov [esp], 01 pop eax = mov eax,[esp]; add esp, 04 堆疊 1 2 3 12FFF8 12FFF4 12FFF0 記憶體位址
  41. aaaddress1 // hackingWeekend $ nasm -felf32 hello.asm 根據 hello.asm 組合語⾔言指令內容

    產出對應 x86 指令集的 object file(hello.o) $ objdump -d ./hello.o -M intel ./hello.o: file format elf32-i386 Disassembly of section .text: 00000000 <_start>: 0: ba 0f 00 00 00 mov edx,0xf 5: b9 22 00 00 00 mov ecx,0x22 a: bb 01 00 00 00 mov ebx,0x1 f: b8 04 00 00 00 mov eax,0x4 14: cd 80 int 0x80 16: bb ff 00 00 00 mov ebx,0xff 1b: b8 01 00 00 00 mov eax,0x1 20: cd 80 int 0x80
  42. aaaddress1 // hackingWeekend $ ld -m elf_i386 -o hello hello.o

    連結器將 hello.o(object file)產出 x86 elf(hello) $ ld -m elf_i386 -o hello hello.o $ file hello hello: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), statically linked, not stripped $ ./hello hello, hacker!
  43. aaaddress1 // hackingWeekend 呼叫約制 Calling Convention add(1, 2, 3) int

    add(int a, int b, int c) { int tmp = (a + b + c); return tmp; }
  44. aaaddress1 // hackingWeekend 呼叫約制 Calling Convention push 3 push 2

    push 1 call add add esp,0x0C //add(1, 2, 3) int add(int a, int b, int c) { int tmp = (a + b + c); return tmp; } 1. 參參數由右⾄至左推入堆疊中 2. 呼叫者負責清理理堆疊(stdcall)
  45. aaaddress1 // hackingWeekend 呼叫約制 Calling Convention push 3 push 2

    push 1 call add add esp,0x0C //add(1, 2, 3) 堆疊 堆疊 12FFF8 12FFF4 12FFF0 記憶體位址 esp 3
  46. aaaddress1 // hackingWeekend 呼叫約制 Calling Convention push 3 push 2

    push 1 call add add esp,0x0C //add(1, 2, 3) 堆疊 堆疊 12FFF8 12FFF4 12FFF0 記憶體位址 esp 3
  47. aaaddress1 // hackingWeekend 呼叫約制 Calling Convention push 3 push 2

    push 1 call add add esp,0x0C //add(1, 2, 3) 堆疊 堆疊 12FFF8 12FFF4 12FFF0 記憶體位址 esp 3 2
  48. aaaddress1 // hackingWeekend 呼叫約制 Calling Convention push 3 push 2

    push 1 call add add esp,0x0C //add(1, 2, 3) 堆疊 堆疊 12FFF8 12FFF4 12FFF0 記憶體位址 esp 3 2
  49. aaaddress1 // hackingWeekend 呼叫約制 Calling Convention push 3 push 2

    push 1 call add add esp,0x0C //add(1, 2, 3) 堆疊 堆疊 12FFF8 12FFF4 12FFF0 記憶體位址 esp 3 2 1
  50. aaaddress1 // hackingWeekend 呼叫約制 Calling Convention push 3 push 2

    push 1 call add add esp,0x0C //add(1, 2, 3) 堆疊 堆疊 12FFF8 12FFF4 12FFF0 記憶體位址 esp 3 2 1 12FFEC
  51. aaaddress1 // hackingWeekend 呼叫約制 Calling Convention push 3 push 2

    push 1 call add add esp,0x0C //add(1, 2, 3) 堆疊 堆疊 12FFF8 12FFF4 12FFF0 記憶體位址 esp 3 2 1 12FFEC return addr
  52. aaaddress1 // hackingWeekend 呼叫約制 Calling Convention push 3 push 2

    push 1 call add add esp,0x0C //add(1, 2, 3) 堆疊 堆疊 12FFF8 12FFF4 12FFF0 記憶體位址 esp 3 2 1 12FFEC 12FFE8 return addr
  53. aaaddress1 // hackingWeekend 呼叫約制 Calling Convention add: push ebp mov

    ebp, esp sub esp, 0x04 mov eax, [ebp+0x08] add eax, [ebp+0x0C] add eax, [ebp+0x10] mov [ebp-0x04], eax mov eax, [ebp-0x04] mov esp, ebp pop ebp ret 堆疊 堆疊 12FFF8 12FFF4 12FFF0 記憶體位址 esp 3 2 1 12FFEC 12FFE8 return addr
  54. aaaddress1 // hackingWeekend 呼叫約制 Calling Convention add: push ebp mov

    ebp, esp sub esp, 0x04 mov eax, [ebp+0x08] add eax, [ebp+0x0C] add eax, [ebp+0x10] mov [ebp-0x04], eax mov eax, [ebp-0x04] mov esp, ebp pop ebp ret 堆疊 堆疊 12FFF8 12FFF4 12FFF0 記憶體位址 esp 3 2 1 12FFEC caller ebp 12FFE8 return addr
  55. aaaddress1 // hackingWeekend 呼叫約制 Calling Convention add: push ebp mov

    ebp, esp sub esp, 0x04 mov eax, [ebp+0x08] add eax, [ebp+0x0C] add eax, [ebp+0x10] mov [ebp-0x04], eax mov eax, [ebp-0x04] mov esp, ebp pop ebp ret 堆疊 堆疊 12FFF8 12FFF4 12FFF0 記憶體位址 esp 3 2 1 12FFEC ebp 12FFE8 return addr caller ebp
  56. aaaddress1 // hackingWeekend add: push ebp mov ebp, esp sub

    esp, 0x04 mov eax, [ebp+0x08] add eax, [ebp+0x0C] add eax, [ebp+0x10] mov [ebp-0x04], eax mov eax, [ebp-0x04] mov esp, ebp pop ebp ret 堆疊 堆疊 12FFF8 12FFF4 12FFF0 記憶體位址 esp 3 2 1 12FFEC 12FFE8 ebp 12FFE4 呼叫約制 Calling Convention return addr caller ebp local buffer
  57. aaaddress1 // hackingWeekend add: push ebp mov ebp, esp sub

    esp, 0x04 mov eax, [ebp+0x08] add eax, [ebp+0x0C] add eax, [ebp+0x10] mov [ebp-0x04], eax mov eax, [ebp-0x04] mov esp, ebp pop ebp ret 堆疊 堆疊 12FFF8 12FFF4 12FFF0 記憶體位址 esp 3 2 1 12FFEC 12FFE8 ebp 12FFE4 呼叫約制 Calling Convention EAX: 1 return addr caller ebp local buffer
  58. aaaddress1 // hackingWeekend add: push ebp mov ebp, esp sub

    esp, 0x04 mov eax, [ebp+0x08] add eax, [ebp+0x0C] add eax, [ebp+0x10] mov [ebp-0x04], eax mov eax, [ebp-0x04] mov esp, ebp pop ebp ret 堆疊 堆疊 12FFF8 12FFF4 12FFF0 記憶體位址 esp 3 2 1 12FFEC 12FFE8 ebp 12FFE4 呼叫約制 Calling Convention EAX: 1+2 return addr caller ebp local buffer
  59. aaaddress1 // hackingWeekend add: push ebp mov ebp, esp sub

    esp, 0x04 mov eax, [ebp+0x08] add eax, [ebp+0x0C] add eax, [ebp+0x10] mov [ebp-0x04], eax mov eax, [ebp-0x04] mov esp, ebp pop ebp ret 堆疊 堆疊 12FFF8 12FFF4 12FFF0 記憶體位址 esp 3 2 1 12FFEC 12FFE8 ebp 12FFE4 呼叫約制 Calling Convention local buffer EAX: 1+2+3 return addr caller ebp
  60. aaaddress1 // hackingWeekend add: push ebp mov ebp, esp sub

    esp, 0x04 mov eax, [ebp+0x08] add eax, [ebp+0x0C] add eax, [ebp+0x10] mov [ebp-0x04], eax mov eax, [ebp-0x04] mov esp, ebp pop ebp ret 堆疊 堆疊 12FFF8 12FFF4 12FFF0 記憶體位址 esp 3 2 1 12FFEC 12FFE8 ebp 12FFE4 呼叫約制 Calling Convention 6 EAX: 1+2+3 return addr caller ebp
  61. aaaddress1 // hackingWeekend add: push ebp mov ebp, esp sub

    esp, 0x04 mov eax, [ebp+0x08] add eax, [ebp+0x0C] add eax, [ebp+0x10] mov [ebp-0x04], eax mov eax, [ebp-0x04] mov esp, ebp pop ebp ret 堆疊 堆疊 12FFF8 12FFF4 12FFF0 記憶體位址 esp 3 2 1 12FFEC 12FFE8 ebp 12FFE4 呼叫約制 Calling Convention EAX: 1+2+3 return addr 6 caller ebp
  62. aaaddress1 // hackingWeekend add: push ebp mov ebp, esp sub

    esp, 0x04 mov eax, [ebp+0x08] add eax, [ebp+0x0C] add eax, [ebp+0x10] mov [ebp-0x04], eax mov eax, [ebp-0x04] mov esp, ebp pop ebp ret 堆疊 堆疊 12FFF8 12FFF4 12FFF0 記憶體位址 3 2 1 12FFEC 12FFE8 12FFE4 呼叫約制 Calling Convention EAX: 1+2+3 esp ebp return addr 6 caller ebp
  63. aaaddress1 // hackingWeekend add: push ebp mov ebp, esp sub

    esp, 0x04 mov eax, [ebp+0x08] add eax, [ebp+0x0C] add eax, [ebp+0x10] mov [ebp-0x04], eax mov eax, [ebp-0x04] mov esp, ebp pop ebp ret 堆疊 堆疊 12FFF8 12FFF4 12FFF0 記憶體位址 3 2 1 12FFEC 12FFE8 12FFE4 呼叫約制 Calling Convention EAX: 1+2+3 esp return addr 6 caller ebp
  64. aaaddress1 // hackingWeekend add: push ebp mov ebp, esp sub

    esp, 0x04 mov eax, [ebp+0x08] add eax, [ebp+0x0C] add eax, [ebp+0x10] mov [ebp-0x04], eax mov eax, [ebp-0x04] mov esp, ebp pop ebp ret 堆疊 堆疊 12FFF8 12FFF4 12FFF0 記憶體位址 3 2 1 12FFEC 12FFE8 12FFE4 呼叫約制 Calling Convention EAX: 1+2+3 esp EBP: caller ebp return addr 6 caller ebp
  65. aaaddress1 // hackingWeekend add: push ebp mov ebp, esp sub

    esp, 0x04 mov eax, [ebp+0x08] add eax, [ebp+0x0C] add eax, [ebp+0x10] mov [ebp-0x04], eax mov eax, [ebp-0x04] mov esp, ebp pop ebp ret 堆疊 堆疊 12FFF8 12FFF4 12FFF0 記憶體位址 3 2 1 12FFEC 12FFE8 12FFE4 呼叫約制 Calling Convention EAX: 1+2+3 esp EBP: caller ebp EIP: return addr return addr 6 caller ebp
  66. aaaddress1 // hackingWeekend 堆疊 堆疊 12FFF8 12FFF4 12FFF0 記憶體位址 3

    2 1 12FFEC 12FFE8 12FFE4 呼叫約制 Calling Convention EAX: 1+2+3 esp EBP: caller ebp push 3 push 2 push 1 call add add esp,0x0C //add(1, 2, 3) return addr 6 caller ebp
  67. aaaddress1 // hackingWeekend 堆疊 堆疊 12FFF8 12FFF4 12FFF0 記憶體位址 3

    2 1 12FFEC 12FFE8 12FFE4 呼叫約制 Calling Convention EAX: 1+2+3 esp push 3 push 2 push 1 call add add esp,0x0C //add(1, 2, 3) return addr 6 caller ebp
  68. aaaddress1 // hackingWeekend 堆疊 堆疊 12FFF8 12FFF4 12FFF0 記憶體位址 12FFEC

    12FFE8 12FFE4 呼叫約制 Calling Convention EAX: 1+2+3 esp push 3 push 2 push 1 call add add esp,0x0C //add(1, 2, 3)
  69. aaaddress1 // hackingWeekend 堆疊 堆疊 12FFF8 12FFF4 12FFF0 記憶體位址 12FFEC

    12FFE8 12FFE4 懶懶⼈人筆記 esp 1. esp 永遠指向 Stack 最⾼高處
 2. [ebp] 保存呼叫者 base pointer
 3. [ebp+4] 指向 return address
 4. [ebp+8+4*0] 為第⼀一個參參數
 [ebp+8+4*1] 為第⼆二個參參數
 [ebp+8+4*2] 為第三個參參數
 ...etc ebp arg 3 arg 2 arg 1 return addr caller ebp 區域變數1 區域變數2 12FFE0 12FFDC 12FFD8 12FFD4 區域變數3
  70. aaaddress1 // hackingWeekend 堆疊 堆疊 12FFF8 12FFF4 12FFF0 記憶體位址 12FFEC

    12FFE8 12FFE4 懶懶⼈人筆記 esp ebp 區域變數1 區域變數2 12FFE0 12FFDC 12FFD8 12FFD4 區域變數3 void func ( int arg1, int* arg2, char* arg3 ){ int buffer = 0; int arr[3]; char data[2]; /* do something */ } arg 3 arg 2 arg 1 return addr caller ebp
  71. aaaddress1 // hackingWeekend $ gdb ./a.out gdb-peda$ disassemble add Dump

    of assembler code for function add: 0x0804840b <+0>: push ebp 0x0804840c <+1>: mov ebp,esp 0x0804840e <+3>: sub esp,0x10 0x08048411 <+6>: mov edx,DWORD PTR [ebp+0x8] 0x08048414 <+9>: mov eax,DWORD PTR [ebp+0xc] 0x08048417 <+12>: add edx,eax 0x08048419 <+14>: mov eax,DWORD PTR [ebp+0x10] 0x0804841c <+17>: add eax,edx 0x0804841e <+19>: mov DWORD PTR [ebp-0x4],eax 0x08048421 <+22>: mov eax,DWORD PTR [ebp-0x4] 0x08048424 <+25>: leave 0x08048425 <+26>: ret End of assembler dump.
  72. aaaddress1 // hackingWeekend breakpoint: gdb-peda$ b *函數名稱 / b *記憶體地址

    ←下斷點 run: gdb-peda$ r ←開始運⾏行行 / 重新創建⼀一個 Process gdb-peda$ r < a.txt ¬開始運⾏行行、並將 a.txt ⽂文字內容傳入作為 input step: gdb-peda$ s ←單步跟蹤 next: gdb-peda$ n ←躍過跟蹤 / 單步跟蹤但不進入 call
  73. aaaddress1 // hackingWeekend 正常的 system 在進入函數前, 會推入字串串指令地址、call會推入 reutrn address。 所以

    Payload 內部得構造為: padding + [eip = system@plt] + [sytem執⾏行行後返回地址] + [/bin/sh 地址] 0x0804851e <+03>: push <指令字串串的地址> 0x08048523 <+08>: call 0x80483d0 <system@plt> 0x08048528 <+13>: add esp,0x4
  74. aaaddress1 // hackingWeekend Executable and Linkable Format In computing, the

    Executable and Linkable Format (ELF, formerly named Extensible Linking Format), is a common standard file format for executable files, object code, shared libraries, and core dumps. In 1999, it was chosen as the standard binary file format for Unix and Unix-like systems on x86 processors by the 86open project. refer: en.wikipedia.org/wiki/Executable_and_Linkable_Format
  75. aaaddress1 // hackingWeekend Process 100 110 120 130 140 150

    160 … 當⼀一⽀支執⾏行行⽂文件被點擊時, 會建立為⼀一個 Process(處理理序)內保存執⾏行行⽂文件的機械碼 Executable and Linkable Format
  76. aaaddress1 // hackingWeekend Process 100 A A A A A

    A . . . 110 120 130 140 150 160 … B B B B B B B B B B B B B B B B 不過作業系統不會真的直接開⼀一⼤大片記憶體保存執⾏行行⽂文件內容 Executable and Linkable Format
  77. aaaddress1 // hackingWeekend $ objdump -s a.out Contents of section

    .text: 400430 31ed4989 d15e4889 e24883e4 f0505449 1.I..^H..H...PTI 400440 c7c0b005 400048c7 c1400540 0048c7c7 [email protected]..@[email protected].. 400450 26054000 e8b7ffff fff4660f 1f440000 &[email protected].. 400460 b83f1060 0055482d 38106000 4883f80e .?.`.UH-8.`.H... 400470 4889e576 1bb80000 00004885 c074115d H..v......H..t.] 400480 bf381060 00ffe066 0f1f8400 00000000 .8.`...f........ 400490 5dc30f1f 4000662e 0f1f8400 00000000 ][email protected]......... 4004a0 be381060 00554881 ee381060 0048c1fe .8.`.UH..8.`.H.. 4004b0 034889e5 4889f048 c1e83f48 01c648d1 .H..H..H..?H..H. 4004c0 fe7415b8 00000000 4885c074 0b5dbf38 .t......H..t.].8 4004d0 106000ff e00f1f00 5dc3660f 1f440000 .`......].f..D.. 4004e0 803d510b 20000075 11554889 e5e86eff .=Q. ..u.UH...n. 4004f0 ffff5dc6 053e0b20 0001f3c3 0f1f4000 ..]..>. ......@. 400500 bf200e60 0048833f 007505eb 930f1f00 . .`.H.?.u...... 400510 b8000000 004885c0 74f15548 89e5ffd0 .....H..t.UH....
  78. aaaddress1 // hackingWeekend $ objdump -d ./a.out Disassembly of section

    .text: 0000000000400430 <_start>: 400430: 31 ed xor %ebp,%ebp 400432: 49 89 d1 mov %rdx,%r9 400435: 5e pop %rsi 400436: 48 89 e2 mov %rsp,%rdx 400439: 48 83 e4 f0 and $0xfffffffffffffff0,%rsp 40043d: 50 push %rax 40043e: 54 push %rsp 40043f: 49 c7 c0 b0 05 40 00 mov $0x4005b0,%r8 400446: 48 c7 c1 40 05 40 00 mov $0x400540,%rcx 40044d: 48 c7 c7 26 05 40 00 mov $0x400526,%rdi 400454: e8 b7 ff ff ff callq 400410 <__libc_start_main@plt> 400459: f4 hlt 40045a: 66 0f 1f 44 00 00 nopw 0x0(%rax,%rax,1) main function
  79. aaaddress1 // hackingWeekend $ gdb ./a.out gdb-peda$ info functions Non-debugging

    symbols: 0x00000000004003c8 _init 0x0000000000400400 puts@plt 0x0000000000400410 __libc_start_main@plt 0x0000000000400430 _start ... 0x0000000000400500 frame_dummy 0x0000000000400526 main 0x0000000000400540 __libc_csu_init 0x00000000004005b0 __libc_csu_fini ... 0x00007ffff7a2c820 memalign@plt 0x00007ffff7a2c850 _dl_find_dso_for_object@plt 0x00007ffff7a2c870 calloc@plt
  80. aaaddress1 // hackingWeekend gdb-peda$ b *main Breakpoint 1 at 0x400526

    gdb-peda$ r Starting program: /home/pwn/Desktop/a.out