C语言实现缓冲区溢出实例
參考書目:0day安全:軟件漏洞分析技術(shù)?
相關(guān)工具使用:OD,IDA Pro,VC++6.0,UltraEdit
最近需要做課堂演習,就選了緩沖區(qū)溢出的實踐。主要參考0day安全這本書,一面一句話很經(jīng)典:?
To be the apostrophe which changed Impossible into I’m possible!
直接步入正題:
1. 反匯編修改程序
在實現(xiàn)緩沖區(qū)溢出之前,簡單熟悉一下反匯編重用的兩個軟件,OD和IDA,用OD修改程序代碼實例。
#include <stdio.h> #define PASSWORD "1234567" int verify(char *password) {int auth;auth = strcmp(password, PASSWORD);return auth; }int main(void){int flag = 0;char pass[1024];while(1){printf("enter the password:\t");scanf("%s", pass);flag = verify(pass);if(flag)printf("password incorrect!\n");else{printf("congratulation!\n");break;}} }- 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
- 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
代碼就是簡單驗證輸入密碼是否正確,首先用IDA打開編譯生成的應(yīng)用程序。看到這樣一個圖(好像每次打開生成的東西都不太一樣~)?
如果看不到地址可以在Options->General在Line prefixes前打鉤以及將Number of opcode bytes設(shè)置為6就可以了。這樣就可以找到代碼中相應(yīng)的跳轉(zhuǎn)部分,然后用OD打開對應(yīng)的EXE文件,看到下圖:?
?
找到004010D5這條命令就是對應(yīng)的判斷地方了,對應(yīng)的匯編命令為:
- 1
- 1
于是將JE改成JNE,再運行程序,這時發(fā)現(xiàn)原來正確的密碼不正確,原來錯誤密碼都可以通過!用OD還可以對程序保存,一個簡單的破解就完成了。(OD保存軟件不會的話可以網(wǎng)上搜一下,我當時沒搞懂還是請教的大神)
2. 緩沖區(qū)溢出漏洞修改鄰接變量
還是剛剛的類似程序,假如程序員一不小心或者因為要在其他地方使用字符串,加了個strcpy函數(shù),驗證函數(shù)如下所示:
int verify(char *password) {int auth;char buffer[8];auth = strcmp(password, PASSWORD);strcpy(buffer, password);return auth; }- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
?
啊,原來是這樣啊,輸入qqqqqqqq,或者輸入其他8位也行(11111111不行,自己探索吧)在strcmp的時候auth確實是1,但是在進行strcpy之后,buffer里面的數(shù)據(jù)太長了,占了auth的位置,將auth從1改成了0。?
看來下次寫程序要注意點了!
3. 修改程序執(zhí)行流程
是看了上面的原理圖,是不是懂了點什么!EBP和返回地址是啥?不禁心生惡意,我要是再長點,是不是把返回地址給換了???還有那個EBP啥東西???
事實上,EBP是PE文件執(zhí)行時候在函數(shù)調(diào)用時函數(shù)調(diào)用前棧底指針,在函數(shù)調(diào)用時會重新生成一個比較小的棧,此新棧為調(diào)用的函數(shù)所用,因此需要將之前棧的棧底入棧。在調(diào)用新的子程序的時候,也需要將子函數(shù)的返回地址入棧,不然子函數(shù)執(zhí)行完了,計算機就不知道下一步執(zhí)行什么了~
搞懂了這點知識,我們就可以利用這個來修改程序的執(zhí)行流程了,具體實驗可以自己做。
4 代碼植入
之前例子的緩沖區(qū)較小,正常的函數(shù)中如果使用的話,緩沖區(qū)可能是比較大的,下面用新的例子來測試緩沖區(qū)溢出中的代碼植入,完整的代碼見上傳的文件。
int verify(char *password) {int auth;char buffer[44];auth = strcmp(password, PASSWORD);strcpy(buffer, password);return auth; }- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
此次的實驗中由于控制臺輸入的限制性,將輸入流改為文本。實驗的目的是利用緩沖區(qū)溢出漏洞植入代碼,代碼內(nèi)容為彈出一個新的窗口。
int MessageBox(HWND hWnd, // handle of owner windowLPCTSTR lpText, // address of text in message boxLPCTSTR lpCaption, // address of title of message boxUINT uType // style of message box );- 1
- 2
- 3
- 4
- 5
- 6
- 1
- 2
- 3
- 4
- 5
- 6
上面是MessageBox的四個參數(shù),如果彈出標題和內(nèi)容都是hellobug的串,四個參數(shù)分別為:?
NULL, “hellobug”, “hellobug”, NULL?
根據(jù)MessageBox得到應(yīng)該執(zhí)行的匯編代碼
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
最后的Address是MessageBoxA地址,對應(yīng)的機器碼如下:
33 DB 53 68 6C 6C 65 68 //hell 68 67 75 62 6F //obug 8B C4 53 50 50 53 B8 ADDRESS FF D0- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
因為緩沖區(qū)有44個字節(jié),而四個字節(jié)一組,因此有11組,加上原來的auth,EBP和返回地址,一共14組,每組4個字節(jié)。新建一個這樣的文件。?
?
我在執(zhí)行的過程中最后部分0018FD44就是Buff的起始地址。
接下來的問題就是buff的起始地址以及MessageBox的入口地址怎么找到呢?
首先是buff的起始地址,這個比較簡單,將該文件寫為14組1234,然后在OD里面跑一遍之后可以看到內(nèi)存里面的數(shù)據(jù),這個數(shù)據(jù)區(qū)的起始地址就是就是buff的起始地址。
然后是MessageBox的入口地址,在0Day安全這本書中有計算過程,我按照這個過程沒有實現(xiàn),因此我自己找了一個方法,有興趣的同學可以按照書上的計算一下~
我的試驗工程就是新建一個工程,只允許Messagebox然后通過OD查看其入口地址
#include <stdio.h> #include <windows.h>int main(void) {LoadLibrary("user32.dll");MessageBoxA(NULL, "abc", "def", NULL);return 0; }- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
寫這樣一個簡單的程序用OD打開以下就好啦?
?
找到MessageBox回車之后就進入了,從這個圖可以看出入口地址是768EFD1E?
然后整個文件就制作完成了,運行一下看看吧?
以上就是一個簡單的緩沖區(qū)溢出的實例了,不過在植入代碼這個過程中電機確定之后~~就掛了,因為一些參數(shù)沒有設(shè)置好,慢慢再深入研究吧。
總結(jié)
以上是生活随笔為你收集整理的C语言实现缓冲区溢出实例的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: mysql_ping与mysql长连接
- 下一篇: 缓冲区溢出漏洞攻击演示实验(CProxy