Global OS object  H  FileSystem  Registry  Generic OS Queries  Global OS object  UI artifacts  OS Features  Processes  Network  CPU  Hardware  Firmware tables  Hooks  Timing  WMI  Human-like behavior  macOS


Global objects detection methods

The principle of all the global objects detection methods is the following: there are no such objects in usual host; however they exist in particular virtual environments and sandboxes. Virtual environment may be detected if such an artifact is present.


 

1. Check for specific global mutexes

This method checks for particular mutexes which are present in virtual environments but not in usual host systems.

Functions used:

Code sample

 

// 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);
}

Credits for this code sample: VMDE project

Signature recommendations

 

If the following function contains 3rd argument from the table column `Name`:

 

then it’s an indication of application trying to use the evasion technique.

Detections table

Check if the following global mutexes exist:
DetectName
DeepFreezeFrz_State
SandboxieSandboxie_SingleInstanceMutex_Control
SBIE_BOXED_ServiceInitComplete_Mutex1
VirtualPCMicrosoftVirtualPC7UserServiceMakeSureWe'reTheOnlyOneMutex


Note: DeepFreeze is an application restoring the system on each reboot.


 

2. Check for specific virtual devices

This method checks for particular virtual devices which are present in virtual environments but not in usual host systems.

Function used:

Code sample

 

// 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);
}

Credits for this code sample: VMDE project

Signature recommendations

 

If the following function contains 3rd argument with its field `ObjectName->Buffer` from the table column `Name`:

 

then it’s an indication of application trying to use the evasion technique.


3rd argument is of the following type:

typedef struct _OBJECT_ATTRIBUTES {
ULONG Length;
HANDLE RootDirectory;
PUNICODE_STRING ObjectName;
ULONG Attributes;
PVOID SecurityDescriptor;
PVOID SecurityQualityOfService;
} OBJECT_ATTRIBUTES;

Detections table

Check if the following virtual devices exist:
DetectPath
VirtualBox\\.\VBoxMiniRdDN
\\.\VBoxMiniRdrDN
\\.\VBoxGuest
\\.\VBoxTrayIPC
\\.\VBoxMouse
\\.\VBoxVideo
VMWare\\.\HGFS
\\.\vmci


 

3. Check for specific global pipes

Pipes are just a particular case of virtual devices, please refer to the previous section for code sample and signature recommendations.

Detections table

Check if the following global pipes exist:
DetectString
VirtualBox\\.\pipe\VBoxMiniRdDN
\\.\pipe\VBoxTrayIPC


 

4. Check for global objects

This method checks for particular global objects which are present in virtual environments but not in usual host systems.

Functions used:

Code sample

 

// 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;
}

Credits for this code sample: VMDE project

Detections table

Check if the following global objects exist:
DetectPathObject
Hyper-VVmGenerationCounter\Device
Parallelsprl_pv\Device
prl_tg\Device
prl_time\Device
SandboxieSandboxieDriverApi\Device
SbieDrv\Driver
SbieSvcPort\RPC Control
VirtualBoxVBoxGuest\Device
VBoxMiniRdr\Device
VBoxVideo\Driver
VBoxMouse\Driver
VirtualPCVirtualMachineServices\Device
1-driver-vmsrvc\Driver
VMWarevmmemctl\Device


 

5. Check for object directory (Sandboxie only)

This method checks for particular object directory which is present in Sandboxie virtual environment but not in usual host systems.

Function used:

Code sample

 

#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;
}

Credits for this code sample: VMDE project

Signature recommendations

 

If the following function contains 3rd argument with its field "ObjectName->Buffer" from the table column `Name`:

 

then it’s an indication of application trying to use the evasion technique.


3rd argument is of the following type:

typedef struct _OBJECT_ATTRIBUTES {
ULONG Length;
HANDLE RootDirectory;
PUNICODE_STRING ObjectName;
ULONG Attributes;
PVOID SecurityDescriptor;
PVOID SecurityQualityOfService;
} OBJECT_ATTRIBUTES;

Detections table

Check if the following object directory exists:
DetectPath
Sandboxie\Sandbox


 

6. Check if virtual registry is present in OS (Sandboxie only)

This method checks for virtual registry which is present in Sandboxie virtual environment but not in usual host systems.

Application opens registry key \REGISTRY\USER. It uses the following function in order to check real object name:

NtQueryObject(
hUserKey,
ObjectNameInformation,
oni, // OBJECT_NAME_INFORMATION object
Size,
NULL);

If received OBJECT_NAME_INFORMATION object name does not equal to the "\REGISTRY\USER", then application assumes that it runs inside Sandboxie environment.

Signature recommendations

 

If the following function is used for opening \REGISTRY\USER:

 

and is followed by the call of the following function with its 1st argument being the handle of \REGISTRY\USER key:

then it’s an indication of application trying to use the evasion technique.


 

Countermeasures

Hook target functions and return appropriate results if indicators (objects from tables) are triggered. In some cases stopping appropriate device may help — but it’s not a universal counter-action: not all global objects are devices.


 

Credits

Credits go to open-source project from where code samples were taken:

Though Check Point tool InviZzzible has them all implemented, due to modular structure of the code it would require more space to show a code sample from this tool for the same purposes. That’s why we’ve decided to use other great open-source projects for examples throughout the encyclopedia.