最近調(diào)了instruder發(fā)的0day漏洞:http://www.exploit-db.com/exploits/18140/
把調(diào)試分析的情況寫在這里。
dump文件的分析結(jié)果如下:
EXCEPTION_CODE: (NTSTATUS) 0xc0000005 - "0x%08lx"
FAULTING_IP:
win32k!ReadLayoutFile+88
bf89ed23 0fb75006 movzx edx,word ptr [eax+6]
TRAP_FRAME: b28068a0 -- (.trap 0xffffffffb28068a0)
ErrCode = 00000000
eax=003e0000 ebx=00000000 ecx=003d0000 edx=804ff619 esi=00000000 edi=00000000
eip=bf89ed23 esp=b2806914 ebp=b2806944 iopl=0 nv up ei pl nz na pe nc
cs=0008 ss=0010 ds=0023 es=0023 fs=0030 gs=0000 efl=00010206
win32k!ReadLayoutFile+0x88:
bf89ed23 0fb75006 movzx edx,word ptr [eax+6] ds:0023:003e0006=????
Resetting default scope
CUSTOMER_CRASH_COUNT: 1
DEFAULT_BUCKET_ID: DRIVER_FAULT
BUGCHECK_STR: 0x8E
PROCESS_NAME: 0Day.exe
LAST_CONTROL_TRANSFER: from bf89ec61 to bf89ed23
STACK_TEXT:
b2806944 bf89ec61 e12a4298 000007cc 00000160 win32k!ReadLayoutFile+0x88
b2806964 bf885192 000007cc 00000160 00000000 win32k!LoadKeyboardLayoutFile+0x6a
b28069f0 bf884c80 81ccf038 000007cc 08040804 win32k!xxxLoadKeyboardLayoutEx+0x1be
b2806d40 8053e638 000007cc 00000160 00409c40 win32k!NtUserLoadKeyboardLayoutEx+0x158
b2806d40 7c92e4f4 000007cc 00000160 00409c40 nt!KiFastCallEntry+0xf8
WARNING: Frame IP not in any known module. Following frames may be wrong.
0012ffc0 00000000 00000000 00000000 00000000 0x7c92e4f4
分析后猜測,winXP沒有對傳入的文件句柄做任何檢測,導(dǎo)致按照PE文件格式逐步解析畸形的鍵盤布局文件時出錯。
漏洞發(fā)生在win32k!ReadLayoutFile函數(shù)中。下面主要是分析該函數(shù)流程:
.text:BF89EC9E ; int __stdcall ReadLayoutFile(int, HANDLE FileHandle, size_t, int)
.text:BF89EC9E _ReadLayoutFile@16 proc near ; CODE XREF: LoadKeyboardLayoutFile(x,x,x,x,x,x,x)+4Dp
.text:BF89EC9E
.text:BF89EC9E ObjectAttributes= OBJECT_ATTRIBUTES ptr -28h
.text:BF89EC9E ViewSize = dword ptr -10h
.text:BF89EC9E Handle = dword ptr -0Ch
.text:BF89EC9E var_8 = dword ptr -8
.text:BF89EC9E BaseAddress = dword ptr -4
.text:BF89EC9E arg_0 = dword ptr 8
.text:BF89EC9E FileHandle = dword ptr 0Ch
.text:BF89EC9E arg_8 = dword ptr 10h
.text:BF89EC9E arg_C = dword ptr 14h
.text:BF89EC9E
.text:BF89EC9E ; FUNCTION CHUNK AT .text:BF89E265 SIZE 00000071 BYTES
......
.text:BF89ECE1 mov [ebp+ObjectAttributes.SecurityDescriptor], esi
.text:BF89ECE4 mov [ebp+ObjectAttributes.SecurityQualityOfService], esi
.text:BF89ECE7 mov [ebp+BaseAddress], esi
.text:BF89ECEA call ds:__imp__ZwCreateSection@28 ; ZwCreateSection(x,x,x,x,x,x,x)
.text:BF89ECF0 test eax, eax
.text:BF89ECF2 jl loc_BF89E265
......
.text:BF89ED07 push eax ; BaseAddress
.text:BF89ED08 push 0FFFFFFFFh ; ProcessHandle
.text:BF89ED0A push [ebp+Handle] ; SectionHandle
.text:BF89ED0D call ds:__imp__ZwMapViewOfSection@40 ; ZwMapViewOfSection(x,x,x,x,x,x,x,x,x,x)
.text:BF89ED13 test eax, eax ; 執(zhí)行對鍵盤文件的內(nèi)存映射
.text:BF89ED15 jl loc_BF89EEB3
.text:BF89ED1B mov ecx, [ebp+BaseAddress] ; ecx保存執(zhí)行文件映射后的內(nèi)存基址
.text:BF89ED1E mov eax, [ecx+3Ch] ; 0x3c是IMAGE_DOS_HEADER_STRUCT的e_lfanew成員,該成員保存指向PE文件的偏移。
.text:BF89ED21 add eax, ecx ; 加上文件映射內(nèi)存基址,eax指向IMAGE_FILE_HEADER結(jié)構(gòu)
.text:BF89ED23 movzx edx, word ptr [eax+6] ; IMAGE_FILE_HEADER結(jié)構(gòu)0x6偏移保存NumberOfSections成員
.text:BF89ED23 ; edx保存NumberOfSections成員的值
.text:BF89ED27 cmp edx, esi ; 比較是否NumberOfSections成員等于0
.text:BF89ED29 movzx ecx, word ptr [eax+14h] ; IMAGE_FILE_HEADER結(jié)構(gòu)0x14偏移保存SizeOfOptionalHeader成員,
.text:BF89ED29 ; 用于表示IMAGE_OPTIONAL_HEADER32結(jié)構(gòu)大小
.text:BF89ED2D lea eax, [ecx+eax+18h] ; ecx+eax+18h指向IMAGE_NT_HEADER結(jié)構(gòu)的OptionalHeader成員,
.text:BF89ED2D ; 也就是指向IMAGE_OPTIONAL_HEADER32結(jié)構(gòu), eax得到相應(yīng)的地址指針
.text:BF89ED31 push edi
.text:BF89ED32 mov [ebp+var_8], edx
.text:BF89ED35 mov [ebp+FileHandle], eax ; filehandle從此保存OptionalHeader的地址
.text:BF89ED38 jbe short loc_BF89ED50 ; 執(zhí)行無符號比較
.text:BF89ED3A
.text:BF89ED3A loc_BF89ED3A: ; CODE XREF: ReadLayoutFile(x,x,x,x)-A23j
.text:BF89ED3A push 6
.text:BF89ED3C mov edi, offset a_data ; ".data" ;這里將會跳轉(zhuǎn)做比較,對程序流程影響不大
.text:BF89ED41 mov esi, eax
.text:BF89ED43 pop ecx
.text:BF89ED44 xor edx, edx
.text:BF89ED46 repe cmpsb
.text:BF89ED48 jnz loc_BF89E26C
.text:BF89ED4E
.text:BF89ED4E loc_BF89ED4E: ; CODE XREF: ReadLayoutFile(x,x,x,x)-A29j
.text:BF89ED4E xor esi, esi
.text:BF89ED50
.text:BF89ED50 loc_BF89ED50: ; CODE XREF: ReadLayoutFile(x,x,x,x)+9Aj
.text:BF89ED50 cmp [ebp+var_8], esi ; [ebp+var_8]保存NumberOfSections成員的值
.text:BF89ED53 jz loc_BF89EEB2 ; 如果NumberOfSections的值等于0則程序結(jié)束
.text:BF89ED59 mov edi, [ebp+arg_8] ; arg8應(yīng)該是文件大小 ????
.text:BF89ED5C sub edi, [eax+0Ch] ; eax指向IMAGE_OPTIONAL_HEADER32結(jié)構(gòu),eax+0xc指向SizeofUninitializedData
.text:BF89ED5C ; 所有未初始化數(shù)據(jù)區(qū)塊總大小
.text:BF89ED5F mov eax, [eax+8] ; eax指向IMAGE_OPTIONAL_HEADER32結(jié)構(gòu),eax+0x8指向SizeofinitializedData
.text:BF89ED5F ; 所有初始化數(shù)據(jù)區(qū)塊總大小
.text:BF89ED62 push esi ; int
.text:BF89ED63 push 746B7355h ; Tag
.text:BF89ED68 push eax ; NumberOfBytes
.text:BF89ED69 mov [ebp+arg_8], eax
.text:BF89ED6C call _HeavyAllocPool@12 ; HeavyAllocPool(x,x,x)
.text:BF89ED71 cmp eax, esi
.text:BF89ED73 mov [ebp+var_8], eax ; 保存分配的地址 <------------問題就在這里
.text:BF89ED76 jz loc_BF89EEB2
.text:BF89ED7C mov ebx, [ebp+arg_0]
.text:BF89ED7F mov ecx, [ebp+FileHandle]
.text:BF89ED82 push [ebp+arg_8] ; size_t 可控,從文件的0x140處的值
.text:BF89ED85 mov [ebx+0Ch], eax
.text:BF89ED88 mov ecx, [ecx+14h] ; ecx可控,從文件0x156處讀出
.text:BF89ED8B add ecx, [ebp+BaseAddress]
.text:BF89ED8E push ecx ; void * ecx可控,從文件中讀出
.text:BF89ED8F push eax ; void *
.text:BF89ED90 call _memmove
從上面的程序流程可以看出,ReadLayoutFile函數(shù)調(diào)用ZwCreateSection和ZwMapViewOfSection將傳入鍵盤布局文件映射到內(nèi)存中,然后執(zhí)行PE
文件格式解析。ecx+3Ch將得到e_lfanew成員,eaxeax指向IMAGE_FILE_HEADER結(jié)構(gòu)地址。
.text:BF89ED1E mov eax, [ecx+3Ch] ; 0x3c是IMAGE_DOS_HEADER_STRUCT的e_lfanew成員,該成員保存指向PE文件的偏移。
.text:BF89ED21 add eax, ecx ; 加上文件映射內(nèi)存基址,eax指向IMAGE_FILE_HEADER結(jié)構(gòu)
從POC代碼可以看到正是對e_lfanew成員的fuzz導(dǎo)致了eax指向了一個無效地址,產(chǎn)生內(nèi)存訪問錯的指令
.text:BF89ED23 movzx edx, word ptr [eax+6] ; IMAGE_FILE_HEADER結(jié)構(gòu)0x6偏移保存NumberOfSections成員
通過適當(dāng)修改POC文件,可以使程序流程執(zhí)行到BF89ED62,將調(diào)用_HeavyAllocPool分配一塊空間,然后執(zhí)行_memmove。
從代碼流程分析看,拷貝數(shù)據(jù)的源、長度分別來自鍵盤布局文件的0x140處的值,0x156處的值。數(shù)據(jù)源、數(shù)據(jù)長度可控,但是目的不可控 :(
從后續(xù)程序流程看,也未找到可以利用之處:(。