MS08067 稳定利用方法 -电脑资料

电脑资料 时间:2019-01-01 我要投稿
【www.unjs.com - 电脑资料】

    文章作者:LittleWallE

    (http://blog.csdn.net/littlewalle)

    MS08-067的问题出在一个格式化路径的函数上,暂命名为ConvertPathMacros,它的工作就是去掉路径中的.\和..\, 例如传入路径为:”\A\B\.\C\..\D\..\..\E”,则经过它的处理后会变成”\A\E”,

MS08067 稳定利用方法

。如果给出一个恶意路径,例如”\A\..\..\..\E”,则它会越过目录A去寻找上层目录,从而造成错误的发生。

    这个漏洞的原理在很多文章中都解释的非常详细了,但是关于漏洞利用的文章却比较少(可能是我没找到),也没有文章描写如何找到栈上的那个关键的反斜杠。参考了其他高手写的exploit和自己的分析,总结了下稳定利用的方法:

    为了利用该漏洞,必须使漏洞函数调用之前执行另一个函数,是栈上残留数据。这个函数我参考了一个高手(EMM@ph4nt0m.org)写的exploit,选择了NetpwNameCompare。

    跟踪NetpwNameCompare后发现,该函数最后会调用RtlUpcaseUnicodeToOemN函数向缓冲区写入大量信息,而这些信息最终会残留在栈中,最后留给漏洞函数。

    分析源代码,知道了如果参数中含有如下的字符时,会在缓冲区中留下一个反斜杠。

    0x2010,0x2011,0x2012,0x2558,0x4e57,0x4fd3,0x50dc,0x5213,0x533c,0x54f1,0x5630,0x573d,0x5861...........

    另外要注意这个反斜杠必须是个UNICODE的反斜杠,即”\x5c\x00”,反斜杠后面的必须跟一个”\x00”,这个”\x00”用字符串的0结尾来代替即可。在字符串在前面加上一个ASCII字符的UNICODE,如"\x4c\x00",以"\x4c\x00\x10\x20"入参,则在栈上得到的结果为"\x4c\xXX\x5c\x00",正好包含一个UNICODE反斜杠。

    最后,以如下的参数来调用NetpwNameCompare

    NetpwNameCompare(L"LittleWallE",(wchar_t *)"\x4c\x00\x10\x20",(wchar_t *)"\x4D\x00\x10\x20",4,0);

    就可以在栈上稳定的留下一个反斜杠,在windows2003 sp0 中文版上,这个反斜杠距离溢出位置为0xA8.

    即构造字符串.\\x\..\..\(0xA8个无用字符)(jmp esp)(ShellCode),即可稳定利用该漏洞。

    附上RtlUpcaseUnicodeToOemN的逆向代码: 复制内容到剪贴板

    代码:

    #define BYTE_HIGH(var) ((var&0xf0)>>4)

    #define BYTE_LOW(var) (var&0xf)

    #define WORD_HIGH(var) ((var&0xff00)>>8)

    #define WORD_LOW(var) (var&0xff)

    #define DWORD_HIGH(var) ((var&0xffff0000)>>16)

    #define DWORD_LOW(var) (var&0xffff)

    /**********************************************************************

    *function:将argc_SrcBuffer的字符逐个进行编码表转换后放入栈上的缓冲区中

    *author: LittleWallE#yahoo.cn

    ***********************************************************************/

    RtlUpcaseUnicodeToOemN(char * arg0_DstBuffer, //栈上的缓冲区

    int arg4_DstBufferLength, //栈上的缓冲区长度

    int * arg8_NoUse,

    WCHAR *argc_SrcBuffer, //入参

    int arg10_SrcBufferLength //入参长度)

    {

    char *MatrixA;//mark:dword_7c9b8e94=,一个表格,内容是0000 0100 0200 0300..一直继续下去,可能是某种编码表

    char *MatrixB;//mark:dword_7C9B8A04 另一个编码表。

    char *MatrixUnknownA;//mark:word_7c9b8c90; 映射区域,不确定其功能;

    char *MatrixUnknownB;//mark:dword_7C9B8E90;映射区域,不确定其功能;

    char *MatrixUnknownC;//mark:dword_7C9B779C;映射区域,不确定功能;

    int var_8_SrcRealLength=arg10_SrcBufferLength/2;

    if(var_8_SrcRealLength==0)

    return 0;

    while(1)

    {

    if(arg4_DstBufferLength==0)

    break;

    WCHAR wcSrcChar_1=*argc_SrcBuffer;

    argc_SrcBuffer++;

    WCHAR wcSrcChar_2=MatrixA[wcSrcChar_1*2];

    wcSrcChar_2_high=WORD_HIGH(wcSrcChar_2);

    wcSrcChar_2_high=MatrixUnknownB[wcSrcChar_2_high*2];

    wcSrcChar_2_low=WORD_LOW(wcSrcChar_2);

    WCHAR wcSrcChar_3;

    if(wcSrcChar_2_high==0)

    {

    wcSrcChar_3=MatrixB[wcSrcChar_2_low*2];

    }else

    {

    int index=wcSrcChar_2_high+wcSrcChar_2_low;

    wcSrcChar_3=MatrixUnknownB[index*2];

    }

    if(wcSrcChar_3>='a'&&wcSrcChar_3<='z')

    {

    wcSrcChar_3+=0x0ffe0;

    }else{

    char wcSrcChar_3_high=WORD_HIGH(wcSrcChar_3);

    wcSrcChar_3_high=MatrixUnknownC[wcSrcChar_3_high*2];

    char wcSrcChar_3_byte_high=BYTE_HIGH(wcSrcChar_3);

    wcSrcChar_3_high+=wcSrcChar_3_byte_high;

    wcSrcChar_3_high=MatrixUnknownC[wcSrcChar_3_high*2];

    char wcSrcChar_3_byte_low=BYTE_LOW(wcSrcChar_3);

    wcSrcChar_3_high+=wcSrcChar_3_byte_low;

    wcSrcChar_3+=wcSrcChar_3_high;

    }//上面这段类似不可逆的加密算法

    WCHAR wcSrcChar_4=MatrixA[wcSrcChar_3*2];

    char wcSrcChar_4_high=WORD_HIGH(wcSrcChar_4);

    char wcSrcChar_4_low=WORD_LOW(wcSrcChar_4);

    if(wcSrcChar_4_high!=0)

    {

    if(arg4_DstBufferLength<2)

    break;

    *arg0_DstBuffer=wcSrcChar_4_high; //这里写入栈上的缓冲区

    arg0_DstBuffer++;

    arg4_DstBufferLength--;

    }

    *arg0_DstBuffer=wcSrcChar_4_low; //这里写入栈上的缓冲区

    arg0_DstBuffer++;

    arg4_DstBufferLength--;

    var_8_SrcRealLength--

    if(arg4_DstBufferLength==0||var_8_SrcRealLength==0)

    break;

    }

    }

最新文章