Windows下的HEAP溢出及其利用(2)

转移技术贴 | 2007-01-14 00:49:00 | 阅读 1351 次 | 评论(0)

四、实战 
由于Windows下的溢出对于本地利用来说没有多大意义,所以我们一个存在HEAP溢出漏洞的网络程序为例:
/* 
win_heap_vul.c 
Windows下存在HEAP溢出漏洞的服务端程序 
*/ 
#define PORT 1500 
#define BUFFLEN 32 //分配内存的大小 
#define COPYLEN 64 //实际拷贝的大小 
int main() 

WSADATA wsd; 
SOCKET sListen, sClient; 
struct sockaddr_in local, client; 
int iAddrSize; 
HANDLE hHeap; 
char *buf1, *buf2; 
char buff[4096]; 
if (WSAStartup(MAKEWORD(2,2), &wsd) != 0) 

printf(\"Failed to load Winsock!\\n\"); 
return 1; 

//建立一个socket监听1500端口 
sListen = socket(AF_INET, SOCK_STREAM, IPPROTO_IP); 
local.sin_addr.s_addr = htonl(INADDR_ANY); 
local.sin_family = AF_INET; 
local.sin_port = htons(PORT); 
if (bind(sListen, (struct sockaddr *)&local, sizeof(local)) == SOCKET_ERROR) 

printf(\"bind() failed: %d\\n\", WSAGetLastError()); 
return 1; 

listen(sListen, 8); 
iAddrSize = sizeof(client); 
sClient = accept(sListen, (struct sockaddr *)&client, &iAddrSize); 
if (sClient == INVALID_SOCKET) 

printf(\"accept() failed: %d\\n\", WSAGetLastError()); 
return 1; 

printf(\"connect form: %s:%d\\n\", inet_ntoa(client.sin_addr), ntohs(client.sin_port)); 

//我们自己建立一个HEAP,以免破坏掉进程默认HEAP以后shellcode无法正常运行 
hHeap = HeapCreate(HEAP_GENERATE_EXCEPTIONS, 0x10000, 0xfffff); 
//动态分配一块BUFFLEN大小的(32 bytes)的内存buf1 
buf1 = HeapAlloc(hHeap, 0, BUFFLEN); 
recv(sClient, buff, 4096, 0); 
//注意:这里溢出的不是buff,而是buf1, 
//buff是在栈中开辟的缓冲区,它的大小是4096,上面recv的也是4096,所以不会溢出 
printf(\"recv1: %s\\n\", buff); 
//将从客户端接受到的内容(即buff)拷贝到buf1中 
//如果接受到的内容大于32字节将发生溢出 
//这里错误的使用了COPYLEN(64 bytes),因此造成溢出 
memcpy(buf1, buff, COPYLEN); 
//如果覆盖到HEAP中的管理结构,那么当再次动态分配内存时将可能被利用 
buf2 = HeapAlloc(hHeap, 0, BUFFLEN); 
recv(sClient, buff, 4096, 0); 
printf(\"recv2: %s\\n\", buf2); 
HeapFree(hHeap, 0, buf1); 
HeapFree(hHeap, 0, buf2); 
closesocket(sListen); 
WSACleanup(); 
return 0; 


整个程序很简单,监听在1500端口,先分配了32字节的buf1,并把客户端发送过来的内容的前64字节拷贝到buf1里,这里是由于错误的使用了宏而发生的溢出(应该用BUFFLEN,但用了COPYLEN),这种情况在实际中也是很容易发生的。这样当再分配buf2的时候就会有写内存的操作,使得我们可以利用这个漏洞。
现在我们就可以写个攻击程序来溢出它,并且控制改写任意4字节的内存。那么到底改写什么地方比较合适呢?我想来想去有4种地方可以改写,用来控制去执行我们的shellcode: 
1.堆栈中保存的函数返回地址 
2.堆栈中保存的的异常处理指针 
3.线程默认异常处理指针(顶层异常处理指针) 
4.线程环境块(TEB) 
1和2都是保存在堆栈中的地址,因此在不同的系统中可能是不一样的,如果改写这两个地址的话虽然也可能成功,但是无法保证程序的通用性,从实际攻击的成功率的角度考虑,就不能用这两种地址。 
3是线程默认异常处理指针(即顶层异常处理指针),它在同一版本的操作系统中是一个固定的值。这里稍微介绍一下Windows结构化异常处理的基本原理。Windows的结构化异常处理(SEH)是一种对程序异常的处理机制,它是按照链式层状结构进行处理的。当线程中发生异常时,操作系统首

文章评论,共0条
游客请输入验证码
浏览64974次