栈溢出笔记1.4 黑掉example_2
在1.2節中我們編寫了一個有漏洞的程序,通過輸入可以控制其EIP,本節,我們要讓example_2運行我們的MessageBox。再看看example_2:
/*****************************************************************************/ // example_2: 演示棧溢出 #include <stdio.h>void get_print() { char str[11]; gets(str); printf("%s\n", str); }int main() { get_print(); return 0; } /*****************************************************************************/- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
問題出在gets函數,要運行MessageBox,我們可以通過gets沒有長度限制來輸入1.3節中的Shellcode,但實際情況不像 example_4那么簡單,有不少問題要解決。
(1)空字符?
操作碼含有不少空字符,在example_4中沒有什么問題,因為它實際上并不是一個字符串,而是一段指令。但是現在,我們只能通過gets函數輸入這段指令,因此,它必須被當做一個字符串讀入。所以,它不能包含空字符。這個問題容易解決,只要把帶有空字符的指令用等效的指令替換就可以了。例如,可以把PUSH 0 換為: XOR EAX,EAX; PUSH EAX。?
修改后的程序如下:
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
這里說明一個東西——指令前綴,在操作碼中會用冒號隔開,但是冒號本身不是操作碼的一部分,提取操作碼的時候不要加入冒號。如下:?
?
圖27
(2)無法輸入的字符?
如果只是abcd這種常見字符,很容易輸入,但是操作碼中含有一些無法輸入的字符。例如,example_7中的操作碼打印出來是這樣子的:
圖28
這個問題很容易解決,cmd命令行中有管道命令,因此,可以通過管道命令向example_2輸入。用一個程序將Shellcode打印出來,然后通過管道輸入到example_2即可。
(3)EIP修改為多少??
這也是最重要的問題,因為我們的目的就是控制EIP執行輸入的Shellcode。那EIP修改為多少呢?當然是修改為Shellcode的首地址。但是不像 example_4中,我們明確指定Shellcode的地址,現在我們不知道。這由幾種辦法來解決,我們先用最笨的辦法,即通過Immunity Debugger找到這個地址。?
用Immunity Debugger打開example_2,這次,我們輸入16個A和4個B,以及一大串C,?
在get_print函數中POP EBP處下斷點:?
?
圖29
查看棧的內容:?
?
圖30
BBBB為返回地址(EIP),因此,Shellcode起始地址為0x0012FF1C。
為了黑example_2,需要修改Shellcode,要在首部填充16個A(正常輸入+填充EBP),然后填充0x0012FF1C,然后是原Shellcode。你注意到問題了嗎?對的,EIP的填充地址0x0012FF1C,包含了空字符,這次,我們無法再替換掉它,而且,地址必須為四字節。因此,這種方法行不通。看來,想偷下懶都不行了。
我們需要另辟蹊徑了。那么,還有什么是與棧上這個地址有關呢?與棧最密切的是EBP,ESP這兩個寄存器,說到這,你可能已經知道了。是的,函數RET指令返回時取走保存的EIP之后,ESP指向的位置就是Shellcode的初始地址。
?
圖31
因此,要讓程序執行Shellcode,只需要一句 jmp esp就行了。所以,我們應該把EIP填充為一句jmp esp指令的地址,這樣,EIP返回后,執行一句jmp esp,然后就跳轉到Shellcode開始執行。但是,example_2中沒有jmp esp,因此,我們需要在其它模塊中找一條該指令。在Immunity Debugger中,右鍵Search for——All commands in all modules,鍵入jmp esp,查找結果如下:
?
圖32
在MSVCR90D.dll和kernel32.dll中各找到一條,我們使用kernel32.dll中的,記下其地址:0x7c86467B。這個地址是可用的,不包含空字符。
下面是輸出Shellcode的程序,它將通過管道將Shellcode輸入給example_2:
/*****************************************************************************/ // example_5 打印Shellcode #include <stdio.h>char opcode[] = "AAAAAAAAAAAAAAAA\x7B\x46\x86\x7c" "\x55\x8B\xEC\x33\xC0\x66\xB8\x6C\x64\x50\x68\x6F\x57\x6F\x72\x68\x48\x65\x6C\x6C\x6A\x31\x68\x70\x6C\x65\x5F" "\x68\x65\x78\x61\x6D\x66\xB8\x6C\x6C\x50\x68\x33\x32\x2E\x64\x68\x75\x73\x65\x72\x8D\x5D\xDC\x53\xBB\x7B" "\x1D\x80\x7C\xFF\xD3\x33\xC0\x50\x8D\x5D\xE8\x53\x8D\x5D\xF4\x53\x50\xBB\xEA\x07\xD5\x77\xFF\xD3" "\x50\xBB\xFA\xCA\x81\x7C\xFF\xD3"; int main() {printf("%s", opcode); } /*****************************************************************************/- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
下面是見證奇跡的時刻,在命令行下輸入如下內容:?
?
圖33
彈出了MessageBox,我們成功的黑掉了具有漏洞的example_2。
新人創作打卡挑戰賽發博客就能抽獎!定制產品紅包拿不停!總結
以上是生活随笔為你收集整理的栈溢出笔记1.4 黑掉example_2的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: x86汇编指令详解
- 下一篇: C# App.config全攻略