堆溢出 对HeapFree函数的详细调试
代码
#include <windows.h>
int main()
{HLOCAL h1,h2,h3,h4,h5,h6;HANDLE hp;hp = HeapCreate(0,0x1000,0x10000);h1 = HeapAlloc(hp,HEAP_ZERO_MEMORY,3);h2 = HeapAlloc(hp,HEAP_ZERO_MEMORY,5);h3 = HeapAlloc(hp,HEAP_ZERO_MEMORY,6);h4 = HeapAlloc(hp,HEAP_ZERO_MEMORY,8);h5 = HeapAlloc(hp,HEAP_ZERO_MEMORY,19);h6 = HeapAlloc(hp,HEAP_ZERO_MEMORY,24);_asm int 3HeapFree(hp,0,h1);HeapFree(hp,0,h3);HeapFree(hp,0,h5);_asm int 3HeapFree(hp,0,h4);return 0;
}
实验目的
了解HeapAlloc函数的操作过程
实验准备
环境:windows 2k professional
编译器:vc++
调试器:OD
实验过程
1.首先观察链表是怎么装载进去的
CPU Disasm
Address Hex dump Command Comments
77FCC8E6 |. 8066 05 10 AND BYTE PTR DS:[ESI+5],10 //对堆块中Flag位进行更改,使其为占用态
2.然后修改被装载进去堆块的地址,先改被占用堆块的第一项,第二项,再去修改Freelist[1]中的第一项第二项,然后再把可用的总空间加起来放进堆块一开始偏移0x28的地方。
77FCC909 |. 8D46 08 LEA EAX,[ESI+8]
77FCC90C |. 8918 MOV DWORD PTR DS:[EAX],EBX
77FCC90E |. 894E 0C MOV DWORD PTR DS:[ESI+0C],ECX
77FCC911 |. 8901 MOV DWORD PTR DS:[ECX],EAX
77FCC913 |. 8943 04 MOV DWORD PTR DS:[EBX+4],EAX //把地址进行替换
77FCC916 |. 8B45 D0 MOV EAX,DWORD PTR SS:[EBP-30]
77FCC919 |. 0147 28 ADD DWORD PTR DS:[EDI+28],EAX //add last part
77FCC91C |> 834D FC FF OR DWORD PTR SS:[EBP-4],FFFFFFFF
3.然后再把int 3断点往下再移一位,观察堆的拆卸,装载这一系列的操作。先开头还是一些准备的传参的工作,上线程锁啊这些的。然后就进入了关键的函数。这是函数的一波传参。
77FCC8CA |. 6A 00 PUSH 0 //Arg4 = 0
77FCC8CC |. 8D45 D0 LEA EAX,[LOCAL.12]
77FCC8CF |. 50 PUSH EAX //Arg3 = 指向堆栈中存放数组的指针
77FCC8D0 |. 56 PUSH ESI //Arg2 = 指向Free的那个堆块的堆块头部
77FCC8D1 |. 57 PUSH EDI //Arg1 = 指向整个堆块的最前面
77FCC8D2 |. E8 EA000000 CALL 77FCC9C1 //ntdll.77FCC9C1
4.然后的代码就是判断上一个堆块的一些数据,来判断要不要合并
77FCC9C1 /$ 55 PUSH EBP // ntdll.77FCC9C1(guessed Arg1,Arg2,Arg3,Arg4)
77FCC9C2 |. 8BEC MOV EBP,ESP
77FCC9C4 |. 53 PUSH EBX
77FCC9C5 |. 56 PUSH ESI
77FCC9C6 |. 8B75 0C MOV ESI,DWORD PTR SS:[ARG.2] //指向Free的那个堆块的堆块头部
77FCC9C9 |. 8B5D 08 MOV EBX,DWORD PTR SS:[ARG.1] //指向HeapCreate堆块的头
77FCC9CC |. 57 PUSH EDI
77FCC9CD |. 8BFE MOV EDI,ESI
77FCC9CF |. 0FB746 02 MOVZX EAX,WORD PTR DS:[ESI+2] //读取上一节的长度
77FCC9D3 |. C1E0 03 SHL EAX,3
77FCC9D6 |. 2BF8 SUB EDI,EAX
77FCC9D8 |. 3BFE CMP EDI,ESI //判断前面的那个堆块是不是只和一块空表连着的,如果连着的判断是不是尾块
77FCC9DA |. 74 0A JE SHORT 77FCC9E6
77FCC9DC |. F647 05 01 TEST BYTE PTR DS:[EDI+5],01 //观察前一块的是否是占用态
77FCC9E0 |.^ 0F84 98E9FFFF JZ 77FCB37E
5.然后就进行了相加的操作,那个Call 778953A的作用应该是检测那个堆块所对应的链表。
77FCB37E |> /8B4D 10 MOV ECX,DWORD PTR SS:[EBP+10]
77FCB381 |. |0FB707 MOVZX EAX,WORD PTR DS:[EDI]
77FCB384 |. |8B09 MOV ECX,DWORD PTR DS:[ECX]
77FCB386 |. |03C8 ADD ECX,EAX //上一节堆块的大小再加上这一节的进行合并
77FCB388 |. |81F9 00FE0000 CMP ECX,0FE00
77FCB38E |. |0F87 52160000 JA 77FCC9E6
77FCB394 |. |807D 14 00 CMP BYTE PTR SS:[EBP+14],0
77FCB398 |. |0F85 6A370000 JNE 77FCEB08
77FCB39E |> |57 PUSH EDI //指向Free的那个堆块的前一个堆块
77FCB39F |. |53 PUSH EBX //指向整个堆块的最前面
77FCB3A0 |. |E8 95E1FBFF CALL 77F8953A // ntdll.77F8953A
6.先把之前的那个表从链表中拿出来,同时还检测了这块上再上面一块,如果这再上面一块不是占用态的话还要继续进行合并。再把堆块最前面对大小的说明的那一部分进行改动。
77FCB3A5 |. 8B4F 0C MOV ECX,DWORD PTR DS:[EDI+0C]
77FCB3A8 |. 8B47 08 MOV EAX,DWORD PTR DS:[EDI+8]
77FCB3AB |. 3BC1 CMP EAX,ECX //看看前面的再前面的那个堆块是不是只和一块空表连着的
77FCB3AD |. 8901 MOV DWORD PTR DS:[ECX],EAX
77FCB3AF |. 8948 04 MOV DWORD PTR DS:[EAX+4],ECX //把和Free合并的那个堆块从链表中取出来
77FCB3B2 |. 74 4D JE SHORT 77FCB401
77FCB3B4 |> 8A47 05 MOV AL,BYTE PTR DS:[EDI+5]
77FCB3B7 |. A8 04 TEST AL,04 //检测标志位。(不是很懂
77FCB3B9 |.^ 0F85 21FDFFFF JNZ 77FCB0E0
77FCB3BF |> 8A46 05 MOV AL,BYTE PTR DS:[ESI+5]
77FCB3C2 |. 24 10 AND AL,10
77FCB3C4 |. A8 10 TEST AL,10
77FCB3C6 |. 8847 05 MOV BYTE PTR DS:[EDI+5],AL //把合并进来的堆块调成空闲态
77FCB3C9 |. 0F85 CB170000 JNZ 77FCCB9A
77FCB3CF |> 0FB70F MOVZX ECX,WORD PTR DS:[EDI]
77FCB3D2 |. 8B45 10 MOV EAX,DWORD PTR SS:[EBP+10]
77FCB3D5 |. 8BF7 MOV ESI,EDI //再往上看一个堆块
77FCB3D7 |. 0108 ADD DWORD PTR DS:[EAX],ECX //加起来
77FCB3D9 |. 0FB70F MOVZX ECX,WORD PTR DS:[EDI]
77FCB3DC |. 294B 28 SUB DWORD PTR DS:[EBX+28],ECX //从总的里面减
77FCB3DF |. 66:8B00 MOV AX,WORD PTR DS:[EAX]
77FCB3E2 |. F647 05 10 TEST BYTE PTR DS:[EDI+5],10 //又判断是不是尾块
77FCB3E6 |. 66:8907 MOV WORD PTR DS:[EDI],AX //堆块头部的大小进行了替换 合并
77FCB3E9 |. 0F85 F7150000 JNZ 77FCC9E6
77FCB3EF |. 8B45 10 MOV EAX,DWORD PTR SS:[EBP+10]
77FCB3F2 |. 8B08 MOV ECX,DWORD PTR DS:[EAX]
77FCB3F4 |. 66:8B00 MOV AX,WORD PTR DS:[EAX]
77FCB3F7 |. 66:8944CF 02 MOV WORD PTR DS:[ECX*8+EDI+2],AX //把下一节中描述上一节大小的量进行变化
77FCB3FC |. E9 E5150000 JMP 77FCC9E6
6.然后又看下一节是不是占用态,不是占用态的话继续合并。
77FCC9E0 |.^\0F84 98E9FFFF JZ 77FCB37E
77FCC9E6 |> F646 05 10 TEST BYTE PTR DS:[ESI+5],10
77FCC9EA |. 75 0F JNZ SHORT 77FCC9FB
77FCC9EC |. 8B45 10 MOV EAX,DWORD PTR SS:[EBP+10]
77FCC9EF |. 8B00 MOV EAX,DWORD PTR DS:[EAX]
77FCC9F1 |. F644C6 05 01 TEST BYTE PTR DS:[EAX*8+ESI+5],01 //看下一节是不是占用态
77FCC9F6 |. 8D3CC6 LEA EDI,[EAX*8+ESI]
77FCC9F9 |. 74 09 JZ SHORT 77FCCA04
7.看下一节是不是尾块,不是的话继续合并、
77FCCA04 |> \0FB70F MOVZX ECX,WORD PTR DS:[EDI]
77FCCA07 |. 03C8 ADD ECX,EAX
77FCCA09 |. 81F9 00FE0000 CMP ECX,0FE00
77FCCA0F |.^ 77 EA JA SHORT 77FCC9FB
77FCCA11 |. 807D 14 00 CMP BYTE PTR SS:[EBP+14],0
77FCCA15 |. 0F85 FB210000 JNE 77FCEC16
77FCCA1B |> 8A47 05 MOV AL,BYTE PTR DS:[EDI+5]
77FCCA1E |. 24 10 AND AL,10
77FCCA20 |. A8 10 TEST AL,10 //看是不是尾块
77FCCA22 |. 8846 05 MOV BYTE PTR DS:[ESI+5],AL
77FCCA25 |. 75 4B JNZ SHORT 77FCCA72
77FCCA27 |> 57 PUSH EDI //下一节的地址
77FCCA28 |. 53 PUSH EBX //堆块的地址
77FCCA29 |. E8 0CCBFBFF CALL 77F8953A //\ntdll.77F8953A
77FCCA2E |. 8B4F 0C MOV ECX,DWORD PTR DS:[EDI+0C]
77FCCA31 |. 8B47 08 MOV EAX,DWORD PTR DS:[EDI+8]
77FCCA34 |. 3BC1 CMP EAX,ECX //看看是不是表里只有一个
77FCCA36 |. 8901 MOV DWORD PTR DS:[ECX],EAX
77FCCA38 |. 8948 04 MOV DWORD PTR DS:[EAX+4],ECX //把表改成指向自己,清空
77FCCA3B |.^ 0F84 12E9FFFF JE 77FCB353
8.然后修改堆块头,改下一节对上一节大小的说明
77FCCA41 |> \8A47 05 MOV AL,BYTE PTR DS:[EDI+5]
77FCCA44 |. A8 04 TEST AL,04
77FCCA46 |.^ 0F85 CBE6FFFF JNZ 77FCB117
77FCCA4C |> 0FB70F MOVZX ECX,WORD PTR DS:[EDI]
77FCCA4F |. 8B45 10 MOV EAX,DWORD PTR SS:[EBP+10]
77FCCA52 |. 0108 ADD DWORD PTR DS:[EAX],ECX //上面加的又加上下一节
77FCCA54 |. 0FB70F MOVZX ECX,WORD PTR DS:[EDI]
77FCCA57 |. 294B 28 SUB DWORD PTR DS:[EBX+28],ECX //从总的里面减
77FCCA5A |. 66:8B08 MOV CX,WORD PTR DS:[EAX]
77FCCA5D |. F646 05 10 TEST BYTE PTR DS:[ESI+5],10 //确认不是尾块
77FCCA61 |. 66:890E MOV WORD PTR DS:[ESI],CX //又一次修改堆块头的大小
77FCCA64 |.^ 75 95 JNZ SHORT 77FCC9FB
77FCCA66 |. 8B08 MOV ECX,DWORD PTR DS:[EAX]
77FCCA68 |. 66:8B00 MOV AX,WORD PTR DS:[EAX]
77FCCA6B |. 66:8944CE 02 MOV WORD PTR DS:[ECX*8+ESI+2],AX //修改下一节中对上一节的大小的描述
77FCCA70 |.^ EB 89 JMP SHORT 77FCC9FB
9.找一个空闲的空表放进去
77FCC8E6 |. 8066 05 10 AND BYTE PTR DS:[ESI+5],10 //确认堆块的Flag位
77FCC8EA |. 0FB745 D0 MOVZX EAX,WORD PTR SS:[LOCAL.12]
77FCC8EE |. 8D9CC7 780100 LEA EBX,[EAX*8+EDI+178] //找一个Freelist
77FCC8F5 |. 895D C4 MOV DWORD PTR SS:[LOCAL.15],EBX
77FCC8F8 |. 391B CMP DWORD PTR DS:[EBX],EBX //看这个表是不是空闲的空表
77FCC8FA |.^ 0F84 CBF5FFFF JE 77FCBECB
77FCC90C |. 8918 MOV DWORD PTR DS:[EAX],EBX
77FCC90E |. 894E 0C MOV DWORD PTR DS:[ESI+0C],ECX
77FCC911 |. 8901 MOV DWORD PTR DS:[ECX],EAX
77FCC913 |. 8943 04 MOV DWORD PTR DS:[EBX+4],EAX //按照顺序改堆块里面的地址
77FCC916 |. 8B45 D0 MOV EAX,DWORD PTR SS:[EBP-30] //堆溢出就在这一个点,就把那个指针替换掉
77FCC919 |. 0147 28 ADD DWORD PTR DS:[EDI+28],EAX //改空表里面的地址
堆溢出 对HeapFree函数的详细调试相关推荐
- 堆溢出-House of orange 学习笔记(看雪论坛)
https://www.jianshu.com/p/4b0a73f321f9 前几天把House of orange重新学习了一下,比照着glibc malloc的源码好好分析了一下,希望做到真正做到 ...
- linux函数 取值溢出,Linux eCryptfs工具parse_tag_3_packet()函数堆溢出漏洞
发布日期:2009-07-28 更新日期:2009-07-29 受影响系统: Linux kernel 2.6.30.3 描述: ----------------------------------- ...
- CVE-2012-0003:Microsoft Windows Media Player winmm.dll MIDI 文件堆溢出漏洞调试分析
0x01 蜘蛛漏洞攻击包 前言:2012 年 2月,地下黑产中流行着一款国产名为蜘蛛漏洞的攻击包 -- "Zhi-Zhu Exploit Pack",该工具包含 5 个漏洞,都是在 ...
- 堆(heap)系列_0x0A:3种方法一次性解决堆溢出问题
概述:本篇文章主要介绍堆问题中最常见的堆溢出问题的排查思路:常规思路 + 页堆思路 + 应用程序验证器思路 前提:可以看到懂得DPH(点击查看)和会使用应用程序验证器(点击查看)和WinDbg 文章目 ...
- Netgear R6400v2 堆溢出漏洞分析与利用
2020 年 6 月,ZDI发布了一个关于Netgear R6700型号设备上堆溢出漏洞的安全公告,随后又发布了一篇关于该漏洞的博客,其中对该漏洞进行了详细分析,并给出了完整的漏洞利用代码.该漏洞存在 ...
- 《0Day安全》之堆溢出
最近重读<0Day安全>,由于栈溢出比较简单,所以直接从堆溢出开始读起. 在学习堆溢出之前,需要读者对堆的结构有一定的了解.先写一个小程序,分配一个新的堆来供我们研究它的结构,代码如下 # ...
- 堆溢出(二)空表DWORD SHOOT
0x000 环境 虚拟机 VirtualBox 5.0.20 系统 windows 2000 Kali linux 工具 VC++6.0 OllyDbg 1.10 汉化版 AsmToE v5.20 0 ...
- 堆溢出(DwordShoot)利用SEH异常处理
异常处理的身影处处可见,最常见的处理方式就是当异常发生时,在异常处理模块中记录日志,便于程序员事后定位.但是,被异常处理包含的代码真的会在异常发生时让程序优雅的退出吗?在程序的世界里什么都可能发生,所 ...
- 【缓冲区溢出】堆溢出原理
一.操作系统中堆和栈的区别 堆内存申请,释放,操作,特点: 1. 堆内存申请环境:堆内存需要程序员在程序中申请 ,动态分配,申请的大小有程序决定. 2. 堆内存申请方法:C语言中的malloc() 函 ...
- 漏洞学习笔记——堆溢出原理
最近在学习堆的溢出原理,但是查了网上和书上的一些讲解,总是感觉缺少一些关键点.所以理解起来总是有点晕,经过努力的调试分析后,总结了下面的更为详细的堆溢出原理.如果不准确的地方,希望大佬可以提醒一哈~ ...
最新文章
- opencart导入导出export/import功能插件
- 超图预览osgb格式倾斜摄影文件
- 基于 Spring Boot 的车牌识别系统(附项目地址)ba
- Python学习系列day2-python基础
- 北大计算机学院冯岩松,冯岩松__北京理工大学机电学院
- 【PL/SQL】学习笔记 (1)一个简单的PL/SQL程序
- testmarkdown
- 单机俄罗斯方块游戏制作心得(四)
- [2018.03.13 T3]联盟(alliances)
- Linux驱动开发 / 字符设备驱动内幕 (1)
- MT4跨平台跟单系统(API跟单、EA跟单、NJ4X跟单)的实现方式和技术原理
- 约翰·冯·诺依曼的开挂人生
- 【烈日炎炎战后端】Git(0.1万字)
- 深度学习(七)——图像验证码破解(数字加减验证码)
- 2022研究生学术与职业素养讲座(MOOC)期末答案
- 平行世界真的存在吗?镜像宇宙的三个科学奥秘
- 如何让百度搜索到我的博客或者网站
- 最先进的智能采茶机器人_一种智能采茶机器人的制作方法
- GUI素材-FLASH模板集
- 前端三剑客 - HTML