目录
-
进程和库的检测方法
-
1.检查特定的正在运行进程和已加载的库
-
1.1. 检查特定进程是否正在运行
-
1.2. 检查进程地址空间中是否加载了特定的库
-
1.3. 检查特定库中是否存在特定函数
-
1.4. 反制措施
-
2.检查进程地址空间中是否存在特定的伪装(仅限于Sandboxie)
-
2.1. 反制措施
-
归功于
进程和库的检测方法
虚拟环境启动了一些特定的辅助进程,这些进程在通常的主机操作系统中没有被执行。还有一些特定的模块被加载到进程地址空间。
1.检查特定的正在运行进程和已加载的库
1.1. 检查特定进程是否正在运行
使用的函数:
-
CreateToolhelp32Snapshot
-
psapi.EnumProcesses (WinXP, Vista)
-
kernel32.EnumProcesses (Win7+)
代码样本:
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
|
check_process_is_running( "vmtoolsd.exe" ); // sample value from the table bool check_process_is_running( const std::string &proc_name) { HANDLE hSnapshot; PROCESSENTRY32 pe = {}; pe.dwSize = sizeof (pe); bool present = false ; hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); if (hSnapshot == INVALID_HANDLE_VALUE) return false ; if (Process32First(hSnapshot, &pe)) { do { if (!StrCmpI(pe.szExeFile, proc_name.c_str())) { present = true ; break ; } } while (Process32Next(hSnapshot, &pe)); } CloseHandle(hSnapshot); return present; } |
识别标志:
没有提供识别标志,因为很难说清楚进程的快照中到底查询了什么。
检测表:
检查以下进程是否正在运行: |
|
检测 |
进程 |
JoeBox |
joeboxserver.exe |
joeboxcontrol.exe |
|
Parallels |
prl_cc.exe |
prl_tools.exe |
|
VirtualBox |
vboxservice.exe |
vboxtray.exe |
|
VirtualPC |
vmsrvc.exe |
vmusrvc.exe |
|
VMware |
vmtoolsd.exe |
vmacthlp.exe |
|
vmwaretray.exe |
|
vmwareuser.exe |
|
vmware.exe |
|
vmount2.exe |
|
Xen |
xenservice.exe |
xsvc_depriv.exe |
|
WPE Pro |
WPE Pro.exe |
注意:WPE Pro是一个嗅探器,不是虚拟机,但它与虚拟机检测一起使用。
1.2. 检查进程地址空间中是否加载了特定的库
使用的函数:
-
GetModuleHandle
代码样本:
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
|
VOID loaded_dlls() { /* Some vars */ HMODULE hDll; /* Array of strings of blacklisted dlls */ TCHAR * szDlls[] = { _T( "sbiedll.dll" ), _T( "dbghelp.dll" ), _T( "api_log.dll" ), _T( "dir_watch.dll" ), _T( "pstorec.dll" ), _T( "vmcheck.dll" ), _T( "wpespy.dll" ), }; WORD dwlength = sizeof (szDlls) / sizeof (szDlls[0]); for ( int i = 0; i < dwlength; i++) { TCHAR msg[256] = _T( "" ); _stprintf_s(msg, sizeof (msg) / sizeof ( TCHAR ), _T( "Checking if process loaded modules contains: %s " ), szDlls[i]); /* Check if process loaded modules contains the blacklisted dll */ hDll = GetModuleHandle(szDlls[i]); if (hDll == NULL) print_results(FALSE, msg); else print_results(TRUE, msg); } } |
该代码样本的作者:al-khaser项目
识别标志:
如果以下函数包含其唯一的参数来自于列表`库`。
-
GetModuleHandle(module_name)
那么这就表明应用程序试图使用这种规避技术。
检测表:
检查进程地址空间中是否加载了下列库: |
|
检测 |
库 |
CWSandbox |
api_log.dll |
dir_watch.dll |
|
pstorec.dll |
|
Sandboxie |
sbiedll.dll |
ThreatExpert |
dbghelp.dll |
VirtualPC |
vmcheck.dll |
WPE Pro |
wpespy.dll |
注意:WPE Pro是一个嗅探器,不是虚拟机,但它与虚拟机检测一起使用。
1.3. 检查特定库中是否存在特定函数
使用的函数(请参阅有关本机函数的注释):
-
kernel32.GetProcAddress
-
kernel32.LdrGetProcedureAddress (called internally)
-
ntdll.LdrGetProcedureAddress
-
ntdll.LdrpGetProcedureAddress (called internally)
代码样本:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
BOOL wine_exports() { /* Some vars */ HMODULE hKernel32; /* Get kernel32 module handle */ hKernel32 = GetModuleHandle(_T( "kernel32.dll" )); if (hKernel32 == NULL) { print_last_error(_T( "GetModuleHandle" )); return FALSE; } /* Check if wine_get_unix_file_name is exported by this dll */ if (GetProcAddress(hKernel32, "wine_get_unix_file_name" ) == NULL) // sample value from the table return FALSE; else return TRUE; } |
该代码样本的作者:al-khaser项目
识别标志:
如果以下函数包含列表 “函数 “中的第2个参数,并且第1个参数是表中匹配 “库 “名称的地址。
-
kernel32.GetProcAddress(lib_handle, func_name)
-
kernel32.LdrGetProcedureAddress(lib_handle, func_name)
-
ntdll.LdrGetProcedureAddress(lib_handle, func_name)
-
ntdll.LdrpGetProcedureAddress(lib_handle, func_name)
那么这就表明应用程序试图使用这种规避技术。
检测表:
检查以下函数是否存在于以下库中: |
||
检测 |
库 |
函数 |
Wine |
kernel32.dll |
wine_get_unix_file_name |
ntdll.dll |
wine_get_version |
1.4. 反制措施
-
对于进程:从枚举中排除目标进程或终止它们。
-
对于库:将它们从PEB的枚举列表中排除。
-
对于库中的函数:拦截适当的函数并将其参数与目标参数进行比较。
2. 检查进程地址空间中是否存在特定的伪装(仅限于Sandboxie)。
使用的函数:
-
NtQueryVirtualMemory
代码样本:
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
|
BOOL AmISandboxied( LPVOID lpMinimumApplicationAddress, LPVOID lpMaximumApplicationAddress) { BOOL IsSB = FALSE; MEMORY_BASIC_INFORMATION RegionInfo; ULONG_PTR i, k; SIZE_T Length = 0L; i = ( ULONG_PTR )lpMinimumApplicationAddress; do { NTSTATUS Status = NtQueryVirtualMemory(GetCurrentProcess(), ( PVOID )i, MemoryBasicInformation, &RegionInfo, sizeof (MEMORY_BASIC_INFORMATION), &Length); if (NT_SUCCESS(Status)) { // Check if executable code if (((RegionInfo.AllocationProtect & PAGE_EXECUTE_READWRITE) == PAGE_EXECUTE_READWRITE) && ((RegionInfo.State & MEM_COMMIT) == MEM_COMMIT)) { for (k = i; k < i + RegionInfo.RegionSize; k += sizeof ( DWORD )) { if ( (*(PDWORD)k == 'kuzt' ) || (*(PDWORD)k == 'xobs' ) ) { IsSB = TRUE; break ; } } } i += RegionInfo.RegionSize; } else { i += 0x1000; } } while (i < ( ULONG_PTR )lpMaximumApplicationAddress); return IsSB; } |
Take a look at VMDE project sources.
看看VMDE项目源代码。
识别标志:
没有提供识别标志,因为很难说在检查内存缓冲区时到底查询了什么。
2.1. 反制措施
从内存中抹除现在的伪装
暂无评论内容