当前位置: 首页 >新闻中心

新闻中心
软件漏洞分析的八大技巧汇总(3)
2014-03-28

技巧三:基于堆分配记录定位整数溢出漏洞代码

以CVE-2011-0027 Microsoft Data Access组件整数溢出漏洞为例,这个漏洞就是在Pwn2Own 2010黑客大赛中,荷兰黑客Peter Vreugdenhil利用它来攻破Win7上的IE8浏览器的。

下面是打开poc.html后的异常情况:

(7b8.278): Access violation - code c0000005 (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
eax=0000036b ebx=0000035b ecx=00000000 edx=00000001 esi=088c8000 edi=00000000
eip=6887746f esp=044dee84 ebp=044dee88 iopl=0         nv up ei pl nz na po nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00010202
mshtml!CImpIRowset::HRowNumber2HROWQuiet+0x23:
6887746f 8906            mov     dword ptr [esi],eax  ds:0023:088c8000=????????
0:005> !heap -p -a 088c8000
address 088c8000 found in
_DPH_HEAP_ROOT @ 8821000
in busy allocation (  DPH_HEAP_BLOCK:         UserAddr         UserSize -         VirtAddr         VirtSize)
88227ec:          88c7298             d64-          88c7000             2000
72eb8e89 verifier!AVrfDebugPageHeapAllocate+0x00000229
77034ea6 ntdll!RtlDebugAllocateHeap+0x00000030
76ff7d96 ntdll!RtlpAllocateHeap+0x000000c4
76fc34ca ntdll!RtlAllocateHeap+0x0000023a
730d975d MSDART!MpHeapAlloc+0x00000029
6e5406e7 msado15!CRecordGroup::AllocateHRowRange+0x00000085
6e540650 msado15!CRecordset::PrepareForFetch+0x000000e2
6e5d44ae msado15!CRecordset::MoveAbsolute+0x000003e3
6e5680a5 msado15!CRecordset::_MoveFirst+0x0000007d
6e5d7957 msado15!CRecordset::MoveFirst+0x00000221
6e54fde6 msado15!CRecordset::Invoke+0x00001560
71dcdb38 jscript!IDispatchInvoke2+0x000000f0
71dcda8c jscript!IDispatchInvoke+0x0000006a
71dcd9ff jscript!InvokeDispatch+0x000000a9
71dcdb8a jscript!VAR::InvokeByName+0x00000093
71dcd8c8 jscript!VAR::InvokeDispName+0x0000007d
71dcd96f jscript!VAR::InvokeByDispID+0x000000ce
71dce3e7 jscript!CScriptRuntime::Run+0x00002b80
71dc5c9d jscript!ScrFncObj::CallWithFrameOnStack+0x000000ce
71dc5bfb jscript!ScrFncObj::Call+0x0000008d
71dc5e11 jscript!CSession::Execute+0x0000015f
71dbf3ee jscript!NameTbl::InvokeDef+0x000001b5
71dbea2e jscript!NameTbl::InvokeEx+0x0000012c
71db96de jscript!NameTbl::Invoke+0x00000070
685aaa7b mshtml!CWindow::ExecuteTimeoutScript+0x00000087
685aab66 mshtml!CWindow::FireTimeOut+0x000000b6
685d6af7 mshtml!CStackPtrAry<unsigned long,12>::GetStackSize+0x000000b6
685d1e57 mshtml!GlobalWndProc+0x00000183
770e86ef USER32!InternalCallWinProc+0x00000023
770e8876 USER32!UserCallWinProcCheckWow+0x0000014b
770e89b5 USER32!DispatchMessageWorker+0x0000035e
770e8e9c USER32!DispatchMessageW+0x0000000f

根据上面异常的信息,可以知道程序是在向地址为0x88c7298,大小0xd64的堆块写入数据时造成堆溢出了。再根据!heap命令中返回的栈回溯信息可以知道,被溢出的堆块是在CRecordset::MoveFirst函数中调用MpHeapAlloc函数分配的,调用该分配函数的上层函数是CRecordGroup::AllocateHRowRange,对此函数下断,跟进后:

Breakpoint 0 hit
eax=00000001 ebx=40000358 ecx=76fc316f edx=096f2d34 esi=09759d70 edi=40000358eip=69da06be esp=0446eeec ebp=0446eef8 iopl=0         nv up ei pl zr na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000246
msado15!CRecordGroup::AllocateHRowRange+0x5e:
69da06be 85ff            test    edi,edi0:005> p
eax=00000001 ebx=40000358 ecx=76fc316f edx=096f2d34 esi=09759d70 edi=40000358
eip=69da06c0 esp=0446eeec ebp=0446eef8 iopl=0         nv up ei pl nz na po nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000202
msado15!CRecordGroup::AllocateHRowRange+0x60:
69da06c0 0f8e34380200    jle     msado15!CRecordGroup::AllocateHRowRange+0x62 (69dc3efa) [br=0]
0:005> p
eax=00000001 ebx=40000358 ecx=76fc316f edx=096f2d34 esi=09759d70 edi=40000358
eip=69da06c6 esp=0446eeec ebp=0446eef8 iopl=0         nv up ei pl nz na po nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000202
msado15!CRecordGroup::AllocateHRowRange+0x64:
69da06c6 8bc7            mov     eax,edi // eax = edi = 0x40000358,即CacheSize0:005> p
eax=40000358 ebx=40000358 ecx=76fc316f edx=096f2d34 esi=09759d70 edi=40000358
eip=69da06c8 esp=0446eeec ebp=0446eef8 iopl=0         nv up ei pl nz na po nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000202
msado15!CRecordGroup::AllocateHRowRange+0x66:
69da06c8 8b3dfc10d969    mov     edi,dword ptr [msado15!_imp__MpHeapAlloc (69d910fc)] ds:0023:69d910fc={MSDART!MpHeapAlloc (72de9730)}
0:005> p
eax=40000358 ebx=40000358 ecx=76fc316f edx=096f2d34 esi=09759d70 edi=72de9730
eip=69da06ce esp=0446eeec ebp=0446eef8 iopl=0         nv up ei pl nz na po nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000202
msado15!CRecordGroup::AllocateHRowRange+0x6c:
69da06ce 89460c          mov     dword ptr [esi+0Ch],eax ds:0023:09759d7c=00000000
0:005> p
eax=40000358 ebx=40000358 ecx=76fc316f edx=096f2d34 esi=09759d70 edi=72de9730
eip=69da06d1 esp=0446eeec ebp=0446eef8 iopl=0         nv up ei pl nz na po nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000202
msado15!CRecordGroup::AllocateHRowRange+0x6f:
69da06d1 8b0d10f0e569    mov     ecx,dword ptr [msado15!g_hHeapHandle (69e5f010)] ds:0023:69e5f010=096f0000
0:005> p
eax=40000358 ebx=40000358 ecx=096f0000 edx=096f2d34 esi=09759d70 edi=72de9730
eip=69da06d7 esp=0446eeec ebp=0446eef8 iopl=0         nv up ei pl nz na po nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000202
msado15!CRecordGroup::AllocateHRowRange+0x75:
69da06d7 8d048504000000  lea     eax,[eax*4+4] // 分配的堆块大小= 0x40000358*4+4 = 0xd64,这里eax的最大值是0xFFFFFFFF,经eax*4+4后变成0x100000D64 > 0xFFFFFFFF造成整数溢出,结果溢出后等于0xD64。如果我们把CacheSize设置成0x3FFFFFFF,那么后面分配的堆块就是0了。0:005> p
eax=00000d64 ebx=40000358 ecx=096f0000 edx=096f2d34 esi=09759d70 edi=72de9730
eip=69da06de esp=0446eeec ebp=0446eef8 iopl=0         nv up ei pl nz na po nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000202
msado15!CRecordGroup::AllocateHRowRange+0x7c:
69da06de 50              push    eax // 堆块大小=0xd640:005> p
eax=00000d64 ebx=40000358 ecx=096f0000 edx=096f2d34 esi=09759d70 edi=72de9730
eip=69da06df esp=0446eee8 ebp=0446eef8 iopl=0         nv up ei pl nz na po nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000202
msado15!CRecordGroup::AllocateHRowRange+0x7d:
69da06df 680000a000      push    0A00000h
0:005> p
eax=00000d64 ebx=40000358 ecx=096f0000 edx=096f2d34 esi=09759d70 edi=72de9730
eip=69da06e4 esp=0446eee4 ebp=0446eef8 iopl=0         nv up ei pl nz na po nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000202
msado15!CRecordGroup::AllocateHRowRange+0x82:
69da06e4 51              push    ecx
0:005> p
eax=00000d64 ebx=40000358 ecx=096f0000 edx=096f2d34 esi=09759d70 edi=72de9730
eip=69da06e5 esp=0446eee0 ebp=0446eef8 iopl=0         nv up ei pl nz na po nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000202
msado15!CRecordGroup::AllocateHRowRange+0x83:
69da06e5 ffd7            call    edi {MSDART!MpHeapAlloc (72de9730)}

该漏洞主要是由于对CacheSize整数值未作有效判断,导致经CacheSize*4+4造成整数溢出,当以CacheSize*4+4结果作为分配堆块的大小时,由于分配过小堆块就会造成堆溢出。