冷眼Wins远程溢出漏洞 -电脑资料

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

    十一月底,Immunitysec公开了一个WINS的远程安全漏洞,入侵者可利用该漏洞完全控制运行着WINS服务的系统,

冷眼Wins远程溢出漏洞

。其实这个漏洞早就被发现而且在地下流传已久,不过是最近才公布而已。就其公布的原因,估计是因为这个漏洞有趣,而且造成的影响不是很大吧。漏洞本身的特性决定了这个漏洞的利用可以有多种路子,让攻击者使用不同的方法来获得远程控制权,也许就是Immunitysec公开这个漏洞的初衷。不过微软对这个漏洞很敏感,没有发布补丁,因为说自己没有收到攻击报文,所以,本文只是详细的分析了整个漏洞的构造、利用,并未给出具体的利用程序和代码,相信读过我们系列文章“菜鸟版Expliot指南”的朋友应该都有能力写上一段自己的代码吧?

    冷眼Wins远程溢出漏洞

    文/图 马木留克

    关于这个漏洞的描述,比较官方的描述是这样的:WINS服务支持一个称之为“WINS 复制”的特性,不同的WINS服务器可以靠这个功能交换信息。WINS复制使用的也是监听在TCP 42端口上的标准WINS协议。在WINS复制的会话过程中,服务器端会发送一个内存指针给客户端,客户端用这个指针进行后续的会话。如果客户端在发送的数据中自己修改这个指针,使之指向用户控制的数据,最终就可以向任意地址写入16个字节的数据,通过覆盖特殊地址可以执行任意代码。

    对于攻击者而言,了解其中的细节非常必要。通过这一个描述,大致上我们已经可以了解到,这不是一个典型的堆或者栈上的溢出,而是WINS用我们指定的一个数据作为指针,进行了一些操作,最终导致可以写16个字节的数据到任意地址——对于大多数情况而言,能写16个字节的数据就已经足够了,典型的堆溢出甚至只需要写4个字节的数据,这个条件还是很宽松的。通过进一步的分析,我们还可以知道,这里的“16个字节”是指连续的16个字节,更为重要的是,WINS服务处理异常的机制非常的强劲,在你提交恶意的代码造成漏洞利用之后,WINS服务不会挂掉,而是继续的运行,这就意味着我们可以反复地进行“写连续的16字节”。试想一下,我们可以反复的尝试直到成功为止,这个过程中WINS服务不会因为我们的恶意攻击而出现停止的情况。

    在反汇编WINS服务的守护进程之前,我们可以想象一下各种可能的利用方式。按照Immunitysec的说法,恶意用户提交的数据是在堆上的,这就非常类似于远程堆溢出,加上可以写任意值到任意的地址,可以想象,几乎所有的堆溢出利用方式都可以应用到这上面来。最常用的,写top seh,然后看能不能通过寄存器来定位;其次,我们可以尝试写Lookaside表,通过多次发包来强制定位自己的ShellCode地址,然后通过改写RtlEnterCriticalSection(0x7ffdf020)等固定的函数指针来获得控制权;再直接一点,既然可以多次触发而服务不崩溃,那反复利用这个漏洞,直接写ShellCode到一块固定的内存(比如0x7ffdf222)去,继而通过改写固定的函数指针来获得控制权也是一条路子。总之,漏洞本身的特性决定了这个漏洞的利用可以有多种路子,让攻击者使用不同的方法来获得远程控制权,也许就是Immunitysec公开这个漏洞的初衷吧。

    Immunity在公布漏洞的同时,公布了触发漏洞的报文格式,如表1所示:

    报文长度(除头部4字节)

    XX XX FF XX

    四字节指针(绝对地址)

    …… …… …… ……

    (表1)

    其中报文的长度要小于0x2f87f8。报文本身没有什么其它特殊的要求,满足上述格式的都可以触发漏洞。报文中的第三个DOWRD就是一个我们可以控制的指针,因此,我们可以设定这个指针指向我们发送的报文本身所在的地方,进而控制随后依据这个指针的内存读写。

    在一台Windows 2000 Server SP3 + MS04006补丁的机器上,反汇编Wins.exe可以得到如下的代码:

    .text:0101FE34 sub_101FE34    proc near              ; CODE XREF: sub_101FD13+2A p

    .text:0101FE34

    .text:0101FE34 var_84         = dword ptr -84h

    ... ..

    .text:0101FE34 arg_4          = dword ptr 0Ch

    .text:0101FE34 arg_8          = dword ptr 10h

    .text:0101FE34 arg_C          = dword ptr 14h

    ... ...

    .text:0101FE64                mov    ebx, [ebp+arg_4]; 指向提交数据的指针

    .text:0101FE67                mov    al, [ebx+2]    ; Flag的第三个字节

    .text:0101FE6A                mov    cl, al

    .text:0101FE6C                and    cl, 78h

    .text:0101FE6F                cmp    cl, 78h       ; 和0x78与操作,这里必须跳转

    .text:0101FE72                jz     loc_101FF07

    ... ...(中间三个跳转)

    .text:010200F6                push   eax            ; 可以控制的指针A

    .text:010200F7                lea    ecx, [eax+50h]

    .text:010200FA                push   ecx            ; 指针A + 50h

    .text:010200FB                push   dword ptr [eax+44h]

    .text:010200FE                push   [ebp+arg_8]    ; 数据的长度(报文头)

    .text:01020101                push   [ebp+arg_4]    ; 指向提交数据的指针

    .text:01020104                call   sub_1020610

    ... ...

    .text:01020638                xor    ebx, ebx       ; ebx置零

    .text:01020640                mov    eax, [ebp+arg_10] ; 指针A

    .text:01020643                cmp    eax, ebx       ; 是否为合法地址(not NULL)

    .text:01020645                jnz    loc_10206CC    ; 合法

    ... ...

    .text:010206CC                mov    ecx, [eax+2Ch] ; 指针A+2C地址的内容

    .text:010206CF                mov    [ebp+var_20], ecx

    .text:010206D2                lea    edi, [ecx+48h] ; 拷贝的源地址

    .text:010206D5                mov    esi, [ebp+arg_C]; 目的地址A+44地址的内容

    .text:010206D8                movsd              ; 十六字节的写操作,源/目的可控

    .text:010206D9                movsd

    .text:010206DA                movsd

    .text:010206DB                movsd

    可以看到提交报文中第三个DOWRD指针指向的内容最终进行了一系列的写操作,

电脑资料

冷眼Wins远程溢出漏洞》(https://www.unjs.com)。如果以Where表示写操作的目的(esi),What表示写操作的数值(edi),简化后这个指针指向如下所示的结构如表2所示:

    where – 48h (lea  edi, [ecx+48h])  offset:0h

    … … … … … … … … … … … …

    what * 4  (4个DOWRD)        offset:24h

    (表2)

    精心控制发送报文中的指针的值,最后可以写四个DWORD。我们可以猜测我们发送的报文的大概位置,然后设定这个指针,那么,WINS就会把我们报文中的数字写到报文中指定的位置去。提交报文的长度可以很长(前面说了,只要小于0x2f87f8都是可以的),所以我们猜测起来还是比较方便,关键是这个指针指向的内容必须符合一定结构(见上表),一个比较好的方式是按照如下的结构指定我们发送报文中的内容(如表3所示)。

    Where – 48h (DWORD) * 9

    What * 4 (4个DWORD) * 9

    (表3)

    这样,我们只要大量的填充上述结构,就可以提高成功率——只要有一次猜测的指针指向数据块的位置是Where(连续九个为一组)就算成功。内存中大量的上述结构,加上这里堆分配的一些特性,最差情况下猜37次就可以猜到一个(连须36次都指针都猜到了What上),这个成功率还是可以接受的。从测试的情况来看,触发这个漏洞后极有可能导致堆内存没有正确释放,一个可能的利用办法就是先发送由一个大量上述结构填充的报文,设定指针指向一个会造成异常的地址(比如0xffffffff,但不能是0x0,WINS里面判断过这种情况),让这块内存不释放,然后后面都发小包来暴力猜测地址,从而准确的控制写入的源和目的地址。

    好不容易才解决了写16字节到任意地址的方式,那么要写什么东西到哪里去呢?前面说过一些类似于堆利用的方法,可以去试试看,写出来的东西通用性应该很好,下面尝试的是另外一种方法。

    要获得控制权就要想办法让程序执行到我们所指定的位置去。一般来说写一个程序会调用的函数指针是最好,如果不行的话也可以考虑写栈上的返回地址。上面的反汇编中,sub_1020610是导致写16字节的函数,这个函数并没有异常,我们可以考虑在这个地方先下一个断点,继续跟踪一直到有Ret的出现。Ret的意义在于把栈顶的数据作为返回值,也就是[ESP]->EIP,我们要是能够找准当时栈顶的位置然后覆盖掉,就可以准确地控制程序的流向。

    那么,让程序流向何处呢?当然是我们的ShellCode。我们的ShellCode可以随报文一块儿送过去,所以在堆上一定能找到一份拷贝。报文已经有了大量的如表3所定义的结构,然后在报文的最后写入ShellCode,中间可用大量的NOPs来填充。在猜指针的时候我们就大致的猜到了堆所在的地址,所以根据猜测的地址来定位ShellCode也是可以的。这样子,把堆上ShellCode的地址写到栈上函数的返回地址就可以获得控制权了。这一步可能也需要暴力猜解,因为栈上的返回地址可能并不确定。

    在测试的过程中,我们发现栈上返回地址的位置几乎是固定的,都是0x53df4c4,在对近70台机器的测试中,约有半数以上这个地址都是有效的。所以如果不打算写复杂的程序暴力猜测,这个地址就足够了。测试中涉及到了中文版几乎所有SP和MS04006补丁的情况,可见这个还是有一定的通用性的。倘若只是玩票性质的写写EXP,可以直接设置Where的值为0x53df4c4 – 48h。

    同样的,在上述的测试过程中,我们发现第一个发送过去的报文总是拷贝到一个固定的位置,如果用表三所示的数据结构来填充报文,那么这个数据结构第一次出现的位置几乎都固定在0x05391eac。这个几率大概是八成左右,偶尔的失败情况不详,但是有一点可以肯定的是,如果你造成了异常而导致堆没有被正确释放,那么后续报文被拷贝到的地址肯定在这之后。

    有了上述两个地址,要写一个成功率一般的利用程序已经不难,按照上面的报文格式,设定四字节的指针为0x05391eac,然后填充一个图三所示的结构,里面Where都填充为固定的栈上的函数返回地址0x53df4c4 – 48h,所有的What都填上我们猜测的一个大概的ShellCode的位置(比如0x05392000),接下来填充大约0x200个NOPs也就是0x90,然后加上一个任意的ShellCode,把这个报文发送到目标主机的TCP 42口,就有很大的可能性获得对方的控制权了。如果你的ShellCode不是以ExitProcess(0)结束的,那么你还可以反复的利用这个漏洞来获得控制权,只是每次的结果用的都是第一次发送的ShellCode——堆内存没有被释放而且我们猜测的是第一次发送的地址,如果你用的是Bind port的,那还好,如果是Reverse过来的那就麻烦了,别人要是抢先一步,用这种方法就算成功了你也没有机会的。

    至于其它的利用方式,说实话写RtlEnterCriticalSection不太稳定,暴力猜解可是可以,还是麻烦了一点,不知道有没有其他的利用方式。表面上看起来难以利用的漏洞公布出来,没有0day的利用方法怎么也说不过去,只有看看以后是否有好的方法公布出来了。

    关于这个漏洞的危害,报告也说明了,理论上来说对于所有开放了WINS服务(简单的用TCP端口42来判断)的Windows NT、Windows 2000、Windows 2003都有危险,在这个补丁没有出来的时候,最好还是把WINS服务关掉,或者用防火墙一类滤掉所有指向TCP42的报文。也就是因为漏洞没有出补丁就公开了这件事情,据说微软搞得很恼火(微软12月1日报告称没有收到受此漏洞攻击的报告,这简直是笑话,EXP是很容易写的,至少可以弄个不怎么通用的出来,我才不相信没有受到攻击,最多是没有报告罢了),顶着风头外面谁也不敢给出利用程序来。同样的,老独物WTF虽然也很期盼,但估计没这个胆把利用程序放到光盘里面去,大家要爽估计只有等到微软出了补丁后再放出利用程序来了,据说一月份就会出补丁,那么最快二月份可能就可以得到EXP。至于稍微懂行一点的朋友,想必都已经写出来了,有兴趣的的朋友也可以按照上面说的方法来写一个出来,我已经说得很清楚很明显了,不是么?

最新文章