目录
- 全局目标检测方法
- 1.检查特定的全局互斥体
- 2.检查特定的虚拟设备
- 3.检查特定的全局管道
- 4.检查特定的全局对象
- 5.检查特定对象目录(仅限于沙盒)
- 6.检查系统中是否存在虚拟注册表(仅限于沙盒)
- 反制措施
- 归功于
全局目标检测方法
所有全局对象检测方法的基本原理是:在通常的主机上没有这样的对象,但它们存在于特定的虚拟环境和沙盒中。如果存在这样的伪装,则可以检测虚拟环境。
1.检查特定的全局互斥体
此方法检查虚拟环境中存在但通常主机系统中不存在的特定互斥体。
使用的函数:
- CreateMutexA/W
- OpenMutexA/W
代码样本
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
// usage sample: supMutexExist(L "Sandboxie_SingleInstanceMutex_Control" ); // sample value from the table below BOOL supMutexExist(_In_ LPWSTR lpMutexName) { DWORD dwError; HANDLE hObject = NULL; if (lpMutexName == NULL) { return FALSE; } SetLastError(0); hObject = CreateMutex(NULL, FALSE, lpMutexName); // define around A or W function version dwError = GetLastError(); if (hObject) { CloseHandle(hObject); } return (dwError == ERROR_ALREADY_EXISTS); } |
该代码样本归功于:VMDE project
识别标志
如果以下函数包含表列“名称”的第3个参数:
- CreateMutexA/W(…, …, registry_path)
- OpenMutexA/W(…, …, registry_path)
那么这就表明应用程序试图使用规避技术。
检测表
检查是否存在以下全局互斥体: |
|
检测 |
名称 |
DeepFreeze |
Frz_State |
Sandboxie |
Sandboxie_SingleInstanceMutex_Control |
SBIE_BOXED_ServiceInitComplete_Mutex1 |
|
VirtualPC |
MicrosoftVirtualPC7UserServiceMakeSureWe’reTheOnlyOneMutex |
注意:DeepFreeze是一个在每次重启时恢复系统的应用程序。
2. 检查特定的虚拟设备
这种方法检查特定的虚拟设备,这些设备存在于虚拟环境中,但不在常规的主机系统中。
使用的函数:
- NtCreateFile
代码样本
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
|
// 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); } |
该代码样本归功于:VMDE project
识别标志
如果下面的函数包含第三个参数,它的字段’ ObjectName->Buffer ‘来自表列’ 名称 ‘:
- NtCreateFile(…, …, attr, …)
那么这就表明应用程序试图使用规避技术。
第三个参数的类型如下:
1
2
3
4
5
6
7
8
|
typedef struct _OBJECT_ATTRIBUTES { ULONG Length; HANDLE RootDirectory; PUNICODE_STRING ObjectName; ULONG Attributes; PVOID SecurityDescriptor; PVOID SecurityQualityOfService; } OBJECT_ATTRIBUTES; |
检测表
检查是否存在以下虚拟设备: |
||
检测 |
路径 |
|
VirtualBox |
\\.\VBoxMiniRdDN |
|
\\.\VBoxMiniRdrDN |
||
\\.\VBoxGuest |
||
\\.\VBoxTrayIPC |
||
\\.\VBoxMouse |
||
\\.\VBoxVideo |
||
VMware |
\\.\HGFS |
|
\\.\vmci |
3.检查特定的全局管道
管道只是虚拟设备的一个特殊情况,请参考上一节的代码样本和识别标志。
检测表
检查是否存在以下全局管道: | |
检测 |
字符串 |
VirtualBox |
\\.\pipe\VBoxMiniRdDN |
\\.\pipe\VBoxTrayIPC |
4.检查特定的全局对象
这种方法检查特定的全局对象,这些对象存在于虚拟环境中,但不存在于常规的主机系统中。
使用的函数:
- NtOpenDirectoryObject
- NtQueryDirectoryObject
代码样本
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
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
|
// usage sample: supIsObjectExists(L "\\Driver" , L "SbieDrv" ); // sample values from the table below typedef struct _OBJECT_DIRECTORY_INFORMATION { UNICODE_STRING Name; UNICODE_STRING TypeName; } OBJECT_DIRECTORY_INFORMATION, *POBJECT_DIRECTORY_INFORMATION; BOOL supIsObjectExists( _In_ LPWSTR RootDirectory, _In_ LPWSTR ObjectName) { OBJSCANPARAM Param; if (ObjectName == NULL) { return FALSE; } Param.Buffer = ObjectName; Param.BufferSize = ( ULONG )_strlen_w(ObjectName); return NT_SUCCESS(supEnumSystemObjects(RootDirectory, NULL, supDetectObjectCallback, &Param)); } NTSTATUS NTAPI supDetectObjectCallback( _In_ POBJECT_DIRECTORY_INFORMATION Entry, _In_ PVOID CallbackParam) { POBJSCANPARAM Param = (POBJSCANPARAM)CallbackParam; if (Entry == NULL) { return STATUS_INVALID_PARAMETER_1; } if (CallbackParam == NULL) { return STATUS_INVALID_PARAMETER_2; } if (Param->Buffer == NULL || Param->BufferSize == 0) { return STATUS_MEMORY_NOT_ALLOCATED; } if (Entry->Name.Buffer) { if (_strcmpi_w(Entry->Name.Buffer, Param->Buffer) == 0) { return STATUS_SUCCESS; } } return STATUS_UNSUCCESSFUL; } NTSTATUS NTAPI supEnumSystemObjects( _In_opt_ LPWSTR pwszRootDirectory, _In_opt_ HANDLE hRootDirectory, _In_ PENUMOBJECTSCALLBACK CallbackProc, _In_opt_ PVOID CallbackParam) { BOOL cond = TRUE; ULONG ctx, rlen; HANDLE hDirectory = NULL; NTSTATUS status; NTSTATUS CallbackStatus; OBJECT_ATTRIBUTES attr; UNICODE_STRING sname; POBJECT_DIRECTORY_INFORMATION objinf; if (CallbackProc == NULL) { return STATUS_INVALID_PARAMETER_4; } status = STATUS_UNSUCCESSFUL; __try { // We can use root directory. if (pwszRootDirectory != NULL) { RtlSecureZeroMemory(&sname, sizeof (sname)); RtlInitUnicodeString(&sname, pwszRootDirectory); InitializeObjectAttributes(&attr, &sname, OBJ_CASE_INSENSITIVE, NULL, NULL); status = NtOpenDirectoryObject(&hDirectory, DIRECTORY_QUERY, &attr); if (!NT_SUCCESS(status)) { return status; } } else { if (hRootDirectory == NULL) { return STATUS_INVALID_PARAMETER_2; } hDirectory = hRootDirectory; } // Enumerate objects in directory. ctx = 0; do { rlen = 0; status = NtQueryDirectoryObject(hDirectory, NULL, 0, TRUE, FALSE, &ctx, &rlen); if (status != STATUS_BUFFER_TOO_SMALL) break ; objinf = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, rlen); if (objinf == NULL) break ; status = NtQueryDirectoryObject(hDirectory, objinf, rlen, TRUE, FALSE, &ctx, &rlen); if (!NT_SUCCESS(status)) { HeapFree(GetProcessHeap(), 0, objinf); break ; } CallbackStatus = CallbackProc(objinf, CallbackParam); HeapFree(GetProcessHeap(), 0, objinf); if (NT_SUCCESS(CallbackStatus)) { status = STATUS_SUCCESS; break ; } } while (cond); if (hDirectory != NULL) { NtClose(hDirectory); } } __except (EXCEPTION_EXECUTE_HANDLER) { status = STATUS_ACCESS_VIOLATION; } return status; } |
该代码样本归功于:VMDE project
检测表
检查是否存在以下全局对象: |
||
检测 |
路径 |
对象 |
Hyper-V |
VmGenerationCounter |
\Device |
Parallels |
prl_pv |
\Device |
prl_tg |
\Device |
|
prl_time |
\Device |
|
Sandboxie |
SandboxieDriverApi |
\Device |
SbieDrv |
\Driver |
|
SbieSvcPort |
\RPC Control |
|
VirtualBox |
VBoxGuest |
\Device |
VBoxMiniRdr |
\Device |
|
VBoxVideo |
\Driver |
|
VBoxMouse |
\Driver |
|
VirtualPC |
VirtualMachineServices |
\Device |
1-driver-vmsrvc |
\Driver |
|
VMware |
vmmemctl |
\Device |
5.检查特定对象目录(仅限于沙盒)
该方法检查特定的对象目录,该目录存在于Sandboxie虚拟环境中,但不存在于常规的主机系统中。
使用的函数:
- GetFileAttributes
代码样本
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
#define DIRECTORY_QUERY (0x0001) #define OBJ_CASE_INSENSITIVE 0x00000040L #define DIRECTORY_SANDBOXIE L"\\Sandbox" int check_if_obj_dir_present() { OBJECT_ATTRIBUTES attr; UNICODE_STRING ustrName; HANDLE hObject = NULL; RtlSecureZeroMemory(&ustrName, sizeof (ustrName)); RtlInitUnicodeString(&ustrName, DIRECTORY_SANDBOXIE); InitializeObjectAttributes(&attr, &ustrName, OBJ_CASE_INSENSITIVE, NULL, NULL); if (NT_SUCCESS(NtOpenDirectoryObject(&hObject, DIRECTORY_QUERY, &attr))) { NtClose(hObject); return TRUE; } return FALSE; } |
该代码样本归功于:VMDE project
识别标志
如果下面的函数包含第3个参数,其字段 “ObjectName->Buffer “来自表列`名称`。
- NtOpenDirectoryObject(…, …, attr, …)
那么这就表明应用程序试图使用规避技术。
第三个参数的类型如下:
1
2
3
4
5
6
7
8
|
typedef struct _OBJECT_ATTRIBUTES { ULONG Length; HANDLE RootDirectory; PUNICODE_STRING ObjectName; ULONG Attributes; PVOID SecurityDescriptor; PVOID SecurityQualityOfService; } OBJECT_ATTRIBUTES; |
检测表
Check if the following object directory exists: |
|
Detect |
Path |
Sandboxie |
\Sandbox |
6.检查系统中是否存在虚拟注册表(仅限于沙盒)
此方法检查Sandboxie虚拟环境中存在的虚拟注册表,但在通常的主机系统中不存在。
应用程序打开注册表项\注册表\用户。它使用以下函数来检查真实的对象名:
1
2
3
4
5
6
|
NtQueryObject( hUserKey, ObjectNameInformation, oni, // OBJECT_NAME_INFORMATION object Size, NULL); |
如果接收到的OBJECT_NAME_INFORMATION对象名称不等于“”\REGISTRY\USER”,则应用程序假定它运行在沙箱环境中。
识别标志
如果使用以下函数来打开\REGISTRY\USER:
- NtOpenKey
后面是调用下面的函数,其第一个参数是 \REGISTRY\USER键的句柄:
- NtQueryObject(hUserKey, …)
那么这就表明应用程序试图使用规避技术。
反制措施
拦截目标函数,如果指标(表格中的对象)被触发,返回适当的结果。在某些情况下,停止适当的设备可能会有帮助–但这并不是一个普遍的反击行动:不是所有的全局对象都是设备。
暂无评论内容