首页
社区
课程
招聘
[原创]CVE-2012-1535 Flash漏洞调试笔记
2012-8-24 21:11 11212

[原创]CVE-2012-1535 Flash漏洞调试笔记

2012-8-24 21:11
11212
CVE-2012-1535 Flash漏洞调试笔记

前言:
    好久没来看雪,看了古河的分析之前,自己也调了一下这个洞。感觉现在漏洞分析贴,一般自己分析完之后,会按照正向的思路写下整个触发成因。这种公告式的制式写法确实清晰明了,却删减了大量原创作者在分析过程中的思路和数据追踪、回溯的轨迹。造成分析爱好者无法学习,只能膜拜。也许这是一种门槛吧。
    本文反其道而行之。着力点在于从现象挖掘本质,注重描述作者个人的思路和分析方法。希望对大家有所帮助,供大家共同学习。

环境:
Windows XP en +windbg
Adobe Flash Player ActiveX 11.1.102.63

样本:
见同版块古河的帖子。

1, 打开windbg,进行如下设置:
gflags.exe /i iexplore.exe +hpa
0:000> g
(c4.4cc): Access violation - code c0000005 (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
eax=1e0d0000 ebx=1e0cfff0 ecx=000004f4 edx=00000000 esi=0535df70 edi=053697f0
eip=103d7a0e esp=0013dd48 ebp=0013dd80 iopl=0         nv up ei pl nz na po nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00050202
Flash11g!DllUnregisterServer+0x23bfb5:
103d7a0e ff5008          call    dword ptr [eax+8]    ds:0023:1e0d0008=????????

发现异常,简单的数据回溯追踪后,设置如下断点:
sxe ld:Flash11g.ocx
bp 103d7bd0
bp 103d7d6b ".echo *****************************************; r esi; kp L20;.echo **************************************; gc;
"

2, 进入sub_103D7BD0函数(此时设置虚拟机快照,以后每次恢复,保证上下文每次分析都相同):我们发现离esi比较近的赋值语句
.text:103D7D57                 mov     esi, eax

bp 103D7D57 ".echo Signal####################; r eax; .echo the virtual call:; dd poi(eax)+8 L1; .echo $$$$$$$$$$$$$$$$$$$$End; gc;"
0:000> g
Signal####################
eax=0535df70
the virtual call:
0535c1b8  100336df
####################

......

Signal####################
eax=0535df70
the virtual call:
0535c1b8  100336df
####################
Signal####################
eax=0535df70
the virtual call:
0535c1b8  00000000
####################
......

Signal####################
eax=0535df70
the virtual call:
0535c1b8  00000000
####################
Signal####################
eax=0535df70
the virtual call:
1e0d0008  ????????
####################
Signal####################
eax=0535df70
the virtual call:
1e0d0008  ????????
####################
*****************************************
esi=0535df70
1e0d0008  ????????
**************************************
eax=00000000 ebx=1e0cfff0 ecx=000004f4 edx=00000000 esi=0535df70 edi=053697f0
eip=103d7d6b esp=0013dd58 ebp=0013dd80 iopl=0         nv up ei pl zr na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00040246
Flash11g!DllUnregisterServer+0x23c312:
103d7d6b e88ffcffff      call    Flash11g!DllUnregisterServer+0x23bfa6 (103d79ff)


3, 我们发现eax所指向的dword经过几次重要的变化,正是最后的变化,导致访问虚表函数失败。对其下内存写入断点。重新开始
ba w1 0535df70 ".echo mem changed--------------; r ebx; dd poi(0535df70)+8 L1; "
...
Signal####################
eax=0535df70
the virtual call:
0535c1b8  00000000
$$$$$$$$$$$$$$$$$$$$End
Signal####################
eax=0535df70
the virtual call:
0535c1b8  00000000
$$$$$$$$$$$$$$$$$$$$End
mem changed--------------
1e0d0000  ????????
eax=1e0cfff8 ebx=1e0cfff0 ecx=00e40206 edx=00000000 esi=0535df68 edi=053697f0
eip=103d7cfa esp=0013dd5c ebp=0013dd80 iopl=0         nv up ei pl zr na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00040246
Flash11g!DllUnregisterServer+0x23c2a1:
103d7cfa 7512            jne     Flash11g!DllUnregisterServer+0x23c2b5 (103d7d0e) [br=0]


4, 指令mov [esi+8], eax是关键,直接导致后面的执行异常。我们必须在此处追踪eax的来源。发现跟ebx有关,我们在循环中读取一下ebx的值。
发现在第一次循环后,ebx已经是这个值了。继续追踪ebx的来源
.text:103D7C05                 push    8
.text:103D7C07                 jmp     short loc_103D7C1D
.text:103D7C09 ; ---------------------------------------------------------------------------
.text:103D7C09
.text:103D7C09 loc_103D7C09:                           ; CODE XREF: sub_103D7BD0+21j
.text:103D7C09                 cmp     eax, 0FFFFh
.text:103D7C0E                 ja      loc_103D7D76
.text:103D7C14                 mov     [ebp+var_14], 1
.text:103D7C1B                 push    4
.text:103D7C1D
.text:103D7C1D loc_103D7C1D:                           ; CODE XREF: sub_103D7BD0+37j
.text:103D7C1D                 pop     ebx             //执行完这个之后,ebx=8

.text:103D7D54                 add     ebx, [ebp+var_18]  //加上后,是不是ebx就确定了?
.text:103D7D57                 mov     esi, eax


5, 我们猜测以上两个地方决定了ebx的值。
bp 103D7D54 ".echo trace ebx from where:; r ebx;.echo : +++++++++++++++++++++++; "重新开始下
0:000> g
trace ebx from where:
ebx=00000008
+++++++++++++++++++++++
eax=0535df70 ebx=00000008 ecx=00000001 edx=00000000 esi=05359048 edi=053697f0
eip=103d7d54 esp=0013dd5c ebp=0013dd80 iopl=0         nv up ei pl nz na po nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00040202
Flash11g!DllUnregisterServer+0x23c2fb:
103d7d54 035de8          add     ebx,dword ptr [ebp-18h] ss:0023:0013dd68=1e0cffe8


可以看出1e0cffe8+8 =1E0CFFF0。证实了我们的猜测。接下来追踪ebp-18h指向的内存数据的变化来源。

6, 设置内存写入断点,初步假设ebp-18h始终为0013dd68。栈针一般不会有变化的。
ba w1 0013dd68 ".echo poi(0013dd68) has changed:; dd 0013dd68 L1; .echo ------------------------------;"

0:000> bp 103D7D57 ".echo Signal####################; r eax; .echo the virtual call:; dd poi(eax)+8 L1; .echo $$$$$$$$$$$$$$$$$$$$End; gc;"
0:000> bp 103D7D54 ".echo trace ebx from where:; r ebx;.echo +++++++++++++++++++++++; "
0:000> ba w1 0013dd68 ".echo poi(0013dd68) has changed:; dd 0013dd68 L1; .echo ------------------------------;"
0:000> g
poi(0013dd68) has changed:
0013dd68  1e0cffe8
------------------------------
eax=1e0cffe8 ebx=00000008 ecx=000000ff edx=00000000 esi=05359048 edi=053697f0
eip=103d7ce0 esp=0013dd50 ebp=0013dd80 iopl=0         nv up ei pl nz na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00040206
Flash11g!DllUnregisterServer+0x23c287:
103d7ce0 8b4510          mov     eax,dword ptr [ebp+10h] ss:0023:0013dd90=00003000

对应的IDA查看如下:
.text:103D7CD5 loc_103D7CD5:                           ; CODE XREF: sub_103D7BD0+D8j
.text:103D7CD5                 push    ebx
.text:103D7CD6                 push    [ebp+arg_4]
.text:103D7CD9                 push    edi
.text:103D7CDA                 call    dword ptr [edi+18h]  //关键函数啦
.text:103D7CDD                 mov     [ebp+var_18], eax ; poi(0013dd68) has changed


7, 在103D7CDA处下断点。查看函数执行的过程
0:000> bp 103d7cda
0:000> ba w1 0013dd68 ".echo poi(0013dd68) has changed:; dd 0013dd68 L1; .echo ------------------------------;"
0:000> g
Breakpoint 2 hit
eax=00003000 ebx=00000008 ecx=05413000 edx=00000000 esi=05359048 edi=053697f0
eip=103d7cda esp=0013dd50 ebp=0013dd80 iopl=0         nv up ei pl zr na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00040246
Flash11g!DllUnregisterServer+0x23c281:
103d7cda ff5718          call    dword ptr [edi+18h]  ds:0023:05369808=103d85bb
0:000> dds esp esp+20
0013dd50  053697f0
0013dd54  0013ddf8
0013dd58  00000008
0013dd5c  0013ddf8
0013dd60  05848020
0013dd64  0535c1b0
0013dd68  103cb90c Flash11g!DllUnregisterServer+0x22feb3
0013dd6c  00000000
0013dd70  00000000


8, 在函数103d85bb中,比较关键的代码如下:
.text:103D85F8                 mov     ecx, [esi+40h]  //ecx = 0541788d 
.text:103D85FB                 add     eax, ecx        //eax = 8 +ecx = 05417895
.text:103D85FD                 movzx   ebx, byte ptr [eax]  
.text:103D8600                 movzx   ecx, byte ptr [eax+1]
.text:103D8611                 shl     ebx, 8
.text:103D8614                 or      ebx, ecx
.text:103D8616                 shl     ebx, 8
.text:103D8619                 or      ebx, eax


0:000> db 05417895(ecx+eax)
05417895  1e 0c ff e8 30 00 00 0b-0d da 00 03 00 22 ff a2  ....0........"..
054178a5  00 03 00 2b ff 81 00 03-00 35 00 1a 00 03 00 79  ...+.....5.....y
054178b5  ff a2 00 03 00 7b ff a2-00 03 00 7c ff a2 00 03  .....{.....|....


很明显的可以看出,这段代码的意思,就是把ebx赋值成0x1e0cffe8

9,我们需要追踪内存地址处05417895的来源,由指令可见,主要是来源于esi+40h。而esi则是函数压入的第一个参数值(初步猜测为某个类型的基址假定为baseAddr)
这样我们推断,这个地址来源于poi(baseAddr+40)+8 =05417895。而且此处地址指向的内存一直没有发生变化。
0:000> bp 103d7bd0
*** ERROR: Symbol file could not be found.  Defaulted to export symbols for C:\WINDOWS\system32\Macromed\Flash\Flash11g.ocx - 
0:000> bp 103d7d6b ".echo *****************************************; r esi; dd poi(esi)+8 L1; .echo **************************************;"
0:000> g
Breakpoint 0 hit
eax=053697f0 ebx=0535c1b0 ecx=0000003d edx=0000009c esi=05848020 edi=0013ddf8
eip=103d7bd0 esp=0013dd84 ebp=0013dda8 iopl=0         nv up ei pl nz na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00040206
Flash11g!DllUnregisterServer+0x23c177:
103d7bd0 55              push    ebp
0:000> db 05417895
05417895  1e 0c ff e8 30 00 00 0b-0d da 00 03 00 22 ff a2  ....0........"..
054178a5  00 03 00 2b ff 81 00 03-00 35 00 1a 00 03 00 79  ...+.....5.....y
054178b5  ff a2 00 03 00 7b ff a2-00 03 00 7c ff a2 00 03  .....{.....|....


10, 我们搜索这些数据是否在swf中,果然一下子找到了。我们把swf中的这个改成0c0c0c0c,那么最后call的地方应该是0c0c0c2c。重新加载:
This exception may be expected and handled.
eax=0c0c0c24 ebx=0c0c0c14 ecx=000004f5 edx=00000000 esi=0345df80 edi=034697f0
eip=103d7a0e esp=0013dd48 ebp=0013dd80 iopl=0         nv up ei pl nz na po nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00050202
*** ERROR: Symbol file could not be found.  Defaulted to export symbols for C:\WINDOWS\system32\Macromed\Flash\Flash11g.ocx - 
Flash11g!DllUnregisterServer+0x23bfb5:
103d7a0e ff5008          call    dword ptr [eax+8]    ds:0023:0c0c0c2c=????????

验证了我们的猜想,EIP完全可控。
接下来的问题是,为何程序在call这个地址时,简单来说前面的分析可知,call的函数地址其实是poi(addressBase)+8。这个addressBase所指向的本来应该是个正常
的值。后期被覆盖成一个非法的了,而且这个非法的值来源于swf文件内部。

11, addressBase在本实例中为0535df70。单步跟一下sub_103D7BD0。我们发现执行这个函数过后,返回的正是此值。
.text:103D7C27                 mov     eax, [ebp+arg_0]
.text:103D7C2A                 push    10h
.text:103D7C2C                 push    eax
.text:103D7C2D                 call    dword ptr [eax] ; AllocMem Return 0535df70

初步猜测这是个内存的提取函数。而大函数sub_103D7BD0的第一个参数是内存池的提取索引(应该是个类基址一样的东西)我们定义这个函数为GetPoolMem。
记住,函数执行返回的内存池地址为0535df70。

后期内存池类基址(姑且叫这个名吧)首先被放在这个地方
.text:103D7C44                 mov     eax, [ebp+arg_8]   //0x10000000(这个数值的来源一会再说)
.text:103D7C47                 mov     ecx, [ebp+arg_0]   //内存池类基址
.text:103D7C4A                 mov     [esi+8], eax       //存储在addressBase+8的地方
.text:103D7C4D                 shl     eax, 4             // eax= 0x10000000 *0x10
.text:103D7C50                 push    eax
.text:103D7C51                 push    ecx
.text:103D7C52                 mov     [esi], ecx        //内存池类基址(参数一)存储在addressBase的地方
.text:103D7C54                 mov     [esi+4], edi
.text:103D7C57                 call    dword ptr [ecx]   //调用GetPoolMem


我们发现第二次调用了GetPoolMem函数。记下返回值为05359048 < 0535df70 (我们把第二次返回的记录为addressBase2)
0:000> db eax
05359048  44 90 35 05 54 90 35 05-00 00 00 00 50 90 35 05  D.5.T.5.....P.5.
05359058  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00  ................


该返回值被保存在AddressBase+0c的位置
.text:103D7C5D                 mov     [esi+0Ch], eax


接下来进行一系列对刚分配的缓冲区的操作。

12,主要是一个大循环,从addressBase2开始,每次都是0x10个操作单元。
.text:103D7C8A Circle_Handler:                         ; CODE XREF: sub_103D7BD0+18Cj
.text:103D7C8A                 mov     esi, [esi+0Ch]  ; esi = AddressBase2
.text:103D7C8D                 add     esi, [ebp+var_4] ; var_4每次都加10,进而AddressBase2每次都加10
.text:103D7C90                 lea     eax, [ebx+4]
.text:103D7C93                 push    eax
.text:103D7C94                 push    [ebp+arg_4]
.text:103D7C97                 push    edi
.text:103D7C98                 call    dword ptr [edi+0Ch] ; 第一次返回0x300,一会再看
.text:103D7C9B                 add     esp, 0Ch
.text:103D7C9E                 cmp     [ebp+var_14], 0 ; 这地方没看明白,估计会回来
.text:103D7CA2                 mov     [ebp+arg_8], eax
.text:103D7CA5                 mov     [esi+4], ebx    ; addressBase2+4修改
.text:103D7CA8                 jz      short loc_103D7CD5
.text:103D7CAA                 lea     eax, [ebx+2]
.text:103D7CAD                 push    eax
.text:103D7CAE                 push    [ebp+arg_4]
.text:103D7CB1                 push    edi
.text:103D7CB2                 call    dword ptr [edi+0Ch]
.text:103D7CB5                 mov     [ebp+var_18], eax
.text:103D7CB8                 mov     eax, [ebp+arg_8]
.text:103D7CBB                 sar     eax, 8
.text:103D7CBE                 mov     [esi], eax
.text:103D7CC0                 add     esp, 0Ch
.text:103D7CC3                 test    byte ptr [ebp+arg_8], 1
.text:103D7CC7                 lea     eax, [ebx+6]
.text:103D7CCA                 mov     [esi+8], eax
.text:103D7CCD                 jz      short loc_103D7D0E
.text:103D7CCF                 test    byte ptr [ebp+arg_8], 6
.text:103D7CD3                 jmp     short loc_103D7D0C
.text:103D7CD5 ; ---------------------------------------------------------------------------
.text:103D7CD5
.text:103D7CD5 loc_103D7CD5:                           ; CODE XREF: sub_103D7BD0+D8j
.text:103D7CD5                 push    ebx
.text:103D7CD6                 push    [ebp+arg_4]
.text:103D7CD9                 push    edi
.text:103D7CDA                 call    dword ptr [edi+18h] ; 第三次调用,读取1e0cffe8
.text:103D7CDD                 mov     [ebp+var_18], eax ; poi(0013dd68) has changed
.text:103D7CE0                 mov     eax, [ebp+arg_8] ; 刚函数的返回值0x300
.text:103D7CE3                 and     eax, 0FFh       ; eax=0
.text:103D7CE8                 mov     [esi], eax      ; counter的比较值被修改成0,导致第二次循环退出。
.text:103D7CEA                 add     esp, 0Ch
.text:103D7CED                 test    [ebp+arg_8], 0C000h ; 0x300比较
.text:103D7CF4                 lea     eax, [ebx+8]
.text:103D7CF7                 mov     [esi+8], eax    ; poi(0535df70) changed 2ed
.text:103D7CFA                 jnz     short loc_103D7D0E
.text:103D7CFC                 lea     eax, [ebx+6]
.text:103D7CFF                 push    eax
.text:103D7D00                 push    [ebp+arg_4]
.text:103D7D03                 push    edi
.text:103D7D04                 call    dword ptr [edi+0Ch] ; 又调用这个,不知道干啥,应该是couter之类的。。。返回0x0b
.text:103D7D07                 add     esp, 0Ch
.text:103D7D0A                 test    eax, eax
.text:103D7D0C
.text:103D7D0C loc_103D7D0C:                           ; CODE XREF: sub_103D7BD0+103j
.text:103D7D0C                 jz      short loc_103D7D12
.text:103D7D0E
.text:103D7D0E loc_103D7D0E:                           ; CODE XREF: sub_103D7BD0+FDj
.text:103D7D0E                                         ; sub_103D7BD0+12Aj
.text:103D7D0E                 and     dword ptr [esi+8], 0 ; addressBase2+8 修改
.text:103D7D12
.text:103D7D12 loc_103D7D12:                           ; CODE XREF: sub_103D7BD0:loc_103D7D0Cj
.text:103D7D12                 mov     eax, [esi]
.text:103D7D14                 test    eax, eax
.text:103D7D16                 jnz     short loc_103D7D2F
.text:103D7D18                 push    dword ptr [esi+8]
.text:103D7D1B                 push    [ebp+arg_4]
.text:103D7D1E                 push    edi
.text:103D7D1F                 call    dword ptr [edi+0Ch] ; 返回1
.text:103D7D22                 add     esp, 0Ch
.text:103D7D25                 dec     eax
.text:103D7D26                 add     dword ptr [esi+8], 8 ; AddressBase2+8修改
.text:103D7D2A                 mov     [esi+0Ch], eax  ; AddressBase2+0c修改
.text:103D7D2D                 jmp     short loc_103D7D3E
.text:103D7D2F ; ---------------------------------------------------------------------------
.text:103D7D2F
.text:103D7D2F loc_103D7D2F:                           ; CODE XREF: sub_103D7BD0+146j
.text:103D7D2F                 cmp     eax, 2
.text:103D7D32                 jnz     short loc_103D7D3A
.text:103D7D34                 or      dword ptr [esi+0Ch], 0FFFFFFFFh
.text:103D7D38                 jmp     short loc_103D7D3E
.text:103D7D3A ; ---------------------------------------------------------------------------
.text:103D7D3A
.text:103D7D3A loc_103D7D3A:                           ; CODE XREF: sub_103D7BD0+162j
.text:103D7D3A                 and     dword ptr [esi+8], 0
.text:103D7D3E
.text:103D7D3E loc_103D7D3E:                           ; CODE XREF: sub_103D7BD0+15Dj
.text:103D7D3E                                         ; sub_103D7BD0+168j
.text:103D7D3E                 cmp     dword ptr [esi+8], 0
.text:103D7D42                 jnz     short loc_103D7D47
.text:103D7D44                 inc     [ebp+var_10]
.text:103D7D47
.text:103D7D47 loc_103D7D47:                           ; CODE XREF: sub_103D7BD0+172j
.text:103D7D47                 inc     [ebp+var_8]     ; 注意了,couter自加了
.text:103D7D4A                 mov     eax, [ebp+var_C]
.text:103D7D4D                 mov     ecx, [ebp+var_8]
.text:103D7D50                 add     [ebp+var_4], 10h
.text:103D7D54                 add     ebx, [ebp+var_18] ; ebx此时被赋值0x1e0cfff0
.text:103D7D57                 mov     esi, eax
.text:103D7D59                 cmp     ecx, [eax+8]    ; 循环0x10000000次
.text:103D7D5C                 jb      Circle_Handler


根据前面的调试,最终在.text:103D7CF7处,AddressBase1的内容被覆盖为1e0cfff8 。这个应该是循环次数为0x10000000,但是前面AddressBase2分配时整形乘法
溢出造成实际分配的内存为0,覆盖了AddressBase1。我们接下来看下这个循环是如何退出的。继续单步跟踪下(其实没几行代码的,耐心。。。)
在这里我们对103D7D59处设置断点,查下ecx的counter值多少时退出的。(其实前面的调试2步中可以看出是0x4f4)
bp 103D7D59 ".echo counter num:; r ecx; .echo AddressBase1 Mem Status:; dd eax L10; .echo ++++++++++++; gc;"
ba w1 0535df70 ".echo mem changed--------------; "

0:000> bp 103D7D59 ".echo counter num:; r ecx; .echo AddressBase1 Mem Status:; dd eax L10; .echo ++++++++++++; gc;"
0:000> ba w1 0535df70 ".echo mem changed--------------; "
0:000> g
mem changed--------------
eax=00000000 ebx=00000008 ecx=0535c1b0 edx=00000000 esi=0535df70 edi=053697f0
eip=103d7c54 esp=0013dd54 ebp=0013dd80 iopl=0         nv up ei pl zr na pe cy
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00040247
Flash11g!DllUnregisterServer+0x23c1fb:
103d7c54 897e04          mov     dword ptr [esi+4],edi ds:0023:0535df74=00000000
0:000> g
counter num:
ecx=00000001
AddressBase1 Mem Status:
0535df70  0535c1b0 053697f0 10000000 05359048
0535df80  00000000 00000000 00000000 00000000
0535df90  00000000 00000000 00000000 00000000
0535dfa0  00000000 00000000 00000000 00000000
++++++++++++
counter num:
ecx=00000002
AddressBase1 Mem Status:
0535df70  0535c1b0 053697f0 10000000 05359048
0535df80  00000000 00000000 00000000 00000000
0535df90  00000000 00000000 00000000 00000000
0535dfa0  00000000 00000000 00000000 00000000
++++++++++++
counter num:
ecx=00000003
AddressBase1 Mem Status:
0535df70  0535c1b0 053697f0 10000000 05359048
0535df80  00000000 00000000 00000000 00000000
0535df90  00000000 00000000 00000000 00000000
0535dfa0  00000000 00000000 00000000 00000000
++++++++++++

......
......

counter num:
ecx=000004f2
AddressBase1 Mem Status:
0535df70  0535c1b0 053697f0 10000000 05359048
0535df80  00000000 00000000 00000000 00000000
0535df90  00000000 00000000 00000000 00000000
0535dfa0  00000000 00000000 00000000 00000000
++++++++++++
mem changed--------------
eax=1e0cfff8 ebx=1e0cfff0 ecx=00e40206 edx=00000000 esi=0535df68 edi=053697f0
eip=103d7cfa esp=0013dd5c ebp=0013dd80 iopl=0         nv up ei pl zr na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00040246
Flash11g!DllUnregisterServer+0x23c2a1:
103d7cfa 7512            jne     Flash11g!DllUnregisterServer+0x23c2b5 (103d7d0e) [br=0]


这时我们修改下其中一个断点:
bp 103D7D59 ".echo counter num:; r ecx; .echo AddressBase1 Mem Status:; dd eax L10; .echo ++++++++++++;"
0:000> bp 103D7D59 ".echo counter num:; r ecx; .echo AddressBase1 Mem Status:; dd eax L10; .echo ++++++++++++;"
breakpoint 2 redefined
0:000> g
mem changed--------------
eax=ffffffff ebx=1e0cfff0 ecx=00900206 edx=00000000 esi=0535df68 edi=053697f0
eip=103d7d2a esp=0013dd5c ebp=0013dd80 iopl=0         nv up ei pl nz ac pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00040216
Flash11g!DllUnregisterServer+0x23c2d1:
103d7d2a 89460c          mov     dword ptr [esi+0Ch],eax ds:0023:0535df74=053697f0
0:000> g
counter num:
ecx=000004f3
AddressBase1 Mem Status:
0535df70  1e0d0000 ffffffff 10000000 05359048
0535df80  00000000 00000000 00000000 00000000
0535df90  00000000 00000000 00000000 00000000
0535dfa0  00000000 00000000 00000000 00000000
++++++++++++
eax=0535df70 ebx=1e0cfff0 ecx=000004f3 edx=00000000 esi=0535df70 edi=053697f0
eip=103d7d59 esp=0013dd5c ebp=0013dd80 iopl=0         nv up ei pl nz na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00040206
Flash11g!DllUnregisterServer+0x23c300:
103d7d59 3b4808          cmp     ecx,dword ptr [eax+8] ds:0023:0535df78={Flash11g (10000000)}
0:000> g
counter num:
ecx=000004f4
AddressBase1 Mem Status:
0535df70  1e0d0000 ffffffff 00000000 1e0cfff0
0535df80  1e0d0000 ffffffff 00000000 00000000
0535df90  00000000 00000000 00000000 00000000
0535dfa0  00000000 00000000 00000000 00000000
++++++++++++
eax=0535df70 ebx=1e0cfff0 ecx=000004f4 edx=00000000 esi=0535df70 edi=053697f0
eip=103d7d59 esp=0013dd5c ebp=0013dd80 iopl=0         nv up ei pl nz na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00040206
Flash11g!DllUnregisterServer+0x23c300:
103d7d59 3b4808          cmp     ecx,dword ptr [eax+8] ds:0023:0535df78=00000000


13, counter走到0x4f4,我们发现ecx比较的一直是poi(AddressBase1+8),已经在上一轮循环中被修改成0了。直接导致比较失败。我们看下这个值是何时被改成0
的。
bp 103D7D59 ".echo counter num:; r ecx; .echo AddressBase1 Mem Status:; dd eax L10; .echo ++++++++++++; gc;"
ba w1 0535df70 ".echo mem changed--------------; "
ba w1 0535df78 ".echo counter compared num changed*******************;"

0:000> g
counter compared num changed*******************
eax=10000000 ebx=00000008 ecx=0535c1b0 edx=00000000 esi=0535df70 edi=053697f0
eip=103d7c4d esp=0013dd5c ebp=0013dd80 iopl=0         nv up ei pl nz na po nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00040202
Flash11g!DllUnregisterServer+0x23c1f4:
103d7c4d c1e004          shl     eax,4    //这个是最开始保存函数返回的0x10000000,竟然就保存在AddressBase1+8的位置。后面一直用它索引。
0:000> g
mem changed--------------
eax=00000000 ebx=00000008 ecx=0535c1b0 edx=00000000 esi=0535df70 edi=053697f0
eip=103d7c54 esp=0013dd54 ebp=0013dd80 iopl=0         nv up ei pl zr na pe cy
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00040247
Flash11g!DllUnregisterServer+0x23c1fb:
103d7c54 897e04          mov     dword ptr [esi+4],edi ds:0023:0535df74=00000000
0:000> g
counter num:
ecx=00000001
AddressBase1 Mem Status:
0535df70  0535c1b0 053697f0 10000000 05359048
0535df80  00000000 00000000 00000000 00000000
0535df90  00000000 00000000 00000000 00000000
0535dfa0  00000000 00000000 00000000 00000000
++++++++++++
counter num:
ecx=00000002
AddressBase1 Mem Status:
0535df70  0535c1b0 053697f0 10000000 05359048
0535df80  00000000 00000000 00000000 00000000
0535df90  00000000 00000000 00000000 00000000
0535dfa0  00000000 00000000 00000000 00000000
++++++++++++
......
......
......

counter num:
ecx=000004f2
AddressBase1 Mem Status:
0535df70  0535c1b0 053697f0 10000000 05359048
0535df80  00000000 00000000 00000000 00000000
0535df90  00000000 00000000 00000000 00000000
0535dfa0  00000000 00000000 00000000 00000000
++++++++++++
mem changed--------------
eax=1e0cfff8 ebx=1e0cfff0 ecx=00e40206 edx=00000000 esi=0535df68 edi=053697f0
eip=103d7cfa esp=0013dd5c ebp=0013dd80 iopl=0         nv up ei pl zr na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00040246
Flash11g!DllUnregisterServer+0x23c2a1:
103d7cfa 7512            jne     Flash11g!DllUnregisterServer+0x23c2b5 (103d7d0e) [br=0]
0:000> g
mem changed--------------
eax=ffffffff ebx=1e0cfff0 ecx=00900206 edx=00000000 esi=0535df68 edi=053697f0
eip=103d7d2a esp=0013dd5c ebp=0013dd80 iopl=0         nv up ei pl nz ac pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00040216
Flash11g!DllUnregisterServer+0x23c2d1:
103d7d2a 89460c          mov     dword ptr [esi+0Ch],eax ds:0023:0535df74=053697f0
0:000> g
counter num:
ecx=000004f3
AddressBase1 Mem Status:
0535df70  1e0d0000 ffffffff 10000000 05359048
0535df80  00000000 00000000 00000000 00000000
0535df90  00000000 00000000 00000000 00000000
0535dfa0  00000000 00000000 00000000 00000000
++++++++++++
counter compared num changed*******************
eax=00000000 ebx=1e0cfff0 ecx=00e40206 edx=00000000 esi=0535df78 edi=053697f0
eip=103d7cea esp=0013dd50 ebp=0013dd80 iopl=0         nv up ei pl zr na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00040246
Flash11g!DllUnregisterServer+0x23c291:
103d7cea 83c40c          add     esp,0Ch


这里就找到counter比较值修改的地方了。现在大致搞清楚了。整形溢出导致分配的AddressBase2内存池长度为0,而后进行的操作以它的基址开始,仍然进行
原始的赋值操作循环,影响开始分配的内存池AddressBase1。在赋值过程中计数器的比较值也被修改,导致循环退出。而后在进一步的操作中,本来一开始
AddressBase1索引着内存池一系列的操作函数(0535c1b0)。结果这么一搞尼玛被修改成无效的地址1e0d0000了。直接导致call异常。所有的这些地址都可控。

14, 整个分析完成后,再去看古河的帖子,估计也不用我在这里重复描述一下他正向分析的过程吧。另外,结构体、数据解析之类的见他的文章。另附古河的帖子链接:http://bbs.pediy.com/showthread.php?t=154860

[培训]二进制漏洞攻防(第3期);满10人开班;模糊测试与工具使用二次开发;网络协议漏洞挖掘;Linux内核漏洞挖掘与利用;AOSP漏洞挖掘与利用;代码审计。

收藏
点赞3
打赏
分享
最新回复 (22)
雪    币: 401
活跃值: (330)
能力值: ( LV12,RANK:230 )
在线值:
发帖
回帖
粉丝
cscoder 5 2012-8-24 21:27
2
0
沙发!期待楼主造福人类的asLib
雪    币: 429
活跃值: (1875)
能力值: ( LV17,RANK:1820 )
在线值:
发帖
回帖
粉丝
riusksk 41 2012-8-24 21:41
3
0
占座学习!期待楼主造福人类的asLib
雪    币: 6
活跃值: (980)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
lookzo 2012-8-24 23:40
4
0
占位顶贴,呵呵
雪    币: 579
活跃值: (168)
能力值: ( LV6,RANK:90 )
在线值:
发帖
回帖
粉丝
金罡 1 2012-8-25 00:06
5
0
我来晚了,古河出品,必出精品。
雪    币: 609
活跃值: (172)
能力值: ( LV9,RANK:140 )
在线值:
发帖
回帖
粉丝
小覃 2 2012-8-25 01:34
6
0
gflags.exe /i iexplore.exe +hpa
不错!
雪    币: 389
活跃值: (150)
能力值: (RANK:110 )
在线值:
发帖
回帖
粉丝
wingdbg 2 2012-8-25 08:40
7
0
古河的帖子在另外一篇,这个不是古河写的。。。
雪    币: 820
活跃值: (380)
能力值: ( LV12,RANK:310 )
在线值:
发帖
回帖
粉丝
古河 6 2012-8-25 09:41
8
0
进来学习!期待楼主造福人类的asLib
雪    币: 220
活跃值: (626)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
dayang 2012-8-25 15:25
9
0
我用MSF生成的样本不成功啊
雪    币: 1015
活跃值: (235)
能力值: ( LV12,RANK:440 )
在线值:
发帖
回帖
粉丝
loongzyd 10 2012-8-26 08:59
10
0
站位,谢谢楼主,要详细学习。
雪    币: 239
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
天行客 2012-8-26 11:50
11
0
占座学习!期待楼主造福人类的asLib
雪    币: 253
活跃值: (46)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
tangwenbin 1 2012-8-27 07:58
12
0
学习。期待楼主造福人类的asLib
雪    币: 159
活跃值: (40)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
PEYlxZ 2012-8-27 08:58
13
0
看清楚再回啊 大哥们  古河大神在隔壁啊
雪    币: 40
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
误码率 2012-8-28 13:34
14
0
控制EIP的地方是在哪儿
雪    币: 389
活跃值: (150)
能力值: (RANK:110 )
在线值:
发帖
回帖
粉丝
wingdbg 2 2012-8-28 15:39
15
0
  文档里面说的很清楚啊,你仔细看下,肯定能发现。
雪    币: 40
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
误码率 2012-8-29 11:05
16
0
我用metasploit生成的样本,在虚拟机上测试的时候,在还没运行到CALL [EAX+8]的时候,就因为某个寄存器的值变成了1E0D0000,导致后面的操作
10086067    8B46 44         MOV EAX,DWORD PTR DS:[ESI+44]
1008606A    8B88 9C050000   MOV ECX,DWORD PTR DS:[EAX+59C]
因为现在ESI=1e0d0000,所以[ESI+44]取出的刚好是shellcode中的某个字到EAX,导致[EAX+59C]是个非法的空间而奔溃了,新手求解这是咋回事啊
雪    币: 133
活跃值: (546)
能力值: ( LV4,RANK:40 )
在线值:
发帖
回帖
粉丝
njxxdx 2012-8-29 11:11
17
0
源文档里把过掉heapSpray有什么用?heapSpray是用于构造shellcode的
雪    币: 1489
活跃值: (955)
能力值: (RANK:860 )
在线值:
发帖
回帖
粉丝
仙果 19 2012-8-29 11:20
18
0
构造样本的过程,需要么?
想把构造的过程写出来,但不知道有没有人看
雪    币: 40
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
误码率 2012-8-29 11:41
19
0
需要~不怕学的多
雪    币: 40
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
误码率 2012-8-29 11:44
20
0
[QUOTE=误码率;1098053]我用metasploit生成的样本,在虚拟机上测试的时候,在还没运行到CALL [EAX+8]的时候,就因为某个寄存器的值变成了1E0D0000,导致后面的操作
10086067    8B46 44         MOV EAX,DWORD PTR DS:[ESI+44]
1008606A   ...[/QUOTE]

我重装了另一个虚拟机可以了,就是不解是怎么回事~求解释
雪    币: 310
活跃值: (159)
能力值: ( LV12,RANK:200 )
在线值:
发帖
回帖
粉丝
kindsjay 4 2012-9-4 16:55
21
0
风骚的走位,占座
雪    币: 159
活跃值: (40)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
PEYlxZ 2012-10-12 14:24
22
0
分别用两个快照装了古河和你的flash版本,结果函数地址跟你们的分别都一样,这是巧合?
雪    币: 799
活跃值: (452)
能力值: ( LV12,RANK:280 )
在线值:
发帖
回帖
粉丝
Ox9A82 3 2016-8-11 14:58
23
0
很详细,赞
游客
登录 | 注册 方可回帖
返回