Summary:
病毒高危行为:
- 请求一系列加密的未知IP的443端口,连接可能与其他恶意软件通讯;尝试HTTP但是全都失败了
- 使用了大量的微软提供的加密函数,已知是AES对称加密
- 过程中怀疑使用了代码混淆
- 存在多处绕检测,反调试行为:比如频繁分配内存调用native方法,存在用另一个用户开启线程;多处使用了RDTSC指令来比对执行时间检测虚拟化或反调试;存在大量延迟尝试绕检测;存在LdrLoadDll动态调用绕检测;可能读取PEB信息检测调试器;修改token权限
MD5
974d669e861896a0ebd61c7f2d6e8729
SHA-1
3166a8b05fab2c455586e717210bdf1dad621fc1
SHA-256
b00e7f74539cf39940c9044b6ac1d131a23c896c7905d71a087a01245232ada3
Vhash
0150366d556"z
Authentihash
85badbaa56eef4169eb3c0127d9dace88a0b65b5965ad5a146a3477ab38914d4
SSDEEP
3072:9Wql7iWCRq3JV0npTvzY7hEsZNhh8J3Wn:9DNiWn52k7hEsBh
TLSH
T1B8D3490AE7D782B1FE9601B0167EB73F997152216B159EC3C7A01C20AD512E3A33E76D
File type
Win32 EXE
Magic
PE32 executable for MS Windows (GUI) Intel 80386 32-bit
调试过程logs
查完文件基本信息之后发现不是常见的vc/C++程序,直接拉到OD里面跑起来,试了一下平时用的一些脱壳方法完全不凑效,发现该程序的PE比较奇怪导入和导出表地址均为0,
于是开始单步调试大法
程序一定需要运行时动态加载未加载完的dll,所以我打开内存映射窗口,看着主窗口,一遍单步一遍观察内存情况同时适当的跳过一些未知的加密循环,光标所在行的上一个call eax为Sleep大约3秒然后光标处加载剩余dll(function0040C2F0),随后马上进入一个Function 00416870,
Function 00416870大概应该可以确定是程序的主体逻辑了.(本来尝试过dump 但是dump之后还是无法运行 大概是动态解密的关系吧)
进来16870之后是一个包含大量Sleep,获取CPU时钟相关API的函数,除此之外还有一个子调用,其中主要功能大概为遍历某个文件夹下的所有文件
随后经过一系列Sleephe GetTickCount,再后面看到几个消息处理的API一直到RtlAddVectoredExceptionHandler。然后出现一个子调用call Function 405B30
进入之后看到上面有几个子调用然后出现一个ConvertStringSecurityDescriptorToSecurityDescriptorW CreateMutexW
查阅MSDN之后,前者通常用于转换安全描述符,结合后面的CreateMutexW打开或者创建互斥量可以得出,这段代码大概率是在打开与当前病毒进程文件同名的信号互斥量,判断信号互斥量是否存在,防止病毒行为的二次执行。
那么我大胆推测病毒的主要功能就在这个代码的上方,结合ida的F5 我认为Function0041C6E0(v3 = mainfunction((int)v17, 0);) 包含了大量逻辑
v3 = mainfunction((int)v17, 0);
v4 = 1;
if ( !v3 )
{
sub_4121B0(v16, 50);
if ( ConvertStringSecurityDescriptorToSecurityDescriptorW(v16, 1, &v10, 0) )
{
v11 = v15;
}
else
{
v10 = 0;
v11 = 0;
}
v5 = sub_41A120();
v15[0] = 12;
v15[2] = 0;
LODWORD(v13) = -1640531527 * v5;
HIDWORD(v13) = -1640531527 * sub_41A120();
v15[1] = v10;
v14 = sub_403020(v17, 2 * v2, v13, HIDWORD(v13));
if ( dword_41F138(&v13, &v12) < 0 )
{
sub_4121B0(v17, 119);
sub_401CB0(v17, 128, v17, v13, v14);
v12 = v17;
}
v6 = sub_4121B0(v16, 27);
sub_41DD90((char *)v16 + 2 * v6, v12, 100);
v7 = createMute(v11, 1, v16);
*this = v7;
if ( v10 )
{
localFree(v10);
v7 = *this;
}
if ( !v7 || (v8 = getLastError(), v4 = 1, v8 != 183) )
v4 = 0;
}
return v4;
进入这个函数 发现非常非常的长,再逐行分析的话非常不容易,于是我查找所有的模块间调用同时查找所有模块中的名称,查看一下是否有一些敏感的api调用。
以下为我整理的可疑函数:
加密:
00406D10 CryptAcquireContextW,CryptImportKey,CryptSetKeyParam,CryptSetKeyParam,CryptDecrypt,CryptReleaseContext,CryptDestroyKey
0040E760 CryptAcquireContextW,CryptCreateHash,CryptHashData,CryptGetHashParam,CryptGetHashParam,CryptDestroyHash,CryptReleaseContext
0041A890 CryptStringToBinaryW,CryptStringToBinaryW
0040E300 CryptBinaryToStringW,CryptBinaryToStringW
网络:(函数在OD中并没有执行 可能是因为检测到调试器吧?unsure)
00415C80 WSAStartup WSACleanup HeapCreate GetProcessHeap RtlAllocateHeap FreeAddrInfoW getaddrinfo FreeAddrInfoW RtlFreeHeap
004067A0 GetCurrentProcess,OpenProcessToken,LookupPrivilegeValueW,AdjustTokenPrivileges,FindCloseChangeNotification
00407870 GetCurrentProcess,OpenProcessToken,LookupPrivilegeValueW,AdjustTokenPrivileges,RevertToSelf,DuplicateTokenEx,CloseHandle,AdjustTokenPrivileges,CloseHandle
0040DB40 GetStartupInfoW,GetCurrentProcess,OpenProcessToken,LookupPrivilegeValueW,AdjustTokenPrivileges,OpenProcess,OpenProcessToken,GetTokenInformation,AllocateAndInitializeSid,EqualSid,OpenProcessToken,RevertToSelf,DuplicateTokenEx,GetTokenInformation,GetTokenInformation,LookupAccountSidW,CreateProcessAsUserW,GetLastError,CloseHandle,CloseHandle,CloseHandle,AdjustTokenPrivileges,CloseHandle
0040BFB0 GetCurrentProcess,OpenProcessToken,LookupPrivilegeValueW,AdjustTokenPrivileges,CloseHandle,
可能的反调试,绕检测:
004021A0 RtlReAllocateHeap,NtDelayExecution,NtDelayExecution,
0041C6E0 NtQuerySstemInformation,NtQueryObject,GetCurrentProcess,NtQuerySystemInformation,OpenProcess,DuplicateHandle,NtQueryObject,NtQueryObject,NtQueryObject,FindCloseChangeNotification,FindCloseChangeNotification(CheckRemoteDebuggerPresent中会调用NtQueryInformationProcess函数)
004116E0 GetProcAddress,NtQueryInformationProcess
00408810 rdtsc 通过统计时间,判断当前环境是否是虚拟
0041B7A0 GetAdaptersInfo,GetAdaptersInfo 获取网络适配器信息
0040B4D0 LdrLoadDll,未公开的内核调用加载dll
大量的延迟函数:
419FD0 Sleep
4021D6 NtDelayExecution
403643 Sleep
4021D6 NtDelayExecution
4021D6 NtDelayExecution
408416 Sleep
4171A8 Sleep
4021D6 NtDelayExecution
可能用另一个用户启动线程:
0040DB40 GetStartupInfoW,GetCurrentProcess,OpenProcessToken,LookupPrivilegeValueW,AdjustTokenPrivileges,OpenProcess,OpenProcessToken,GetTokenInformation,AllocateAndInitializeSid,EqualSid,OpenProcessToken,RevertToSelf,DuplicateTokenEx,GetTokenInformation,GetTokenInformation,LookupAccountSidW,CreateProcessAsUserW,GetLastError,CloseHandle,CloseHandle,CloseHandle,AdjustTokenPrivileges,CloseHandle,
动态调用api:
00405940 LoadLibraryW,GetProcAddress,
程序大致流程和逻辑
设置了一个计时器和消息处理,然后创建了heap,在最下面的if出call 405b30
来到405b30
遍历完目录之后进入41c6e0
综合上述信息可得v117的结果应该是通过rdtsc测量时间来检测虚拟化
那么从125行到172行一定是具体检测的逻辑,对于具体怎么测量我不是很清楚
变量v5处再次调用41a120应该是测量前后两次时间差作比较的
接下来又出现3个子调用
第一个
4195a0
408c30
存在循环和位运算,和上一个函数的入参密码相关
第二个
打开句柄调整token权限
第三个
408810是之前的rdtsc指令,getTickCount上下都存在多个rdtsc
执行完第三个函数之后的变量v106和v117存在大量相似的计算和比较
V106还额外执行了上图的3个函数,结合逻辑可以得出上述的推测应该是正确的,即通过106和117获取检测虚拟化,同时在第一个调用处尝试隐藏一些信息(4195a0每次进入循环虚拟机就卡死了,不知道具体是在做什么样的加密)
接下来到label58
4148c0
执行到返回
中间又是包含一堆数学计算
然后出现一个入参包括v24,即上面计算结果的一个复制对象句柄函数
进入41a120之后发现又是一堆rdtsc和位运算
跟v69执行同样的操作在下面还有个v72=sub_41a120();
函数结尾处 停止监视通知更改句柄
该函数执行完后if判断通过
V7后面的操作应该就是判断是否重复执行了,所以该函数分析结束
返回到外层函数
40e940
生成sid 判断sid相等
40e5d0
StrStrlW GetSystemDirectoryW
大致逻辑下图
其中的41A840
返回a1不超过a2的第一个0地址
8460函数里面逻辑比价复杂
总体上应该就是一个获取目录比较确定目录同时包含加密解密的过程
在Function 00416870函数主体中一路分析
直到此处发现第一个网络连接httpAPiCalled,具体调用时数据如下图
跟进dword_41f044的函数看到出现了http相关的api
可以推测这个函数所在的循环 会循环请求ip地址列表中的ip,由于没有网络安全方面的工具,无法检测目标ip的安全性
继续调试
这个函数明显发送了请求 并且返回了请求失败
我在httpcall的地方留了断电 ,F9直接发现了第二个尝试请求的ip
继续F9
我在realrequest的地方F9至少等待了5次以上,不清楚这个
于是我打开wireshark对目标ip进行监视
192.168.88.135 51.77.112.255 TCP 66 49942 → 443 [SYN] Seq=0 Win=64240 Len=0 MSS=1460 WS=256 SACK_PERM=1
关于其连接知道的信息只有这么多了,未知的具体网络行为