黑客技术-反虚拟机和沙箱检测的一些小技巧

2019年5月30日17:16:14 发表评论

近年来,各类恶意软件层出不穷,反病毒软件也更新了各种检测方案以提高检测率。其中比较有效的方案是动态沙箱检测技术,即通过在沙箱中运行程序并观察程序行为来判断程序是否为恶意程序。

与此同时,安全人员也在各类虚拟机中运行程序进行分析。为了逃避沙箱/安全人员的检测,恶意软件使用了各类识别沙箱/虚拟机的技术,用于判断自身程序是否运行在沙箱/虚拟机中。文中介绍了几种检测虚拟机和沙箱的技术,如果有错误之处请各位 dalao 指正。

一、常用虚拟机检测

很多安全人员使用 VMware 和 VirtualBox 运行程序,以下介绍几种办法检测 vmware 和 vbox 特征。

1.通过进程名检测 VMware&VirtualBox

以下是 Vmware 和 VirtualBox 可能存在的进程,我们可以使用 Process32First,Process32Next 等 WINAPI 列举进程并且检测是否存以下内容。

Vmware:

Vmtoolsd.exe

Vmwaretrat.exe

Vmwareuser.exe

Vmacthlp.exe

VirtualBox:

vboxservice.exe

vboxtray.exe

以下是示例代码:

图片.png如上图,我们使用了 CreateToolhelp32Snapshot 给进程来个快照,然后使用 Process32First,Process32Next 枚举进程,并将进程名传入 check 函数中检测是否匹配数组中的名字,如果匹配到其中的一个,说明在 VirtualBox 中运行,CheckProcess 函数将返回 false。

图片.png

以下是在 VirtualBox 中运行的例子:

图片.png

备注:许多分析虚拟机中没有安装常用软件,我们也可以使用类似的办法检测系统中的 IM、浏览器等常用程序,来判断程序是否运行在虚拟机中。

2.检测注册表

以下是 vbox 和 vmware 存在的一些注册表:

HKLM\SOFTWARE\Vmware Inc\Vmware Tools

HKLM\HARDWARE\DEVICEMAP\Scsi\Scsi Port 2\Scsi Bus 0\Target Id 0\Logical Unit Id 0\Identifier

HKEY_CLASSES_ROOT\Applications\VMwareHostOpen.exe

HKEY_LOCAL_MACHINE\SOFTWARE\Oracle\VirtualBox Guest Additions


通过检测指定注册表键值是否存在来判断程序是否在虚拟机中运行:

图片.png

如上图使用 RegOpenKey WINAPI 打开指定键,如果成功代表存在该键,由此程序判断是否在虚拟机中。

3.检测硬盘中的文件

下面搜集来了一些 vmware 和 vbox 存在的文件特征。可以用多种方法检测文件是否存在,如:WMIC,WINAPI 和 CMD。

VMware

C:\windows\System32\Drivers\Vmmouse.sys

C:\windows\System32\Drivers\vmtray.dll

C:\windows\System32\Drivers\VMToolsHook.dll

C:\windows\System32\Drivers\vmmousever.dll

C:\windows\System32\Drivers\vmhgfs.dll

C:\windows\System32\Drivers\vmGuestLib.dll


VirtualBox

C:\windows\System32\Drivers\VBoxMouse.sys

C:\windows\System32\Drivers\VBoxGuest.sys

C:\windows\System32\Drivers\VBoxSF.sys

C:\windows\System32\Drivers\VBoxVideo.sys

C:\windows\System32\vboxdisp.dll

C:\windows\System32\vboxhook.dll

C:\windows\System32\vboxoglerrorspu.dll

C:\windows\System32\vboxoglpassthroughspu.dll

C:\windows\System32\vboxservice.exe

C:\windows\System32\vboxtray.exe

C:\windows\System32\VBoxControl.exe


例:使用 cmd 命令检测文件是否存在:

if exist "C:\windows\System32\vboxtray.exe" echo exist

图片.png

例:使用 c 语言中的 access 函数判断文件是否存在:

if ( !access("C:\\windows\\System32\\vboxtray.exe",0) )

printf(“在虚拟机中”)

else

printf(“不在虚拟机中”)


4.判断运行中的服务

下面列表中的服务如果存在,很可能运行在虚拟机中,我们可以使用 wmic 或命令 sc.exe query 等方式判断是否存在以下服务。

VMTools

Vmrawdsk

Vmusbmouse

Vmvss

Vmscsi

Vmxnet

vmx_svga

Vmware Tools

例:在 vbox 虚拟机中使用 sc query 获取服务名。

图片.png

上图黄色标记的 VBoxService 就是有可能携带的 vbox 虚拟机特征之一。

5.检测 mac 地址前缀

以下列出了几个 vmware 和 vbox 可能出现的默认 MAC 地址前缀,可以逐一判断来确认程序是否运行在虚拟机中:

00:05:69 (Vmware)

00:0C:29 (Vmware)

00:1C:14 (Vmware)

00:50:56 (Vmware)

08:00:27 (VirtualBox)

图片.png

如图在 vbox 虚拟机中使用 ipconfig /all 命令得到 MAC 地址,前缀 08-00-27 在列表中,可以判断是 vbox 虚拟机。

我们可以使用 c 中的 pipe 来获取 ipconfig /all 的结果,并且判断指定 MAC 是否存在,来判断是否在虚拟机中运行。

图片.png

下图是在 vbox 中运行的结果:

图片.png

下图是普通运行:

图片.png

6.使用 CPUID 指令检测虚拟机

CPUID 是一个面向 x86 架构的处理器补充指令,它的名称派生自 CPU 识别,作用是允许软件发现处理器的详细信息。EFLAGS 中的 bit 21 可以识别 CPU 是否支持 CPUID 指令,如下图:

图片.png

现在的 cpu 都是支持此指令的。cpuid 指令由 eax 寄存器获得输入,执行 cpuid 指令前,需要将功能号传给 eax 寄存器。

图片.png

在上图中 EAX=0:获取 CPU 的 Vendor ID。

用下面的方法执行该功能:

mov eax, 0

cpuid


执行 CPUID 指令后,返回的 Vendor ID 固定为 12 个 ASCII 字符,依次存放在 EBX、EDX、ECX 中。

EAX=1 部分:处理器签名(Processor Signiture)和功能(Feature)位。

mov eax, 1

cpuid


执行完成后,处理器签名放在 EAX 中,功能位及其它的内容分别放在 EBX、ECX 和 EDX 中。

将 EAX 置为 1,运行 CPUID 指令后获取 ECX 中的值并判断。

下图为示例代码:

图片.png

注:可以通过设置 eax 中不同的功能号自由获取 cpu 信息。

二、在线分析沙箱检测

在线沙箱通过记录程序运行情况进行判定,下面介绍一些小技巧来检测程序是否在沙箱里运行。

1.延迟运行

在各类检测沙箱中,检测运行的时间往往是比较短的,因为其没有过多资源可以供程序长时间运行,所以我们可以延迟等待一会儿后再进行真实的操作。

图片.png

std::sleep_for():线程调用该方法时,同样会让出 CPU,并且休眠一段时间,从而让其他线程有机会运行。等到休眠结束时,才参与 CPU 调度。

我们使用 this_thread::sleep_for()来延迟当前线程,此方法比使用 Sleep()更不容易被沙箱使用模拟方法绕过。

2.检测开机时间

许多沙箱检测完毕后会重置系统,我们可以检测开机时间来判断是否为真实的运行状况。

我们使用 WINAPI GetTickCount()来获取机器已运行的时间(以秒为单位)。然后判断开机运行时间是否大于 1 个小时,如果开机时间小于 1 小时就返回 false。

下图是示例代码:

图片.png

3.检测物理内存

当今大多数 pc 具有 4GB 以上的 RAM,我们可以检测 RAM 是否大于 4GB 来判断是否是真实的运行机器。

内存大小可能会大于 4GB 的情况下我们需要用 GlobalMemoryStatusEx 获取内存信息,查看 MSDN 会发现 MEMORYSTATUSEX 的成员值所占的字节数比 MEMORYSTATUS 成员值占用的字节数大,其中的成员 ullTotalPhys 为物理内存大小。

下图代码使用 GlobalMemoryStatusEx()来获得一个 DWORDLONG 类型的内存大小,然后与 4GB 比较,小于 4GB 返回 false,大于 4GB 返回 true。图片.png

4.检测 CPU 核心数

大多数 pc 拥有 4 核心 cpu,许多在线检测的虚拟机沙盘是 2 核心,我们可以通过核心数来判断是否为真实机器或检测用的虚拟沙箱。

使用 winapi 函数 GetSystemInfo()将系统信息写入类型为 SYSTEM_INFO 的结构体,其中成员 dwNumberOfProcessors 就是 CPU 核心数(超线程技术也算入核心),如果其小于 4,CheckCPU()将返回 false,检测不通过。

图片.png

5.检测临时文件数

正常使用的系统,其中用户的临时文件夹中有一定数量的临时文件,可以通过判断临时文件夹内的文件数量来检测是否在沙箱中运行。

先使用 GetEnvironmentVariable()获取 temp 路径,再利用 FindFirstFile()与 FindNextFile()枚举 temp 文件夹内的文件数量,如果小于 30,就返回 false,代表检测失败。

图片.png

总结与备注

当前有部分检测沙箱使用了 Intel Processor Tracing 技术,可以高效追踪程序的分支,在实际使用过程中,需要对 if 分支进行一定程度的代码混淆,防止分支模拟技术。并且现代检测沙箱正在不断提高拟真度,单独使用几个判断方法可能无法得出正确的判断,要多种方法结合使用,才能发挥出良好的效果。

参考链接:

https://docs.microsoft.com/zh-cn/windows/desktop/api/

http://blog.chinaunix.net/uid-20729583-id-1884599.html

*本文原创作者:nekoyansu

历史上的今天:

  • 博主微信
  • 赶快加我来聊天吧
  • weinxin
  • 博主QQ
  • QQ号:862277464
  • weinxin

发表评论

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: