攻击:漏洞利用
触发原理
该漏洞是一个典型的UAF释放重利用的漏洞。用户改写字节数组大小,在原来字节数组释放后,重新分配,导致该数值被写入已经释放的内存中,造成释放重利用。
动态调试
由于Hacking Team泄露出的数据中暴露了Flash 0Day漏洞源码,我们的得以使用CS进行动态调试。
源码级调试分析
利用CS装载源文件中的fla原始档,和其他as文件。生成SWF文件
可以看出先是调用了MyClass.as文件中的InitGui函数来初始化GUI元素并输出一些系统相关信息,点击swf文件中的button按钮就会调用相应的处理函数如下图所示:
6 | 31
处理函数btnClickHandler里面首先调用了TryExpl函数如下图所示:
接下来就看看TryExp1函数里面是怎么样做到漏洞利用的,进入该函数
从给出的源码可以看出先是声明了变量alen=90,然后声明一个数组a,并将数组的各元素赋值,在AS中Array数组类型的变量不像C/C++数组一样要求是同一类型的数据在可以放到数组里面,在AS中不同类型的变量对象可以放到同一数组里面。从源码可以看出,a数组的90个元素是MyClass2对象和
7 | 31
ByteArray类型数组交替出现,并且每分配两个MyClass2元素才会分配一次BtyeArray类型数组,那么实际运行效果是怎么的呢,我们利用CS调试功能在for结束后的下一条语句下了断点显示如下图:
从图中看出我们在for(i=alen-5;i>=0;i-=3)处下了断点,在调试运行后,让a数组填充完毕;左上部紫色的框给出了按钮按下后堆栈中函数调用关系,btnClinckHandler->TryExp1。左下方的红框给出了a数组赋值完成后每个元素的实际值,从图中看出,除了a[0]外,每出现一次ByteArray元素要出现两次MyClass2元素,这和我们刚才通过静态代码分析的结果是一致的。
接下来就是一个for(i=alen-5;i>=0;i=3)语句,前面知道alen=90那么在第一次循环时i=85,通过源代码中的赋值我们知道a[85]的大小是0Xfa0,源码中将_ba=a[i],也就是第一次将a[85]赋给_ba(也就是_ba大小为0xfa0),同时将一个新的Myclass类赋给_ba的第四个字节_ba[3]。如下图所示
8 | 31
接下来就要动态跟踪一下a[i]是不是a[85],如果是a[85] 那么又是什么类型,为了能查看i的值到底是不是a[85],我在源码中添加了一条调试语句trace(“the number of i =”)看i的值打印多少,根据之前设置的断点,单步执行源代码,如下图所示:
从图中可以看出右下方打印出i的值是85,刚好我们分析的一致,从左边图可以看出a[85]元素的类型是ByteArray类型。接下来代码中会将MyClass对象赋值给_ba[3]。由前面介绍的知识我们知道,在MyClass对象赋给一个基本类型时,会调用ValueOf函数,这里给对象MyClass定义了ValueOf函数,所以在赋值之前会调用该函数。
继续单步跟进_ba[3]=new MyClass();调用自定义的ValueOf函数
9 | 31
在我们单步跟踪调试ValueOf函数,_gc数组除了在TryExp1中加入a数组元素外(_gc.push(a)),又通过valueof函数,加入了-va元素(_gc.push(_va)),这样_gc数组就有两个元素,一个是a数组元素,一个是_va数组元素,每个元素又是数组类型,a数组有90个元素,前面已经介绍过了,_va有5个元素,如图中左边显示的结果。在TryExp1中_ba=a[i]大小为0xfa0,在valueof函数中_ba通过_ba.length=0x1100会释放调原来的空间而从新分配内存大小。同时通过后面的_va[i]=new Vector.
而在_ba[3]=new Myclass()中_ba[3]实际指向的内存地址还是释放后的内存地址所以在返回40后被释放的内存的数据就是0x400003f0。
UAF漏洞图解
a. 通过a数组创建ByteArray类型元素数据,设置长度为0xfe0:
b.通过调用valueof函数中的_ba.length=0x1100,释放该空间
c.调用分配vector
d.在valueof返回0x40后,写入到之前_ba[3]指向的地址中
10 | 31