-
-
讨论一下ms12-020
-
发表于:
2012-3-28 13:03
7007
-
分析这个漏洞好几天,应该是有两个,一是那个rdpclient.exe和ruby脚本中用的;另一个是http://aluigi.org/adv/termdd_1-adv.txt里面说的,这是两个漏洞,aluigi说rdpclient.exe抄袭他的,我觉得不太靠谱。
先说第一个漏洞,原因是在MCSChannelJoinRequest中,如指定了channelId,会进行错误的比较,导致一个user的Base channelId(这是我起的名字,或者说是user id),被另一个user引用,这样当HandleDisconnectProviderUlt时依次DetachUser每个用户,前面的User的channel已被释放了,DetachUser后面的用户时,引用已被释放的channel导致异常。这个漏洞可以不触发蓝屏检测,根据joinchannel的返回情况可以判断,最后直接断开连接,这样会直接释放所有内存,而不会走到DetachUser,也就不会蓝屏了。
第二个漏洞,是在发的连接参数中限定了channel个数,WDWConnect过程会建立好几个channel,如达到了这个最高channel个数,会走向失败,对一个标志的重复判断(NMAbortConnect和NM_Disconnect中),会导致两次NMDetachUserReq,第一次释放了user内存,第二次就异常了。
这两个漏洞都是Use After Free释放后引用的,都是分页内存,这里再说说系统分页内存的机制,分页内存在分页内存池中,分页内存池有多个(看wrk好像是4个),使用哪个分页内存池是线程相关的,分配的内存地址-8是Pool_header,其中的Blocksize和PreviousSize都是以8字节一块为单位的,释放内存时,会释放到池的ListHeads[Blocksize-1]中,分配时从ListHeads中取一个,因此同一线程释放后再立刻分配相同大小的内存,分配的一般就是刚才释放的地址,另外分配可能拆分空闲块,释放时可能合并,特别小和超过一个页的内存会有不同,不过漏洞涉及的内存大小是如上面所说的。
两个漏洞 一个释放的channel,字节数是0x40,一个释放的User,字节数是0x4c,我所能想到的利用方式就是重新分配内存占用释放的位置,理想的情况是我们发送0x40或0x4c字节的数据,占用了释放的位置,这样按我们希望的执行流向引导,但是实际很难。一开始我寄希望于第一个漏洞,因为第一个漏洞是DetachUser引起的,如果先DetachUser释放channel,然后占用内存,然后再DetachUser另一个用户触发漏洞,那就有可能可控,但是我找了好久都没有发现rdpdw.sys中可以直接处理发来的数据单独DetachUser某一用户的,可能rdp连接完全建立后,ring3层或者rdpdr.sys也许可以单独DetachUser某一用户,没有再深入分析,此时我发现即使可以可控占用,在漏洞触发点SListRemove中也不能达到利用的要求,在其中虽然可能覆盖8字节,但是通过搜索User得到的要修改的地址是不确定的。然后再看第二个漏洞,这个释放到触发是一起的,不可能分开来,不过如果可以成功占用,倒是有可能利用,漏洞触发点是在termdd!IcaBufferAlloc中,释放的是pUserContext,这一系列的转换是:
*pUserContext->pFakeContext
*pFakeContext->pFake(未知指针,不太清楚这是干什么的)
要满足*(pFake-8)>0,得x=*(pFake-8)-8,要满足x!=0且**(x+24)!=0,*(x+16)要可写,最后调用**(x+24),如果**(x+24)的代码可以跳到shellcode就有可能利用,但是看上面这要满足太多条件。如何才能占用内存,Termdd!_IcaCopyDataToUserBuffer似乎有希望,触发走这个函数似乎要rdp连接完全建立后,这个函数中才能分配分页内存,且用于容纳发送的数据,但是这个内存分配后使用完很快就释放了。对于多个内存池,建立多个连接,不停发送数据,不断地走_IcaCopyDataToUserBuffer可能提高成功率。总结一下,要利用第二个漏洞,要在第一次释放后、第二次释放前的短暂时间里,发送数据争取占用那个内存池的那段内存,且还要满足那些转换条件,难度之大成功率之低,以至于我不得不放弃了。这是我第二次分析漏洞,没想到碰到这么难的...
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)