hexj9 |
2015-07-21 15:59 |
源码级调试分析 利用CS装载源文件中的fla原始档,和其他as文件。生成SWF文件
可以看出先是调用了MyClass.as文件中的InitGui函数来初始化GUI元素并输出一些系统相关信息,点击swf文件中的button按钮就会调用相应的处理函数如下图所示:
处理函数btnClickHandler里面首先调用了TryExpl函数如下图所示:
接下来就看看TryExp1函数里面是怎么样做到漏洞利用的,进入该函数
从给出的源码可以看出先是声明了变量alen=90,然后声明一个数组a,并将数组的各元素赋值,在AS中Array数组类型的变量不像C/C++数组一样要求是同一类型的数据在可以放到数组里面,在AS中不同类型的变量对象可以放到同一数组里面。从源码可以看出,a数组的90个元素是MyClass2对象和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,也就是第一次将a[85]赋给_ba(也就是_ba大小为0xfa0),同时将一个新的Myclass类赋给_ba的第四个字节_ba[3]。如下图所示
接下来就要动态跟踪一下a是不是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函数
在我们单步跟踪调试ValueOf函数,_gc数组除了在TryExp1中加入a数组元素外(_gc.push(a)),又通过valueof函数,加入了-va元素(_gc.push(_va)),这样_gc数组就有两个元素,一个是a数组元素,一个是_va数组元素,每个元素又是数组类型,a数组有90个元素,前面已经介绍过了,_va有5个元素,如图中左边显示的结果。在TryExp1中_ba=a大小为0xfa0,在valueof函数中_ba通过_ba.length=0x1100会释放调原来的空间而从新分配内存大小。同时通过后面的_va=new Vector.(0x3f0)来重新使用释放的内存。前面我们介绍过,在分配vector类型的空间时其前四个字节是vector大小也就是说,在被释放的空间的开始四个字节会写入0x3f0。 而在_ba[3]=new Myclass()中_ba[3]实际指向的内存地址还是释放后的内存地址所以在返回40后被释放的内存的数据就是0x400003f0。 |
|