DWORD Shoot利用Crt库free函数

之前写过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!RtlFreeHeap
0:000> g
Breakpoint 1 hit
0:000> kb
ChildEBP RetAddr  Args to Child              
0012ff5c 00401049 00390000 00000000 003928e8 ntdll!RtlFreeHeap
0012ff70 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!RtlFreeHeap
0:000> g
Breakpoint 1 hit
0:000> kb
ChildEBP RetAddr  Args to Child              
0012fef4 00431839 00390000 00000000 00392930 ntdll!RtlFreeHeap
0012ff10 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
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值