描述
全局操作系统对象检测方法的原理是普通主机中不存在此类对象,因为此类对象只存在于特定的虚拟环境和沙箱中。如果存在这样的对象,则证明是虚拟环境。
1.热键
恶意软件可以设置热键,如果用户没有触发热键则不运行,以避免被虚拟机或沙盒环境检测。
以RegisterHotKey函数为例:
以RegisterHotKey函数为例:
#include <windows.h>
#include <stdio.h>
// 定义一个常量存储热键的标识符
const int HOTKEY_ID = 1;
// 定义一个常量存储规定时间(毫秒)
const DWORD TIME_LIMIT = 5000;
// 定义一个窗口过程函数,用于处理WM_HOTKEY消息
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
// 判断是否为WM_HOTKEY消息
if (uMsg == WM_HOTKEY)
{
// 判断是否为指定的热键
if (wParam == HOTKEY_ID)
{
// 如果是指定的热键,运行恶意代码
printf("The hotkey 'ALT+B' is pressed, executing.\n");
// 这里插入恶意代码,比如显示一个弹窗消息
MessageBoxA(NULL, "You have been infected by a malware!", "Malware Alert", MB_OK | MB_ICONWARNING);
return 0;
}
}
// 调用默认的窗口过程函数处理其他消息
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
int main()
{
// 注册一个窗口类
WNDCLASS wc = { 0 };
wc.lpfnWndProc = WindowProc;
wc.hInstance = GetModuleHandle(NULL);
wc.lpszClassName = L"HotKeyWindowClass";
RegisterClass(&wc);
// 创建一个隐藏的窗口,用于接收WM_HOTKEY消息
HWND hWnd = CreateWindowEx(0, L"HotKeyWindowClass", L"HotKeyWindow", 0, 0, 0, 0, 0, HWND_MESSAGE, NULL, GetModuleHandle(NULL), NULL);
// 如果成功,继续执行
if (hWnd != NULL)
{
// 调用RegisterHotKey函数注册热键“Alt+b”,并使用MOD_NOREPEAT标志避免重复触发
BOOL result = RegisterHotKey(hWnd, HOTKEY_ID, MOD_ALT | MOD_NOREPEAT, 0x42); // 0x42 is 'b'
// 如果成功,继续执行
if (result)
{
// 打印提示信息
printf("Hotkey 'ALT+B' registered, using MOD_NOREPEAT flag\n");
// 定义一个变量存储开始时间
DWORD startTime = GetTickCount();
// 定义一个变量存储结束时间
DWORD endTime;
// 定义一个变量存储是否触发的标志
BOOL triggered = FALSE;
// 循环处理消息
MSG msg = { 0 };
while (GetMessage(&msg, NULL, 0, 0) != 0)
{
// 转换和分发消息
TranslateMessage(&msg);
DispatchMessage(&msg);
// 判断是否为WM_HOTKEY消息
if (msg.message == WM_HOTKEY)
{
// 如果是WM_HOTKEY消息,设置触发标志为真,并退出循环
triggered = TRUE;
break;
}
// 获取当前时间
endTime = GetTickCount();
// 判断是否超过规定时间
if (endTime - startTime > TIME_LIMIT)
{
// 如果超过规定时间,退出循环
break;
}
}
// 判断是否触发了热键
if (triggered)
{
// 如果触发了热键,打印提示信息,并注销热键
printf("The hotkey was triggered within %d milliseconds.\n", TIME_LIMIT);
UnregisterHotKey(hWnd, HOTKEY_ID);
}
else
{
// 如果没有触发热键,不运行恶意代码,并注销热键
printf("The hotkey was not triggered within %d milliseconds, aborting.\n", TIME_LIMIT);
UnregisterHotKey(hWnd, HOTKEY_ID);
return 0;
}
}
else
{
// 如果失败,打印错误信息
printf("RegisterHotKey failed with error %d\n", GetLastError());
return -1;
}
}
else
{
// 如果失败,打印错误信息
printf("CreateWindowEx failed with error %d\n", GetLastError());
return -1;
}
}
2.检查特定的全局互斥体
恶意软件可以检查是否存在特定的全局互斥体,如果存在则不运行,以避免被虚拟机或沙盒环境检测。
检查以下互斥体是否存在:
检查以下互斥体是否存在:
探测 | 互斥体 |
---|---|
DeepFreeze | Frz_State |
Sandboxie | Sandboxie_SingleInstanceMutex_Control SBIE_BOXED_ServiceInitComplete_Mutex1 |
VirtualPC | MicrosoftVirtualPC7UserServiceMakeSureWe'reTheOnlyOneMutex |
以CreateMutexA/W函数为例:
#include <windows.h>
#include <stdio.h>
int main()
{
// 定义一个常量存储要检查的全局互斥体的名称
const char* MUTEX_NAME = "Global\\Sandboxie_SingleInstanceMutex_Control";
// 调用CreateMutexA函数创建或打开全局互斥体
HANDLE hMutex = CreateMutexA(NULL, FALSE, MUTEX_NAME);
// 如果成功,继续执行
if (hMutex != NULL)
{
// 打印提示信息
printf("CreateMutexA succeeded\n");
// 获取错误代码
DWORD dwError = GetLastError();
// 判断是否为ERROR_ALREADY_EXISTS
if (dwError == ERROR_ALREADY_EXISTS)
{
// 如果是ERROR_ALREADY_EXISTS,说明全局互斥体已经存在,不运行恶意代码,并关闭句柄
printf("The mutex '%s' already exists, aborting.\n", MUTEX_NAME);
CloseHandle(hMutex);
return 0;
}
else
{
// 如果不是ERROR_ALREADY_EXISTS,说明全局互斥体不存在,运行恶意代码,并关闭句柄
printf("The mutex '%s' does not exist, executing.\n", MUTEX_NAME);
// 这里插入恶意代码,比如显示一个弹窗消息
MessageBoxA(NULL, "You have been infected by a malware!", "Malware Alert", MB_OK | MB_ICONWARNING);
CloseHandle(hMutex);
}
}
else
{
// 如果失败,打印错误信息
printf("CreateMutexA failed with error %d\n", GetLastError());
return -1;
}
}
以OpenMutexA/W函数为例:
#include <windows.h>
#include <stdio.h>
int main() {
// 定义一个常量存储要检查的全局互斥体的名称
const char* MUTEX_NAME = "Global\\Sandboxie_SingleInstanceMutex_Control";
// 调用OpenMutexA函数打开全局互斥体
HANDLE hMutex = OpenMutexA(SYNCHRONIZE, FALSE, MUTEX_NAME);
// 如果成功,继续执行
if (hMutex != NULL)
{
// 打印提示信息
printf("OpenMutexA succeeded\n");
// 说明全局互斥体已经存在,不运行恶意代码,并关闭句柄
printf("The mutex '%s' already exists, aborting.\n", MUTEX_NAME);
CloseHandle(hMutex);
return 0;
}
else
{
// 如果失败,获取错误代码
DWORD dwError = GetLastError();
// 判断是否为ERROR_FILE_NOT_FOUND
if (dwError == ERROR_FILE_NOT_FOUND)
{
// 如果是ERROR_FILE_NOT_FOUND,说明全局互斥体不存在,运行恶意代码
printf("The mutex '%s' does not exist, executing.\n", MUTEX_NAME);
// 这里插入恶意代码,比如显示一个弹窗消息
MessageBoxA(NULL, "You have been infected by a malware!", "Malware Alert", MB_OK | MB_ICONWARNING);
}
else
{
// 如果不是ERROR_FILE_NOT_FOUND,打印错误信息
printf("OpenMutexA failed with error %d\n", dwError);
return -1;
}
}
}
3.检查特定的虚拟设备
恶意软件可以检查主机系统是否存在特定的虚拟设备,例如VMware或VirtualBox的驱动程序或硬件标识符。如果存在,恶意软件可以选择不运行或执行其他的逃逸或免杀技术。
检查是否存在以下虚拟设备:
检查是否存在以下虚拟设备:
探测 | 路径 |
---|---|
VirtualBox | \\.\VBoxMiniRdDN \\.\VBoxMiniRdrDN \\.\VBoxGuest \\.\VBoxTrayIPC \\.\VBoxMouse \\.\VBoxVideo |
VMware | \\.\HGFS \\.\vmci |
以NtCreateFile函数为例:
#include <windows.h>
#include <winternl.h>
#include <stdio.h>
#include <ntstatus.h>
// 定义NtCreateFile函数的类型
typedef NTSTATUS(WINAPI* NTCREATEFILE)(
PHANDLE FileHandle,
ACCESS_MASK DesiredAccess,
POBJECT_ATTRIBUTES ObjectAttributes,
PIO_STATUS_BLOCK IoStatusBlock,
PLARGE_INTEGER AllocationSize,
ULONG FileAttributes,
ULONG ShareAccess,
ULONG CreateDisposition,
ULONG CreateOptions,
PVOID EaBuffer,
ULONG EaLength
);
// 定义一些常量
#define FILE_OPEN 0x00000001
#define FILE_NON_DIRECTORY_FILE 0x00000040
#define OBJ_CASE_INSENSITIVE 0x00000040L
// 定义一个结构体来存储虚拟设备的名称和标识符
typedef struct _VIRTUAL_DEVICE {
LPCWSTR DeviceName; // 设备名称,如"\\Device\\VBoxMiniRdrDN"
LPCWSTR DeviceID; // 设备标识符,如"VBOX"
} VIRTUAL_DEVICE, * PVIRTUAL_DEVICE;
// 定义一个数组来存储要检测的虚拟设备
VIRTUAL_DEVICE VirtualDevices[] = {
{L"\\Device\\VBoxMiniRdrDN", L"VBOX"},
{L"\\Device\\vmci", L"VMWARE"},
{L"\\Device\\HGFS", L"VMWARE"},
{L"\\Device\\QEMUVP", L"QEMU"},
{NULL, NULL} // 结束标志
};
// 获取NtCreateFile函数的地址
NTCREATEFILE NtCreateFile = (NTCREATEFILE)GetProcAddress(GetModuleHandle(L"ntdll.dll"), "NtCreateFile");
// 检查虚拟设备是否存在
BOOL CheckVirtualDevice(PVIRTUAL_DEVICE vd)
{
HANDLE hFile;
OBJECT_ATTRIBUTES oa;
UNICODE_STRING us;
IO_STATUS_BLOCK isb;
// 初始化UNICODE_STRING结构体
RtlInitUnicodeString(&us, vd->DeviceName);
// 初始化OBJECT_ATTRIBUTES结构体
oa.Length = sizeof(oa);
oa.RootDirectory = NULL;
oa.ObjectName = &us;
oa.Attributes = OBJ_CASE_INSENSITIVE;
oa.SecurityDescriptor = NULL;
oa.SecurityQualityOfService = NULL;
// 调用NtCreateFile函数尝试打开虚拟设备
NTSTATUS status = NtCreateFile(&hFile, SYNCHRONIZE | FILE_READ_DATA, &oa, &isb, NULL, 0, FILE_SHARE_READ | FILE_SHARE_WRITE, FILE_OPEN, FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0);
// 如果成功打开,则关闭句柄并返回TRUE,否则返回FALSE
if (status == STATUS_SUCCESS)
{
CloseHandle(hFile);
return TRUE;
}
return FALSE;
}
// 主函数
int main()
{
// 遍历要检测的虚拟设备数组
for (int i = 0; VirtualDevices[i].DeviceName != NULL; i++)
{
// 如果检测到虚拟设备,则输出其名称和标识符,并退出程序
if (CheckVirtualDevice(&VirtualDevices[i]))
{
wprintf(L"Detected virtual device: %s (%s)\n", VirtualDevices[i].DeviceName, VirtualDevices[i].DeviceID);
ExitProcess(0);
}
}
// 如果没有检测到虚拟设备,则输出正常信息,并继续运行
wprintf(L"No virtual device detected.\n");
// 这里插入恶意代码,比如显示一个弹窗消息
MessageBoxA(NULL, "You have been infected by a malware!", "Malware Alert", MB_OK | MB_ICONWARNING);
return 0;
}
4.检查特定全局管道
管道只是虚拟设备的一种特殊情况,通常为VirtualBox特有的两个路径:
\.\pipe\VBoxMiniRdDN
\.\pipe\VBoxTrayIPC
以NtCreateFile函数为例:
\.\pipe\VBoxMiniRdDN
\.\pipe\VBoxTrayIPC
以NtCreateFile函数为例:
// usage sample:
HANDLE hDummy = NULL;
supOpenDevice(L"\\Device\\Null", GENERIC_READ, &hDummy); // sample values from the table below
BOOL supOpenDevice(
_In_ LPWSTR lpDeviceName,
_In_ ACCESS_MASK DesiredAccess,
_Out_opt_ PHANDLE phDevice)
{
OBJECT_ATTRIBUTES attr;
IO_STATUS_BLOCK iost;
UNICODE_STRING uDevName;
HANDLE hDevice;
NTSTATUS Status;
if (phDevice) {
*phDevice = NULL;
}
if (lpDeviceName == NULL) {
return FALSE;
}
hDevice = NULL;
RtlSecureZeroMemory(&uDevName, sizeof(uDevName));
RtlInitUnicodeString(&uDevName, lpDeviceName);
InitializeObjectAttributes(&attr, &uDevName, OBJ_CASE_INSENSITIVE, 0, NULL);
Status = NtCreateFile(&hDevice, DesiredAccess, &attr, &iost, NULL, 0,
0, FILE_OPEN, 0, NULL, 0);
if (NT_SUCCESS(Status)) {
if (phDevice != NULL) {
*phDevice = hDevice;
}
}
return NT_SUCCESS(Status);
}
5.检查全局对象
恶意软件可以检查主机系统是否存在特定的全局对象,例如VMware或VirtualBox的虚拟机标识符。如果存在,恶意软件可以选择不运行或执行其他的逃逸或免杀技术。
需要检查的全局对象如下:
需要检查的全局对象如下:
探测 | 路径 |
---|---|
Hyper-V | VmGenerationCounter |
Parallels | prl_pv prl_tg prl_time |
Sandboxie | SandboxieDriverApi SbieDrv SbieSvcPort |
VirtualBox | VBoxGuest VBoxMiniRdr VBoxVideo VBoxMouse |
VirtualPC | VirtualMachineServices 1-driver-vmsrvc |
VMware | vmmemctl |
以NtOpenDirectoryObject函数为例:
#include <windows.h>
#include <winternl.h>
#include <stdio.h>
// 定义NtOpenDirectoryObject函数的类型
typedef NTSTATUS(WINAPI* NTOPENDIRECTORYOBJECT)(
PHANDLE DirectoryHandle,
ACCESS_MASK DesiredAccess,
POBJECT_ATTRIBUTES ObjectAttributes
);
// 定义一些常量
#define DIRECTORY_QUERY 0x0001
#define OBJ_CASE_INSENSITIVE 0x00000040L
// 定义一个结构体来存储全局对象的名称和标识符
typedef struct _GLOBAL_OBJECT {
LPCWSTR ObjectName; // 全局对象名称,如"\\GLOBAL??\\VBoxMiniRdrDN"
LPCWSTR ObjectID; // 全局对象标识符,如"VBOX"
} GLOBAL_OBJECT, * PGLOBAL_OBJECT;
// 定义一个数组来存储要检测的全局对象
GLOBAL_OBJECT GlobalObjects[] = {
{L"\\GLOBAL??\\VBoxMiniRdrDN", L"VBOX"},
{L"\\GLOBAL??\\vmci", L"VMWARE"},
{L"\\GLOBAL??\\HGFS", L"VMWARE"},
{L"\\GLOBAL??\\QEMUVP", L"QEMU"},
{NULL, NULL} // 结束标志
};
// 获取NtOpenDirectoryObject函数的地址
NTOPENDIRECTORYOBJECT NtOpenDirectoryObject = (NTOPENDIRECTORYOBJECT)GetProcAddress(GetModuleHandle(L"ntdll.dll"), "NtOpenDirectoryObject");
// 检查全局对象是否存在
BOOL CheckGlobalObject(PGLOBAL_OBJECT go)
{
HANDLE hDir;
OBJECT_ATTRIBUTES oa;
UNICODE_STRING us;
// 初始化UNICODE_STRING结构体
RtlInitUnicodeString(&us, go->ObjectName);
// 初始化OBJECT_ATTRIBUTES结构体
oa.Length = sizeof(oa);
oa.RootDirectory = NULL;
oa.ObjectName = &us;
oa.Attributes = OBJ_CASE_INSENSITIVE;
oa.SecurityDescriptor = NULL;
oa.SecurityQualityOfService = NULL;
// 调用NtOpenDirectoryObject函数尝试打开全局对象
NTSTATUS status = NtOpenDirectoryObject(&hDir, DIRECTORY_QUERY, &oa);
// 如果成功打开,则关闭句柄并返回TRUE,否则返回FALSE
if (status == STATUS_SUCCESS)
{
CloseHandle(hDir);
return TRUE;
}
return FALSE;
}
// 主函数
int main()
{
// 遍历要检测的全局对象数组
for (int i = 0; GlobalObjects[i].ObjectName != NULL; i++)
{
// 如果检测到全局对象,则输出其名称和标识符,并退出程序
if (CheckGlobalObject(&GlobalObjects[i]))
{
wprintf(L"Detected global object: %s (%s)\n", GlobalObjects[i].ObjectName, GlobalObjects[i].ObjectID);
ExitProcess(0);
}
}
// 如果没有检测到全局对象,则输出正常信息,并继续运行
wprintf(L"No global object detected.\n");
// 这里插入恶意代码,比如显示一个弹窗消息
MessageBoxA(NULL, "You have been infected by a malware!", "Malware Alert", MB_OK | MB_ICONWARNING);
return 0;
}
以NtQueryDirectoryObject函数为例:
#include <windows.h>
#include <winternl.h>
#include <stdio.h>
// 定义NtQueryDirectoryObject函数的类型
typedef NTSTATUS(WINAPI* NTQUERYDIRECTORYOBJECT)(
HANDLE DirectoryHandle,
PVOID Buffer,
ULONG Length,
BOOLEAN ReturnSingleEntry,
BOOLEAN RestartScan,
PULONG Context,
PULONG ReturnLength
);
// 定义一些常量
#define DIRECTORY_QUERY 0x0001
#define OBJ_CASE_INSENSITIVE 0x00000040L
// 定义一个结构体来存储全局对象的名称和标识符
typedef struct _GLOBAL_OBJECT {
LPCWSTR ObjectName; // 全局对象名称,如"\\GLOBAL??\\VBoxMiniRdrDN"
LPCWSTR ObjectID; // 全局对象标识符,如"VBOX"
} GLOBAL_OBJECT, * PGLOBAL_OBJECT;
// 定义一个数组来存储要检测的全局对象
GLOBAL_OBJECT GlobalObjects[] = {
{L"\\GLOBAL??\\VBoxMiniRdrDN", L"VBOX"},
{L"\\GLOBAL??\\vmci", L"VMWARE"},
{L"\\GLOBAL??\\HGFS", L"VMWARE"},
{L"\\GLOBAL??\\QEMUVP", L"QEMU"},
{NULL, NULL} // 结束标志
};
// 获取NtQueryDirectoryObject函数的地址
NTQUERYDIRECTORYOBJECT NtQueryDirectoryObject = (NTQUERYDIRECTORYOBJECT)GetProcAddress(GetModuleHandle(L"ntdll.dll"), "NtQueryDirectoryObject");
// 检查全局对象是否存在
BOOL CheckGlobalObject(PGLOBAL_OBJECT go)
{
HANDLE hDir;
OBJECT_ATTRIBUTES oa;
UNICODE_STRING us;
// 初始化UNICODE_STRING结构体
RtlInitUnicodeString(&us, go->ObjectName);
// 初始化OBJECT_ATTRIBUTES结构体
oa.Length = sizeof(oa);
oa.RootDirectory = NULL;
oa.ObjectName = &us;
oa.Attributes = OBJ_CASE_INSENSITIVE;
oa.SecurityDescriptor = NULL;
oa.SecurityQualityOfService = NULL;
// 调用NtOpenDirectoryObject函数尝试打开全局对象
NTSTATUS status = NtOpenDirectoryObject(&hDir, DIRECTORY_QUERY, &oa);
// 如果成功打开,则继续查询目录对象内容
if (status == STATUS_SUCCESS)
{
// 定义一个缓冲区结构体来存储目录对象信息
typedef struct _OBJECT_DIRECTORY_INFORMATION {
UNICODE_STRING Name;
UNICODE_STRING TypeName;
} OBJECT_DIRECTORY_INFORMATION, * POBJECT_DIRECTORY_INFORMATION;
// 分配一个缓冲区大小为1024字节
POBJECT_DIRECTORY_INFORMATION buffer = (POBJECT_DIRECTORY_INFORMATION)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 1024);
// 定义一些变量来控制查询过程
ULONG context = 0; // 查询上下文,第一次为0,后续为返回值
ULONG returnLength; // 返回长度
BOOL restartScan = TRUE; // 是否重新扫描,第一次为TRUE,后续为FALSE
// 循环查询目录对象内容,直到返回STATUS_NO_MORE_ENTRIES
while (TRUE)
{
// 调用NtQueryDirectoryObject函数查询目录对象内容
status = NtQueryDirectoryObject(hDir, buffer, 1024, TRUE, restartScan, &context, &returnLength);
// 如果返回STATUS_NO_MORE_ENTRIES,表示查询结束,退出循环
if (status == STATUS_NO_MORE_ENTRIES)
{
break;
}
// 如果返回STATUS_SUCCESS,表示查询成功,继续判断
if (status == STATUS_SUCCESS)
{
// 比较目录对象的名称和类型是否与全局对象的标识符相同,如果相同,表示检测到全局对象,返回TRUE
if (wcscmp(buffer->Name.Buffer, go->ObjectID) == 0 || wcscmp(buffer->TypeName.Buffer, go->ObjectID) == 0)
{
return TRUE;
}
// 设置restartScan为FALSE,继续查询下一个目录对象
restartScan = FALSE;
}
}
// 释放缓冲区
HeapFree(GetProcessHeap(), 0, buffer);
// 关闭目录对象句柄
NtClose(hDir);
}
// 如果没有检测到全局对象,返回FALSE
return FALSE;
}
// 主函数
int main()
{
// 遍历要检测的全局对象数组
for (int i = 0; GlobalObjects[i].ObjectName != NULL; i++)
{
// 调用CheckGlobalObject函数检查全局对象是否存在
BOOL result = CheckGlobalObject(&GlobalObjects[i]);
// 打印检测结果
printf("Checking %S: %s\n", GlobalObjects[i].ObjectName, result ? "Detected" : "Not detected");
}
return 0;
}
6.检查对象目录
恶意软件可以检查主机系统是否存在特定的对象目录,例如某些安全软件或虚拟机的安装目录。如果存在,恶意软件可以选择不运行或执行其他的逃逸或免杀技术。
以GetFileAttributes函数为例:
以GetFileAttributes函数为例:
#include <windows.h>
#include <stdio.h>
#define UNICODE
// 定义一个结构体来存储对象目录的名称和属性
typedef struct _OBJECT_DIRECTORY {
LPCWSTR DirectoryName; // 对象目录名称,如"C:\\Program Files\\VMware"
DWORD DirectoryAttributes; // 对象目录属性,如FILE_ATTRIBUTE_DIRECTORY
} OBJECT_DIRECTORY, * POBJECT_DIRECTORY;
// 定义一个数组来存储要检测的对象目录
OBJECT_DIRECTORY ObjectDirectories[] = {
{"C:\\Program Files\\VMware", FILE_ATTRIBUTE_DIRECTORY},
{"C:\\Program Files\\Oracle\\VirtualBox", FILE_ATTRIBUTE_DIRECTORY},
{"C:\\Program Files\\QEMU", FILE_ATTRIBUTE_DIRECTORY},
{NULL, 0} // 结束标志
};
// 检查对象目录是否存在
BOOL CheckObjectDirectory(POBJECT_DIRECTORY od)
{
// 调用GetFileAttributes函数获取对象目录的属性
DWORD attributes = GetFileAttributes(od->DirectoryName);
// 如果返回值为INVALID_FILE_ATTRIBUTES,表示获取失败,可能对象目录不存在或者无法访问
if (attributes == INVALID_FILE_ATTRIBUTES)
{
return FALSE;
}
// 如果返回值与对象目录的属性相同,表示检测到对象目录,返回TRUE
if (attributes == od->DirectoryAttributes)
{
return TRUE;
}
// 否则返回FALSE
return FALSE;
}
7.检查虚拟注册表
此方法检查 Sandboxie 虚拟环境中存在但通常主机系统中不存在的虚拟注册表。需要检测注册表项\REGISTRY\USER,并使用
NtQueryObject
函数来检查真实对象名称:NtQueryObject(
hUserKey,
ObjectNameInformation,
oni, // OBJECT_NAME_INFORMATION object
Size,
NULL);
如果返回的OBJECT_NAME_INFORMATION对象名称不等于”\REGISTRY\USER”,则假定恶意软件在 Sandboxie 环境中运行。