我也贴个分析。大家都分析下载器。我来个盗号木马。这个是在早先看一个下载器样本时 从它的下载列表里搞到的。2.exe (下载列表里就叫这个)
反汇编代码实在是太多了,所以那些大家都十分熟悉的函数调用的代码就不贴了,贴些我觉得比较好玩的部分。
写的很糙,水平很烂,难免出错,各位见笑了~~~~
分析环境是VMware,分析工具是OD + IDApro + Winhex
2.exe 概述
梦幻西游(my.exe) 征途(conquer.exe) 浩方对战平台(gameclient.exe) 盗号木马
C++语言编写
主要行为
读取fonts下文件比较字符串判断是否已经感染。释放动态链接库文件。写启动项,安装全局钩子注入游戏进程,通过封包截取(hook联网函数),内存读取(读取mhmain.dll地址空间内数据,mhmain.dll是梦幻西游游戏进程关键模块。其他两个类似),读取窗口标题方式获取游戏玩家密码密保等信息,然后使用windows 套接字函数将窃取的信息发送到骇客指定的服务器上(http://121.10.112.142)。木马还会盗取征途,浩方对战平台的密码。木马会关闭一些账号保护工具并不停对注册表中自身启动项进行回写,最后调用命令删除自身。
※※该木马应该经过免杀处理,在几处关键位置(如10003C28处等)存在多条nop指令。
※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※
2.exe
Size: 24683 bytes
MD5: ED91C86A102E8F4DA2191D210EDFDAEE
加壳:UPX 0.89.6 - 1.02 / 1.05 - 1.24 -> Markus & Laszlo [Overlay]
编写工具及语言:VC++ 6.0 C++语言编写
※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※
(一).CreateEvent创建无名事件对象,然后主线程CreateThread创建一线程,主线程WaitForSingleObject等待事件对象受信,如果1800000ms后,事件对象仍未受信,则调用TerminateThread结束线程(ExitCode = -1)。然后执行(二)的操作。
新创建的线程行为:
1.GetWindowsDirectoryA获取系统文件夹路径。sprintf格式化字符串%systemroot%\FOnts\D9PjvuvCAeWudqwq.ttf (不是随机文件名)
2.读取自身到内存缓冲区。
GetModuleFileNameA获取病毒体路径名。CreateFileA打开自身,GetFileSize获取自身大小。接下来调用VirtualAlloc在自己进程地址空间中分配 与自身文件大小相同的内存,然后ReadFile读取自身到这片内存缓冲区。CloseHandle关闭文件句柄。最后返回指向缓冲区的指针,返回0表示读取失败。
3.将病毒路径名全部转换为小写格式。
这里是一个调用tolower toupper的大小写转换的通用函数,传入的参数之一是选择转大写或转小写的标志量。传零表示转大写,非零转小写。
push 1 ; int
push eax ; Str
call sub_401BB7
这里是将传入的str转小写(下面提到的字符串转小写用的函数都和这个相同或者类似)。
4.读取内存缓冲区中病毒体尾部数据(距文件尾部56字节至距文件尾部8字节这段数据),strcat连接成字符串"2761E00B569F0A28CF882C76FD4912242D0000000A0000002064ED5415DC4D25D7902A73FB5014233E67E60E4F99092DC2872B79FA514F7A7525BF5D0E87517696917A32BA2064ED5415DC4D25D790"
然后VirtualFree释放分配的内存
5.CreateFileA打开%systemroot\FOnts\D9PjvuvCAeWudqwq.ttf(我的电脑上是C:\WINDOWS\FOnts\D9PjvuvCAeWudqwq.ttf)。GetFileSize获取D9PjvuvCAeWudqwq.ttf的大小。接下来调用VirtualAlloc在自己进程地址空间中分配与D9PjvuvCAeWudqwq.ttf大小相同的内存,如果分配失败,子函数直接返回 0。否则,ReadFile将其读取到这片内存缓冲区。CloseHandle关闭文件句柄。最后返回指向缓冲区的指针。
以返回值判断D9PjvuvCAeWudqwq.ttf是否存在。
如果存在,则读取D9PjvuvCAeWudqwq.ttf尾部数据(距文件尾部56字节至距文件尾部8字节这段数据),与从病毒体尾部读取的数据进行比较,如果一致,则认为已经感染,跳到步骤7执行。
6.如果不存在D9PjvuvCAeWudqwq.ttf(返回0),则再重复一遍5的过程。如果仍不存在,则DeleteFileA删除%systemroot%\FOnts\D9PjvuvCAeWudqwq.ttf。CreateFileA打开%systemroot%\FOnts\D9PjvuvCAeWudqwq.ttf,_llseek定位文件指针到尾部(FILE_END),WriteFile向其尾部(因为是新创建的文件,所以也就是文件头写入"2761E00B569F0A28CF882C76FD4912242D0000000A0000002064ED5415DC4D25D7902A73FB5014233E67E60E4F99092DC2872B79FA514F7A7525BF5D0E87517696917A32BA2064ED5415DC4D25D790" (不含引号)
※※※通过资源管理器查看字体安装目录 fonts 下只会显示已经安装了的字体,不会显示其他文件,所以这为木马提供了很好的掩护,但是在命令行下木马就无所遁形了~~~
7.GetSystemDirectory获取%systemroot%,sprintf格式字符串"C:\WINDOWS\system32\erdznUfbK0ZF.dll"
8.同2的方法将自己读取到内存缓冲区。DeleteFileA 删除C:\WINDOWS\system32\erdznUfbK0ZF.dll 。以37为密钥,异或解密内存缓冲区中自身数据(从距文件头偏移0x6010处开始的共17920个字节,异或解密后,这17920个字节的数据是一个dll文件)
CreateFileA打开%systemroot%\system32\erdznUfbK0ZF.dll,_llseek定位文件指针到尾部,WriteFile向其尾部(其实也是文件头)将解密后的17920个字节的数据写入。同样的方法再向其尾部写入"2761E00B569F0A28CF882C76FD4912242D0000000A0000002064ED5415DC4D25D7902A73FB5014233E67E60E4F99092DC2872B79FA514F7A7525BF5D0E87517696917A32BA2064ED5415DC4D25D790" (不含引号),作为病毒释放文件标记。
9.LoadLibraryA加载%systemroot%\system32\erdznUfbK0ZF.dll,GetProcAddress获取其导出函数JUFndB4pARSJ函数指针,调用JUFndB4pARSJ。
10.RegOpenKeyExA打开HKEY_LOCAL_MACHINE\Software\microsoft\windows\currentversion\Explorer\shellexecutehooks,RegQueryValueExA判断名为{669029EE-81FB-496F-9AC4-FE838B16F231}的键值是否存在。不存在则创建。
11.CreateToolhelp32Snapshot创建进程快照。Process32First,Process32Next遍历进程链,将遍历到的进程名转换为小写形式(同3类似的大小写转换通用函数),调用CryptoAPI为已转换为小写的进程名计算相应的MD5值。
这里比较感兴趣,贴下计算MD5的反汇编代码片段
以下是病毒为进程名计算MD5的反汇编代码片段。
.text:00401B0E ; =============== S U B R O U T I N E =======================================
.text:00401B0E
.text:00401B0E ; Attributes: bp-based frame
.text:00401B0E
.text:00401B0E ; int __cdecl sub_401B0E(BYTE *pbData, DWORD dwDataLen, int)
.text:00401B0E sub_401B0E proc near ; CODE XREF: sub_4017DE+AC p
.text:00401B0E
.text:00401B0E pdwDataLen = dword ptr -0Ch
.text:00401B0E hProv = dword ptr -8
.text:00401B0E hHash = dword ptr -4
.text:00401B0E pbData = dword ptr 8
.text:00401B0E dwDataLen = dword ptr 0Ch
.text:00401B0E arg_8 = dword ptr 10h
.text:00401B0E
.text:00401B0E push ebp
.text:00401B0F mov ebp, esp
.text:00401B11 sub esp, 0Ch
.text:00401B14 push esi
.text:00401B15 push edi
.text:00401B16 xor esi, esi
.text:00401B18 push 0F0000000h ; dwFlags
.text:00401B1D push 1 ; dwProvType
.text:00401B1F push esi ; szProvider
.text:00401B20 lea eax, [ebp+hProv]
.text:00401B23 push esi ; szContainer
.text:00401B24 push eax ; phProv
.text:00401B25 xor edi, edi
.text:00401B27 mov [ebp+hProv], esi
.text:00401B2A mov [ebp+hHash], esi
.text:00401B2D mov [ebp+pdwDataLen], esi
.text:00401B30 call ds:CryptAcquireContextA
.text:00401B36 test eax, eax
.text:00401B38 jz short loc_401B79
.text:00401B3A lea eax, [ebp+hHash]
.text:00401B3D push eax ; phHash
.text:00401B3E push esi ; dwFlags
.text:00401B3F push esi ; hKey
.text:00401B40 push 8003h ; Algid
.text:00401B45 push [ebp+hProv] ; hProv
.text:00401B48 call ds:CryptCreateHash
.text:00401B4E test eax, eax
.text:00401B50 jz short loc_401BA7
.text:00401B52 push esi ; dwFlags
.text:00401B53 push [ebp+dwDataLen] ; dwDataLen
.text:00401B56 push [ebp+pbData] ; pbData
.text:00401B59 push [ebp+hHash] ; hHash
.text:00401B5C call ds:CryptHashData
.text:00401B62 test eax, eax
.text:00401B64 jnz short loc_401B7D
.text:00401B66 push esi ; dwFlags
.text:00401B67 push [ebp+hProv] ; hProv
.text:00401B6A call ds:CryptReleaseContext
.text:00401B70 push [ebp+hHash] ; hHash
.text:00401B73 call ds:CryptDestroyHash
.text:00401B79
.text:00401B79 loc_401B79: ; CODE XREF: sub_401B0E+2A j
.text:00401B79 xor eax, eax
.text:00401B7B jmp short loc_401BB3
.text:00401B7D ; ---------------------------------------------------------------------------
.text:00401B7D
.text:00401B7D loc_401B7D: ; CODE XREF: sub_401B0E+56 j
.text:00401B7D lea eax, [ebp+pdwDataLen]
.text:00401B80 push esi ; dwFlags
.text:00401B81 push eax ; pdwDataLen
.text:00401B82 mov [ebp+pdwDataLen], 10h
.text:00401B89 push [ebp+arg_8] ; pbData
.text:00401B8C push 2 ; dwParam
.text:00401B8E push [ebp+hHash] ; hHash
.text:00401B91 call ds:CryptGetHashParam
.text:00401B97 test eax, eax
.text:00401B99 jz short loc_401B9E
.text:00401B9B push 1
.text:00401B9D pop edi
.text:00401B9E
.text:00401B9E loc_401B9E: ; CODE XREF: sub_401B0E+8B j
.text:00401B9E push [ebp+hHash] ; hHash
.text:00401BA1 call ds:CryptDestroyHash
.text:00401BA7
.text:00401BA7 loc_401BA7: ; CODE XREF: sub_401B0E+42 j
.text:00401BA7 push esi ; dwFlags
.text:00401BA8 push [ebp+hProv] ; hProv
.text:00401BAB call ds:CryptReleaseContext
.text:00401BB1 mov eax, edi
.text:00401BB3
.text:00401BB3 loc_401BB3: ; CODE XREF: sub_401B0E+6D j
.text:00401BB3 pop edi
.text:00401BB4 pop esi
.text:00401BB5 leave
.text:00401BB6 retn
.text:00401BB6 sub_401B0E endp
因为比较感兴趣这段代码,所以闲的没事给转成C代码了,以后可以留着自己用,呵呵
将以上反汇编代码转为C代码为:
//梦幻西游盗号木马2.exe计算进程名md5函数
//by jerrysun
//参数 1 pbData 为进程名字符串指针,
//参数 2 dwDataLen为是进程名的长度(strlen计算得到)
//参数 3 pbMd5为计算得到的进程名的MD5值
//返回值为 指示是否计算成功的标志量flag,返回FALSE指示计算失败,TRUE表示成功。
BOOL CalProcessNameMd5(char *pbData, DWORD dwDataLen, int pbMd5)
{
BOOL flag = FALSE;
HCRYPTPROV hProv = NULL;
HCRYPTHASH hHash = NULL;
DWORD pdwDataLen = 0;
//获取系统默认的CSP密钥容器句柄
if(!CryptAcquireContext(&hProv, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT))
return flag;
//创建hash对象,使用MD5 hash算法
if(CryptCreateHash(hProv, CALG_MD5, 0, 0, &hHash))
{
//计算pbData指向的长度为dwDataLen的一段数据(进程名)的MD5值
if(!CryptHashData(hHash, pbData, dwDataLen, 0))
{
CryptReleaseContext(hProv, 0);
CryptDestroyHash(hHash);
return flag;
}
pdwDataLen = 16;
//取出hash后的数据存在pbMd5指向的内存中
if(CryptGetHashParam(hHash, 2, (char *)pbMd5, &pdwDataLen, 0))
flag = TRUE;
CryptDestroyHash(hHash);
}
CryptReleaseContext(hProv, 0);
return flag;
}
12.OpenProcessToken,LookupPrivilegeValueA,AdjustTokenPrivileges提升病毒进程权限为SeDebugPrivilege权限,使其拥有对其他进程的访问权。
13.然后调用memcmp将刚计算得到的进程名的MD5值与292685D9ED93E1336EBE01B60314D8F8比较,如果一致,则OpenProcess获取该进程句柄,然后TerminateProcess将其结束。
※这里是要结束名字的MD5值为292685D9ED93E1336EBE01B60314D8F8的进程,经过测试,字符串my.exe的MD5值就是292685d9ed93e1336ebe01b60314d8f8,即病毒要结束my.exe(网络游戏梦幻西游的进程名)
14.GetSystemDirectory获取%systemroot%路径。连接字符串 得到%systemroot%\system32\VErCLSiD.exe,FindFirstFileA 查找%systemroot%\system32\VErCLSiD.exe,找到后DeleteFileA 删除VErCLSiD.exe
15.RegCreateKeyA,RegSetValueEx新建注册表项及其下键值,注册CLSID值。
[HKEY_CLASSES_ROOT\CLSID\{669029EE-81FB-496F-9AC4-FE838B16F231}\InprocServer32]
名称:@
类型:REG_SZ
数据:"C:\\WINDOWS\\system32\\erdznUfbK0ZF.dll"
名称:ThreadingModel
类型:REG_SZ
数据:Apartment
同样的方法接着创建:
[HKEY_LOCAL_MACHINE\Software\microsoft\windows\currentversion\Explorer\shellexecutehooks]
名称:{669029EE-81FB-496F-9AC4-FE838B16F231}
类型:REG_SZ
将指向病毒文件erdznUfbK0ZF.dll的CLSID号添加到HOOK项中,使explorer.exe进程自动加载该dll文件,同时实现自启动。
16.Loadlibrary,GetProcAddress加载%systemroot%\system32\erdznUfbK0ZF.dll的导出函数JUFndB4pARSJ
17.SetEvent设置事件对象受信,主线程WaitForSingleObject返回,开始继续执行主线程内代码。ExitThread结束线程(ExitCode = 0)
(二).主线程接下来,GetModuleFileNameA获取自身路径,GetShortPathNameA获取短路径名。strcat拼接字符串得到"/c del C:\MYDOCU~1\桌面\2.exe >> NUL"
GetEnvironmentVariableA获取%ComSpec%路径,(即cmd.exe路径)ShellExecuteA调用cmd.exe 执行命令删除自身
ShellExecuteA
|hWnd = NULL
|Operation = NULL
|FileName = "C:\WINDOWS\system32\cmd.exe"
|Parameters = "/c del C:\MYDOCU~1\桌面\2.exe >> NUL"
|DefDir = NULL
\IsShown = 0
调用exit退出
[ 本帖最后由 jerrysun 于 2009-5-28 18:54 编辑 ] |