看雪论坛
发新帖

[原创]XP SP3, IE8, JavaScript 堆喷射经验值的修正及修正思路

Arslonga 2017-8-23 12:23 2381

15PB参加培训刚毕业,

之前上课过程中发现一直广泛使用的一个经验值有问题

现在正好有时间,整理一下发出来


环境:WindowsXP SP3IE8

利用漏洞: 暴雷漏洞 CVE-2012-1889 ( 同学的分析报告在这里 [2])

整体思路:确保每一段填入的数据连续、有效

结论: XP SP3, IE8 下经验值应该改为 block = shellcode.substring(2, 0x40000 - 0x809)

结果:修正前512M内存下失败概率接近1/2,调整后为1/5 1/10; 1G内存下失败率很低,未统计。

代码见附件。


下面开始上主菜:修正过程及修正思路

每当提到IE堆喷射的时候总会提到一套前辈们的经验值,具体出处,还没有找到。

这里[3]

(图1:前辈们的经验值)

还有这里[4]:

(图2:前辈们的经验值)

等等。

当然,我们课上提到的也是同一套经验值。

1. 但是在 WindowsXP SP3IE8 环境下经常会有很大的概率遇到如下错误


(图3:报错信息)

2.  用 windbg 查看报错原因:


(图4:windbg观察错误区域信息)   

     发现 0X0C0C0C0C 处并不是我们理想中的 shellcode ,而是填充的“00

3. 接着网下看,会发现 0X0C0C0C0C 之后是一段不可访问的内存,从 0x0C0C1000 开始

(图5:windbg观察错误区域信息)

4. 那我们的 shellcode 去哪儿了呢,于是接着往下看发现 0x0C0C0C0C + 0x10000又有数据了


(图6:windbg观察堆的结构)

5. 看看这段连续数据有多长,于是在0x0C0C0C0C -  0x90000 位置又是一段,而且每隔 0x90000 就会有一段 00

(图6:windbg观察堆的结构)

6.  接着往下看会发现,同样每隔0x90000 就会出现一段 00 填充的内存


7. 可以看出堆中一个单位块的结构:后两段正好0x10000

数据(大小 0x80000)

00(大小 0x1000)

???(0x10000-0x1000)

    一个单位块的大小正好是 0x90000

    猜测 1:代码中cBlock Unicode)长度正好是 0x40000 大小正好是0x80000,两者之间会不会有关系

    验证猜测:把代码中的cBlock 大小改成 0x50000,于是内存分布变成这样:

   


数据(大小 0xA0000)

00(大小 0x1000)

???(0x10000-0x1000)

     单位块 的大小变成了 0x50000 * 2 + 10000

8.  顺着教材的思路


如果把后边点 0x21 改成0 点话,会发现00 填充段 大小为 0x2000, 无效段 的大小还是 0x10000

   猜测2

 (1)内存中每个块点大小是0x10000对齐的

 (2)堆中每个cBlock末尾都有一段长度介于0x1000 0x2000 之间的00填充段,然后 是一段不可读的区域,补齐到0x10000

把这一段在cBlock 中空出来,改成这样 (注意:这里还是拿cBlock 大小为 0x50000 为例)



     依据: (1) Unicode 0x800大小正好是0x800*2 = 0x1000 字节

                (2) 这里依然减掉那个经验值(0x21), 具体数值是多少后边会进一步验证

                (3) cBlock末尾后四位为0xefd0 开始填充00 ,覆盖不到0C0C0C0C

结果: 可以看出不可访问的区域(那一段问号 ??)没有了

0x50000下块的大小也变成了 0xA0000,后边那个0x10000 的段也没有了(对比第7步的猜侧1


堆块达到了理想中的连续状态。

9.  这也就基本玩工了,那如果再把cBlock 改成0x40000,当然就失败了

于是我们发现 UserPtr 变成这样


        但是当我们再找末尾点那一段00 的时候 他跑到 UserPtr – n*(0x80000 - 1000)的位置

  

   用公式 “偏移值 = (0x0c0c0c0c - Userptr)%0x1000/2” 计算出新的偏移值 602,一切又正常了。

   但是当我们再找末尾点那一段00 的时候 他跑到 UserPtr – n*(0x80000 - 1000)的位置

对比上边nBlockSize = 0x50000的情况看出

0x40000 堆中一个“单位块”的大小为 0x80000 – 1000)字节,末尾为0x42字节。

0x50000 堆中一个“单位块的大小为  0xA0000 字节,末尾为 0x1042 字节(而且由前边点结论可以推断得出,0x50000UserPtr一般为0xXXXX0020,末尾的0x1042 字节不会落在0C0C上)。

所以以上两种参数组合都是可取的,根据进一步测试0x821准确值应该为0x809

调整 0x821 大小cBlock = 0x50000情况下并未得到 cBlock = 0x40000时那种中间相隔很少的一段00 的效果。所以还是无法避免一个分页全部填充成00


结论: XP SP3, IE8 下经验值应该改为 block = shellcode.substring(2, 0x40000 - 0x809)


在这里感谢 15PB 任老师 @A1pass 的指导


目前猜测 跟XP SP3的堆分配机制有关, 目前在看《软件调试》这本书,找出原因的话继续写

有什么问题欢迎交流讨论

邮箱: liupengshx@Gmail.com



参考:

[1] 15PB安全机制绕过课程及和尚资料

[2]【暴雷漏洞】CVE-2012-1889个人漏洞分析报告

[3]  堆喷射学习笔记~                          

[4]  Heap Feng Shui in JavaScript  (中文在这里: JavaScript中的堆风水,中英文对照版)


上传的附件:
本主题帖已收到 0 次赞赏,累计¥0.00
最新回复 (5)
smurf 2017-8-23 17:08
2
沙发给我,支持
朗里格 2017-9-1 09:00
3
高三 2017-9-7 22:23
4
blog.guanggaoqun.net/
1
holing 2017-9-10 16:25
5
不错
wwihacker 2017-9-13 10:31
6
mark
返回



©2000-2017 看雪学院 | Based on Xiuno BBS | 域名 加速乐 保护 | SSL证书 又拍云 提供 | 微信公众号:ikanxue
Time: 0.014, SQL: 11 / 京ICP备10040895号-17