本帖最后由 康小泡 于 2015-9-2 18:52 编辑
前言
样本信息
nvwsrds.dll-MD5: 22248627f964fe6cd6a137c9fbb12a58
png.bat-MD5: 97f24d32dba35fe19b11951c4bb09bfd
temp-MD5: 7c0fe5ca914753bb93351508836a266f
图1-MD5: d652e4f08ac6b7ba5f6aab1be42dbda2
样本分析
"图1"分析
"图1"是一个快捷方式,指向了cmd,调用cmd去执行png.bat
[Asm] 纯文本查看 复制代码 C:\WINDOWS\system32\cmd.exe /c png.bat
png.bat分析
Png.bat是一个批处理文件,用记事本打开的时候是乱码,这里有一个小的知识点,这个bat采用的是UTF-16LE编码形式,只要我们用winhex将最前面的FF FE去掉,用记事本打开就不是乱码了。大家可以下去试试。
[Asm] 纯文本查看 复制代码 mkdir "%programfiles%"
rundll32.exe nvwsrds.dll,avmode -fn hgfyryertsdsd
nvwsrds.dll分析
0x01采用大量花指令来做免杀
在分析png.bat的时候,我们就知道这个样本的重头戏就在avmode这个函数里面,所以我们重点从这个函数入手,在进入这个函数的时候,我们看到的是大量的花指令,列如下面一小段(目测是手工添加的,真想问一句,累吗?)
[Asm] 纯文本查看 复制代码 10003468 55 push ebp
10003469 90 nop
1000346A 90 nop
1000346B 8BEC mov ebp,esp
1000346D 85F6 test esi,esi
1000346F 90 nop
10003470 8BE5 mov esp,ebp
10003472 90 nop
10003473 90 nop
10003474 5D pop ebp
0x02判断自身是否已驻扎在系统
先通过调用GetModuleFileName获取到当前已加载模块的完整路径,然后通过调用strstr函数来判断当前已加载模块中是否含有nvwing.dll字符串
[Asm] 纯文本查看 复制代码 0012F374 100062DC |s1 = "c:\documents and settings\administrator\桌面\价格图\nvwsrds.dll"
0012F378 0012F930 \s2 = "\nvwimg.dll"
0x03对敏感信息的隐藏
该样本在对敏感字符串和敏感函数的处理上都是通过使用拼接的方式来获完成的,(对于敏感函数的处理是先通过拼接的方式获取到完整的函数名,在通过LoadLibrary和GetProceAddress函数合用获取到函数的地址,然后进行调用)
[Asm] 纯文本查看 复制代码 .text:10002E90 mov byte ptr [ebp-9Bh], 'A'
.text:10002E97 mov [ebp-9Ah], al
.text:10002E9D mov [ebp-99h], al
.text:10002EA3 mov byte ptr [ebp-98h], 'D'
.text:10002EAA mov byte ptr [ebp-97h], 'A'
.text:10002EB1 mov byte ptr [ebp-96h], 'T'
.text:10002EB8 mov byte ptr [ebp-95h], 'A'
.text:10002EBF mov [ebp-94h], cl
.text:10002EC5 mov byte ptr [ebp-93h], '\'
0x04复制自身
调用ExpandEnvironmentStringA函数,传入参数%APPDAT%avmode来得到即将要创建的文件的路径,当函数调用成功后,%APPDAT%\avmode会扩展成 "C:\Documents and Settings\Administrator\Application Data\avmode"
然后调用CreateDirectoryA函数来创建路径。再调用strcat函数将文件名添加到后面(注意到没有,这里的文件名就是最开始的时候查找字符串,所以这里我们可以看出分析出前面是在判断样本是否已经驻扎在了我们的电脑里面)
[Asm] 纯文本查看 复制代码 0012F370 10002FBB /CALL 到 lstrcatA 来自 nvwsrds.10002FB9
0012F374 0012F488 |ConcatString = "C:\Documents and Settings\Administrator\Application Data\avmode"
0012F378 0012F930 \StringToAdd = "\nvwimg.dll"
调用CopyFile函数将文件复制到新的目录下
[Asm] 纯文本查看 复制代码 0012F36C 10002FD1 /CALL 到 CopyFileA 来自 nvwsrds.10002FCF
0012F370 100062DC |ExistingFileName = "c:\documents and settings\administrator\桌面\价格图\nvwsrds.dll"
0012F374 0012F488 |NewFileName = "C:\Documents and Settings\Administrator\Application Data\avmode\nvwimg.dll"
0012F378 00000000 \FailIfExists = FALSE
接下来样本使用同样的手段将temp文件复制到了 "C:\Documents and Settings\Administrator\Application Data\avmode"路径下。
0x05全屏显示图片
这里样本一个以字符串拼接获取到字符串"shimgvw.dll,ImageView_Fullscreen c:\documents and settings\administrator\桌面\价格图\bbs.bmp",也就是下面调用ShellExecuteA函数时需要用到的一个参数。这里的功能其实就是使图片bbs.bmp全屏显示。所以这里不知道是样本的不完整,还是是样本保留了以前的版本的一些功能。
[Asm] 纯文本查看 复制代码 0012F360 10003326 /CALL 到 ShellExecuteA 来自 nvwsrds.10003324
0012F364 00000000 |hWnd = NULL
0012F368 0012F958 |Operation = "Open"
0012F36C 0012F904 |FileName = "rundll32.exe"
0012F370 0012F690 |Parameters = "shimgvw.dll,ImageView_Fullscreen c:\documents and settings\administrator\桌面\价格图\bbs.bmp"
0012F374 100060D8 |DefDir = "c:\"
0012F378 00000005 \IsShown = 5
0x06 执行复制到系统中的"自己"
前面这些都是在为隐藏自己做的铺垫
[Asm] 纯文本查看 复制代码 0012F360 100033CB /CALL 到 ShellExecuteA 来自 nvwsrds.100033C9
0012F364 00000000 |hWnd = NULL
0012F368 0012F958 |Operation = "Open"
0012F36C 0012F904 |FileName = "rundll32.exe"
0012F370 0012F388 |Parameters = ""C:\Documents and Settings\Administrator\Application Data\avmode\nvwimg.dll" avmode"
0012F374 100060D8 |DefDir = "c:\"
0012F378 00000005 \IsShown = 5
0x07检测虚拟机
首先还是判断自己是不是已经驻扎在了系统中,如果有就开始做检测啦。这里使用的是特权指令来检测是否是在虚拟机中,原理是因为in指令属于特权指令,在处于保护模式下的合计上执行次指令时,除非权限允许,否则将会"EXCEPTION_PRIV_INSTRUCTION"异常(程序企图执行一条当前CPU模式不允许的指令时引发该异常),但是在虚拟机中的时候就不会触发该异常
[Asm] 纯文本查看 复制代码 .text:100027D8 mov eax, 'VMXh'
.text:100027DD mov ebx, 0
.text:100027E2 mov ecx, 0Ah ;指定功能号,0A是获取版VMware版本
.text:100027E7 mov edx, 'VX' ;端口号
.text:100027EC in eax, dx ;从端口dx读取VWware版本到eax
.text:100027ED cmp ebx, 'VMXh' ;判断ebx中是否包含VMware版本"VMXh",如果有就在虚拟机中
.text:100027F3 setz byte ptr [ebp-1Ch] ;设置返回值
因为已经知道是是需要触发异常才能去执行正确的代码段,这里我们直接去找到异常处理的地方,当我们执行完in eax,dx的时候,我们就可以去查找异常处理链来找到异常处理的地址
0012F330 0012F998 指向下一个 SEH 记录的指针
0012F334 1000244E SE处理程序
SE处就是我们要找的地方。我们在这里新建eip,然后F7,然后alt+F9就到达了用户领空了
1000244E - FF25 88430010 jmp dword ptr ds:[<&MSVCRT._except_handl>; msvcrt._except_handler3
这里说一点是当他检测到了虚拟机的时候是进入了休眠里,使用了sleep和jmp使程序一直在sleep,而不是直接退出程序
0x08解密temp文件
[Asm] 纯文本查看 复制代码 0012EC0C 10002A94 /CALL 到 CreateFileA 来自 nvwimg.10002A92
0012EC10 100062DC |FileName = "c:\documents and settings\administrator\application data\avmode\temp"
0012EC14 80000000 |Access = GENERIC_READ
0012EC18 00000000 |ShareMode = 0
0012EC1C 00000000 |pSecurity = NULL
0012EC20 00000003 |Mode = OPEN_EXISTING
0012EC24 00000080 |Attributes = NORMAL
0012EC28 00000000 \hTemplateFile = NULL
获取文件大小
[Asm] 纯文本查看 复制代码 0012EC20 10002AB6 /CALL 到 GetFileSize 来自 nvwimg.10002AB3
0012EC24 0000003C |hFile = 0000003C
0012EC28 00000000 \pFileSizeHigh = NULL
读取文件
[Asm] 纯文本查看 复制代码 0012EC14 10002B2A /CALL 到 ReadFile 来自 nvwimg.10002B28
0012EC18 0000003C |hFile = 0000003C
0012EC1C 00A20048 |Buffer = 00A20048
0012EC20 0002102D |BytesToRead = 2102D (135213.)
0012EC24 0012EC4C |pBytesRead = 0012EC4C
0012EC28 00000000 \pOverlapped = NULL
读入的temp文件
解密后的数据
0x09 创建配置文件
通过字符串拼接的方式拼接处路径,然后创建配置文件
[Asm] 纯文本查看 复制代码 0012DC90 00CBBDB7 /CALL 到 lstrcatA 来自 00CBBDB5
0012DC94 0012EAD0 |ConcatString = "C:\Documents and Settings\Administrator\Application Data\avmode\avmode"
0012DC98 00CCD6AC \StringToAdd = ".inf"
配置文件内容如下,主要起开机自启动作用
[Asm] 纯文本查看 复制代码 [Version]
Signature="$CHICAGO$"
Provider=t@t.com, 2002
[DefaultInstall]
; DelReg=run_DelReg
AddReg=run_AddReg
[run_DelReg]
[run_AddReg]
hkcu,"Software\Microsoft\Windows\CurrentVersion\Run","Update",,"rundll32.exe ""C:\Documents and Settings\Administrator\Application Data\avmode\Bitavmode.dll"",avmode"
[Strings]
0xA0创建互斥量
创建一个名文"t.qq.com/as730498358"的互斥量
[Asm] 纯文本查看 复制代码 0012DC8C 00CBC370 /CALL 到 CreateMutexA 来自 00CBC36A
0012DC90 00000000 |pSecurity = NULL
0012DC94 00000000 |InitialOwner = FALSE
0012DC98 00CCD220 \MutexName = "t.qq.com/as730498358"
0xA1创建线程
调用_beginthreadex创建线程,我们来到创建线程的地方的基地址,这里就跑到解密后的temp文件的领空去执行了
[Asm] 纯文本查看 复制代码 00CBCF94 52 push edx
00CBCF95 68 D0CECB00 push 0xCBCED0
00CBCF9A 50 push eax
00CBCF9B 51 push ecx
00CBCF9C FF15 9822CC00 call dword ptr ds:[0xCC2298] ; msvcrt._beginthreadex
0xA2建立TCP协议
调用socket的时候,我们从参数SOCK_STREAM可以看出采用的TCP协议来进行通信,接下来就是基本的套接字的建立过程,就不写了。
[Asm] 纯文本查看 复制代码 00EABBE4 00000002 |Family = AF_INET
00EABBE8 00000001 |Type = SOCK_STREAM
00EABBEC 00000006 \Protocol = IPPROTO_TCP
从下面看出这个是个客户端,在创建连接
[Asm] 纯文本查看 复制代码 00CB2375 6A 10 push 0x10
00CB2377 52 push edx
00CB2378 50 push eax
00CB2379 FF15 8824CC00 call dword ptr ds:[0xCC2488] ; ws2_32.connect
0xA3注册表操作
[Asm] 纯文本查看 复制代码 if ( !RegCreateKeyExA(hKey, lpSubKey, 0, 0, 0, 0xF003Fu, 0, &phkResult, &dwDisposition) )
goto LABEL_3;
break;
case 1:
LABEL_3:
if ( !RegOpenKeyExA(hKey, lpSubKey, 0, 0x2001Fu, &phkResult) && dwType > 0 )
{
if ( dwType <= 2 )
{
if ( !RegSetValueExA(phkResult, lpValueName, 0, dwType, lpData, strlen((const char *)lpData) + 1) )
goto LABEL_16;
}
else if ( dwType == 4 && !RegSetValueExA(phkResult, lpValueName, 0, 4u, &Data, 4u) )
{
goto LABEL_16;
}
}
break;
case 2:
if ( !RegOpenKeyExA(hKey, lpSubKey, 0, 0x2001Fu, &phkResult) && !RegDeleteKeyA(phkResult, lpValueName) )
goto LABEL_16;
break;
case 3:
if ( !RegOpenKeyExA(hKey, lpSubKey, 0, 0x2001Fu, &phkResult) && !RegDeleteValueA(phkResult, lpValueName) )
0xA4查找360主动防御进程
先创建快照,在遍历进程,在进程中寻找是否有"ZhuDongFangYu.exe"进程
[Asm] 纯文本查看 复制代码 00CBB196 68 50D5CC00 push 0xCCD550 ; ASCII "ZhuDongFangYu.exe"
00CBB19B 897424 20 mov dword ptr ss:[esp+0x20],esi
[Asm] 纯文本查看 复制代码 v1 = CreateToolhelp32Snapshot(2u, 0);
memset(&pe.cntUsage, 0, 0x124u);
pe.dwSize = 296;
if ( Process32First(v1, &pe) )
{
if ( !strcmpi(pe.szExeFile, lpString2) )
return pe.th32ProcessID;
if ( Process32Next(v1, &pe) )
{
while ( lstrcmpiA(pe.szExeFile, lpString2) )
{
if ( !Process32Next(v1, &pe) )
return 0;
}
return pe.th32ProcessID;
}
}
return 0;
}
0x0A5访问网络
1.首先通过访问www.360.cn来测试网络是否通畅,然后获取到即将访问的地址(写死到程序中的,就不详细介绍了)
[Asm] 纯文本查看 复制代码 00CB1008 6A 01 push 0x1
00CB100A 68 20B0CC00 push 0xCCB020 ; ASCII "www.360.cn"
00CB100F 8946 14 mov dword ptr ds:[esi+0x14],eax
00CB1012 8946 0C mov dword ptr ds:[esi+0xC],eax
00CB1015 8946 10 mov dword ptr ds:[esi+0x10],eax
00CB1018 8906 mov dword ptr ds:[esi],eax
00CB101A 8946 04 mov dword ptr ds:[esi+0x4],eax
00CB101D 8946 08 mov dword ptr ds:[esi+0x8],eax
00CB1020 FF15 0824CC00 call dword ptr ds:[0xCC2408] ; wininet.InternetOpenA
[Asm] 纯文本查看 复制代码 00EA9BEC 00EABE88 ASCII http://t.qq.com/as730498358
2.通过调用InternetReadFile来读取网页的源码
[Asm] 纯文本查看 复制代码 00CB1404 50 push eax
00CB1405 8D4C24 18 lea ecx,dword ptr ss:[esp+0x18]
00CB1409 68 FF1F0000 push 0x1FFF
00CB140E 51 push ecx
00CB140F 52 push edx
00CB1410 FF15 2C24CC00 call dword ptr ds:[0xCC242C] ; wininet.InternetReadFile
3.查看网页源代码的时候,可以看出来是通过IP#61标记来找到藏在主页中的ip地址
[Asm] 纯文本查看 复制代码 00CBAE8D 68 5CD4CC00 push 0xCCD45C ; ASCII "IP="
00CBAE92 50 push eax
00CBAE93 FF15 D024CC00 call dword ptr ds:[0xCC24D0] ; ntdll.strstr
分割字符串,以获取"纯ip地址" C
[Asm] 纯文本查看 复制代码 00CBAEAF 68 58D4CC00 push 0xCCD458 ; ASCII "&#"
00CBAEB4 57 push edi
00CBAEB5 FF15 A022CC00 call dword ptr ds:[0xCC22A0] ; msvcrt.strtok
0xA6 获取本机基本信息
1.获取主机名
[Asm] 纯文本查看 复制代码 00CBA76C 83E1 03 and ecx,0x3
00CBA76F F3:AA rep stos byte ptr es:[edi]
00CBA771 FF15 B024CC00 call dword ptr ds:[0xCC24B0] ; ws2_32.gethostname
2.获取主机版本信息
[Asm] 纯文本查看 复制代码 00CBA842 C68424 A0000000>mov byte ptr ss:[esp+0xA0],0x66
00CBA84A C68424 7E010000>mov byte ptr ss:[esp+0x17E],0x0
00CBA852 C78424 A4000000>mov dword ptr ss:[esp+0xA4],0x9C
00CBA85D FF15 D821CC00 call dword ptr ds:[0xCC21D8] ; kernel32.GetVersionExA
3.获取本地地址
[Asm] 纯文本查看 复制代码 00CBA93C 52 push edx
00CBA93D FF15 B424CC00 call dword ptr ds:[0xCC24B4] ; ws2_32.getsockname
4.获取当前主机信息
[Asm] 纯文本查看 复制代码 00CBA98A 51 push ecx
00CBA98B FF15 0C21CC00 call dword ptr ds:[0xCC210C] ; kernel32.GetSystemInfo
5.获取硬盘容量
[Asm] 纯文本查看 复制代码 00EAB6EC 00CBA9F0 /CALL 到 GetDriveTypeA 来自 00CBA9EE
00EAB6F0 00EAB704 \RootPathName = "B:\"
00EAB6F4 7C80932E kernel32.GetTickCount
00CBA9EE FFD5 call ebp ; kernel32.GetDriveTypeA
[Asm] 纯文本查看 复制代码 00CBAA07 51 push ecx
00CBAA08 52 push edx
00CBAA09 FF15 C021CC00 call dword ptr ds:[0xCC21C0] ; kernel32.GetDiskFreeSpaceExA
6.获取当前时间信息
[Asm] 纯文本查看 复制代码 00EAB6DC 00EAB8A4 ASCII "2015-09-02 16"
00EAB6E0 00CCD414 ASCII "%4d-%.2d-%.2d %.2d"
0xA7提升权限
[Asm] 纯文本查看 复制代码 v2 = 1;
v3 = GetCurrentProcess();
if ( OpenProcessToken(v3, 0x28u, &TokenHandle) )
{
NewState.PrivilegeCount = 1;
NewState.Privileges[0].Attributes = a2 != 0 ? 2 : 0;
LookupPrivilegeValueA(0, lpName, (PLUID)NewState.Privileges);
AdjustTokenPrivileges(TokenHandle, 0, &NewState, 0x10u, 0, 0);
if ( GetLastError() )
v2 = 0;
CloseHandle(TokenHandle);
result = v2 != 0;
}
总结
啊,这个样本死了,抓包的时候也没有抓到什么有用的信息,这个样本分析就到这吧,感谢前面那篇文章的作者,在前面那篇文章中学到了一些新知识。谢谢
|