DWORD Shoot利用Crt库free函数

来源:互联网 发布:淘宝客代运营 编辑:程序博客网 时间:2024/05/29 08:20

之前写过Win32运行库的DWORD Shoot,随着windows安全性检查的升级,简单的DWORD shoot并不能达到利用程序的目的。但是这种技术就被淘汰了吗?我个人觉得并不是这样,因为DWORD shoot技术本质上是钻了链表出链时不检查内存地址合法性的漏洞,因此只要在代码中找到有链表存在的影子就有利用的可能。

C Programmer一般用Crt运行库提供的库函数malloc/free管理程序的内存,而malloc最终调用HeapAlloc分配内存。我们知道HeapAlloc分配的内存块是_HEAP_ENTRY+用户可见区+尾块的形式,malloc调用HeapAlloc,因此它获得的内存块也遵循这样的形式。无非Crt管理器将用户可见区一部分内存挪为己用。这部分内存用_CrtMemBlockHeader结构进行管理,在VS2010中的定义为:

typedef struct _CrtMemBlockHeader{        struct _CrtMemBlockHeader * pBlockHeaderNext;        struct _CrtMemBlockHeader * pBlockHeaderPrev;        char *                      szFileName;        int                         nLine;#ifdef _WIN64        /* These items are reversed on Win64 to eliminate gaps in the struct         * and ensure that sizeof(struct)%16 == 0, so 16-byte alignment is         * maintained in the debug heap.         */        int                         nBlockUse;        size_t                      nDataSize;#else  /* _WIN64 */        size_t                      nDataSize;        int                         nBlockUse;#endif  /* _WIN64 */        long                        lRequest;        unsigned char               gap[nNoMansLandSize];        /* followed by:         *  unsigned char           data[nDataSize];         *  unsigned char           anotherGap[nNoMansLandSize];         */} _CrtMemBlockHeader;

从pBlockHeaderNext和pBlockHeaderPrev域,可以看出crt库以双向链表的方式用来管理所有调用malloc分配出去内存块。如果调用free时,crt库并没有检查pBlockHeaderNext和pBlockHeaderPrev变量的合法性,就在无意中为我们提供了利用的机会。分别查看vs2010下Debug版本和Release版本对free的调用堆栈,可以看到如下输出:

;release版本0:000> bp ntdll!RtlFreeHeap0:000> gBreakpoint 1 hit0:000> kbChildEBP RetAddr  Args to Child              0012ff5c 00401049 00390000 00000000 003928e8 ntdll!RtlFreeHeap0012ff70 00401b6f 003928e8 7ffda000 00f0f6ee malloc!free+0x1c [f:\dd\vctools\crt_bld\self_x86\crt\src\free.c @ 51] //_free_base (void * pBlock)0012ff84 004011f4 3aeb8a72 00f0f6ee 00f0f7aa malloc!_wsetenvp+0x9d [f:\dd\vctools\crt_bld\self_x86\crt\src\stdenvp.c @ 139]0012ffc0 7c817067 00f0f6ee 00f0f7aa 7ffda000 malloc!__tmainCRTStartup+0xd0 [f:\dd\vctools\crt_bld\self_x86\crt\src\crt0.c @ 259];debug版本0:000> bp ntdll!RtlFreeHeap0:000> gBreakpoint 1 hit0:000> kbChildEBP RetAddr  Args to Child              0012fef4 00431839 00390000 00000000 00392930 ntdll!RtlFreeHeap0012ff10 00428f6e 00392930 00392930 0012ff58 malloc!_free_base+0x29 [f:\dd\vctools\crt_bld\self_x86\crt\src\free.c @ 50]0012ff20 00428a70 00392950 00000002 7ce76772 malloc!_free_dbg_nolock+0x4ae [f:\dd\vctools\crt_bld\self_x86\crt\src\dbgheap.c @ 1431]0012ff58 0042d57b 00392950 00000002 00000012 malloc!_free_dbg+0x50 [f:\dd\vctools\crt_bld\self_x86\crt\src\dbgheap.c @ 1265]0012ff78 00427557 7ce76792 00f6f6ee 00f6f7a6 malloc!_wsetenvp+0x16b [f:\dd\vctools\crt_bld\self_x86\crt\src\stdenvp.c @ 138]0012ffb8 0042746f 0012fff0 7c817067 00f6f6ee malloc!__tmainCRTStartup+0xd7 [f:\dd\vctools\crt_bld\self_x86\crt\src\crt0.c @ 259]
借助调用堆栈在结合crt源码,可知Release版本的程序并没有使用_CrtMemBlockHeader结构管理堆内存;而Debug版本的程序使用_CrtMemBlockHeader用于管理调用malloc分配的堆内存,更重要的一点,vs2010调用free从链表中移除已分配的堆内存时并没有做安全检查,于是,我们有了DWORD Shoot的机会。很幸运的是,crt管理的双向链表和Windows堆管理器管理的空闲链表数组FreeList[128]不同:在win xp sp1以上的系统上,堆管理器对堆分配释放进行严格的安全检查(严格检查_HEAP_ENTRY,_Free_HEAP_ENTRY等结构的正确性),因此出现了文章开头提到的DWORD shoot失效的情况;但是crt提供的堆管理并不在进程堆管理器的管理范围之内(毕竟,对于OS来说_CrtMemBlockHeader结构是在用户可见内存范围内),换句话说,DWORD shoot crt库的free函数是一个很好的选择。

附注,本文分析利用crt库的可行性,具体的事实过程和前面几篇blog大同小异,因此就不细写了。

参考资料:张银奎 <软件调试> 23章 Crt运行库



0 0
原创粉丝点击