继续之前hackteam的flash漏洞,这次的对象为cve-2015-5199,遂做一下记录。
首先,在该exp中TryExpl函数为漏洞的触发函数,该函数也为本次调试的主要对象,函数的开始首先创建两个Array对象a和_gc.
此处对Array函数下断,对象断在array。
函数返回之后a array对象生成,地址为04115a30,对于Array对象在其偏移+10的地方保存了实际Array内容的地址。此处为03d800d8,03d800d8+8即可观察到array中实际保存的内容。
Gc array对象生成,此处为04115a30。
将a(喷射对象)保存在_gc中,此处主要是考虑到之后会有大量的释放操作,以此来保护a对象内存。
gc.push(a),push之后,a对象的地址保存到了_gc对象中,如下图所示。
开始对a进行循环赋值,一共操作5a次。
生成一次之后,得到一组MyClass2,ByteArray,MyClass2的内存结构。
A对象中对应的两个myclass2和一个array
对应的myclass2
具体对MyClass2结构的布局如下
接下来详细分析一个MyClass2对象的生成过程,下图的call eax jitcode中,实现对MyClass2对象的生成。
该处完成0x11223344赋值,该处jit结束之后,myclass2已经完成赋值。
生成的Bytearray。
生成的第二个Myclass2
循环几次之后a中保存的多组结构。
如下图图所示,最后生成的a ,注意由于内存分配的原因,可以发现,在分配的一开始,每一组myclass2,array,myclass2在内存中并不是连续的,如下图所示,之后内存的分配趋于稳定,最后形成的每一组中的这三个对象在内存空中内存布局连续,这也是为什么之后的exp中循环赋值的时候是从数组后面往前赋值的原因,因为后面内存连续。
a中内存布局完成之后,进入以下循环,在该循环中,会依次将a中Bytearray赋值给_ba,之后MyClass对象的赋值将导致valueof函数的调用。
对应的valuefo函数,该函数中对ba.length的修改,将导致a中对应的Array对象的内存释放,之后代码中的一个循环操作完成对释放对象的站位。
_va Array对象生成,此处的地址为041152e0。
同样申城的_va对象会进行gc.push(_va)的操作。
对_ba.length 进行1100赋值操作。
改变长度之后会导致_ba中的内存重新分配,因为_ba中的值其实就是a中所有的ByteArray结构,所以对于一组Myclass2,ByteArray,Myclass2的连续空间而言,相当于中间的ByetArray
直接被释放。
因为发释放时循环从a array的后向前,如下图所示。
结合之前的中a array的结构,可以确定第一个释放的ByteArra结构的地址为0483b8c9
站位之后可以发现,此时0483b8c9处指向的地址和正常的ByteArray已经不同,此时已被
释放。
释放之后,生成vector.<uint>(0x3f0)用于站位,此处0x3f0*4 = fc0,内存对齐之后,为0x1000,正好满足站位的条件。
查看_va的内存,可以发现,此时vector对象的地址040f8ab1已经保存在_va中,在该对象偏移1c处保存了vector的内存空间的地址,不过同样该处的地址需要>>16的操作,最后vector在0x0489c000处,可以看到在偏移0处正好为vector的长度3f0.
此时释放的ByteArray空间已经被站位,当返回的时候,0x40的值会被赋值给_ba[3]中指向ByteArray的地址,因为此处对于ByteArray的引用存在问题,依然指向old的ByteArray,此时ByteArray内存的地址实际上是我们站位的vector,此时的赋值会将0x40赋值到vector对象长度地址的高位处,从而导致一个超长的vector产生,如下图下断点。
运行之后,产生一个超长的vector
此时已经赋值成功。