描述
Windows 管理接口 (WMI) 查询是获取操作系统和硬件信息的另一种方法。WMI 使用 COM 接口及其方法。
1.通用WMI查询
由于 WMI 提供了另一种收集系统信息的方法,因此它可用于执行其他文章中描述的规避技术,例如:
检查处理器数量是否不足
检查硬盘空间是否较小
检查MAC地址是否特定
检查CPU温度信息是否可用
检查处理器数量是否不足
检查硬盘空间是否较小
检查MAC地址是否特定
检查CPU温度信息是否可用
/*
Check number of cores using WMI
*/
BOOL number_cores_wmi()
{
IWbemServices *pSvc = NULL;
IWbemLocator *pLoc = NULL;
IEnumWbemClassObject *pEnumerator = NULL;
BOOL bStatus = FALSE;
HRESULT hRes;
BOOL bFound = FALSE;
// Init WMI
bStatus = InitWMI(&pSvc, &pLoc);
if (bStatus)
{
// If success, execute the desired query
bStatus = ExecWMIQuery(&pSvc, &pLoc, &pEnumerator, _T("SELECT * FROM Win32_Processor"));
if (bStatus)
{
// Get the data from the query
IWbemClassObject *pclsObj = NULL;
ULONG uReturn = 0;
VARIANT vtProp;
// Iterate over our enumator
while (pEnumerator)
{
hRes = pEnumerator->Next(WBEM_INFINITE, 1, &pclsObj, &uReturn);
if (0 == uReturn)
break;
// Get the value of the Name property
hRes = pclsObj->Get(_T("NumberOfCores"), 0, &vtProp, 0, 0);
if (V_VT(&vtProp) != VT_NULL) {
// Do our comparaison
if (vtProp.uintVal < 2) {
bFound = TRUE; break;
}
// release the current result object
VariantClear(&vtProp);
pclsObj->Release();
}
}
// Cleanup
pEnumerator->Release();
pSvc->Release();
pLoc->Release();
CoUninitialize();
}
}
return bFound;
}
/*
Check hard disk size using WMI
*/
BOOL disk_size_wmi()
{
IWbemServices *pSvc = NULL;
IWbemLocator *pLoc = NULL;
IEnumWbemClassObject *pEnumerator = NULL;
BOOL bStatus = FALSE;
HRESULT hRes;
BOOL bFound = FALSE;
INT64 minHardDiskSize = (80LL * (1024LL * (1024LL * (1024LL))));
// Init WMI
bStatus = InitWMI(&pSvc, &pLoc);
if (bStatus)
{
// If success, execute the desired query
bStatus = ExecWMIQuery(&pSvc, &pLoc, &pEnumerator, _T("SELECT * FROM Win32_LogicalDisk"));
if (bStatus)
{
// Get the data from the query
IWbemClassObject *pclsObj = NULL;
ULONG uReturn = 0;
VARIANT vtProp;
// Iterate over our enumator
while (pEnumerator)
{
hRes = pEnumerator->Next(WBEM_INFINITE, 1, &pclsObj, &uReturn);
if (0 == uReturn)
break;
// Get the value of the Name property
hRes = pclsObj->Get(_T("Size"), 0, &vtProp, 0, 0);
if (V_VT(&vtProp) != VT_NULL) {
// Do our comparaison
if (vtProp.llVal < minHardDiskSize) { // Less than 80GB
bFound = TRUE; break;
}
// release the current result object
VariantClear(&vtProp);
pclsObj->Release();
}
}
// Cleanup
pEnumerator->Release();
pSvc->Release();
pLoc->Release();
CoUninitialize();
}
}
return bFound;
}
使用PowerShell查询:
(Get-CimInstance -ClassName Win32_BIOS -Property SerialNumber).SerialNumber
2.使用WMI逃避跟踪
WMI 提供了一种创建新进程和安排任务的方法。沙箱通常使用CreateProcessInternalW函数挂钩来跟踪子进程。但是当使用 WMI 创建进程时,父进程中不会调用函数CreateProcessInternalW 。因此,使用 WMI 创建的进程可能不会被沙箱跟踪,并且它们的行为也不会被记录。
以使用 WMI 启动进程为例:
以使用 WMI 启动进程为例:
// Initialize COM
CoInitializeEx(NULL, COINIT_MULTITHREADED);
// Set general COM security levels
hres = CoInitializeSecurity(NULL, -1, NULL, NULL, RPC_C_AUTHN_LEVEL_DEFAULT, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, 0, NULL);
if (FAILED(hres) && hres != RPC_E_TOO_LATE)
break;
// create an instance of WbemLocator
CoCreateInstance(CLSID_WbemLocator, NULL, CLSCTX_INPROC_SERVER, IID_IWbemLocator, (LPVOID*)&wbemLocator);
wbemLocator->ConnectServer(CComBSTR("ROOT\\CIMV2"), NULL, NULL, NULL, 0, NULL, NULL, &wbemServices);
// get Win32_Process object
wbemServices->GetObject(CComBSTR("Win32_Process"), 0, NULL, &oWin32Process, &callResult);
wbemServices->GetObject(CComBSTR("Win32_ProcessStartup"), 0, NULL, &oWin32ProcessStartup, &callResult);
oWin32Process->GetMethod(CComBSTR("Create"), 0, &oMethCreate, &oMethCreateSignature);
oMethCreate->SpawnInstance(0, &instWin32Process);
oWin32ProcessStartup->SpawnInstance(0, &instWin32ProcessStartup);
// set startup information for process
instWin32ProcessStartup->Put(CComBSTR("CreateFlags"), 0, &varCreateFlags, 0);
instWin32Process->Put(CComBSTR("CommandLine"), 0, &varCmdLine, 0);
instWin32Process->Put(CComBSTR("CurrentDirectory"), 0, &varCurDir, 0);
CComVariant varStartupInfo(instWin32ProcessStartup);
instWin32Process->Put(CComBSTR("ProcessStartupInformation"), 0, &varStartupInfo, 0);
wbemServices->ExecMethod(CComBSTR("Win32_Process"), CComBSTR("Create"), 0, NULL, instWin32Process, &pOutParams, &callResult);
以通过 WMI 使用任务计划程序启动进程 为例(Windows 7):
#使用“ Win32_ScheduledJob ”类和“ Create ”方法通过WMI创建新任务。然而,“ Win32_ScheduledJob ”WMI 类被设计为与 AT 命令一起使用,该命令自 Windows 8 起已被弃用。
#在 Windows 8 及更高版本中,如果注册表项“HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\WindowsNT\CurrentVersion\Schedule\Configuration ”具有REG_DWORD类型的值“ EnableAt ”=”1”,则只能使用 WMI 创建计划任务。因此,这种技术不太可能在野外被发现。
#使用“ Win32_ScheduledJob ”类和“ Create ”方法通过WMI创建新任务。然而,“ Win32_ScheduledJob ”WMI 类被设计为与 AT 命令一起使用,该命令自 Windows 8 起已被弃用。
#在 Windows 8 及更高版本中,如果注册表项“HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\WindowsNT\CurrentVersion\Schedule\Configuration ”具有REG_DWORD类型的值“ EnableAt ”=”1”,则只能使用 WMI 创建计划任务。因此,这种技术不太可能在野外被发现。
strComputer = "."
Set objWMIService = GetObject("winmgmts:" & "{impersonationLevel=Impersonate}!\\" & strComputer & "\root\cimv2")
Set objSWbemDateTime = CreateObject("WbemScripting.SWbemDateTime")
objSWbemDateTime.SetVarDate(DateAdd("n", 1, Now()))
Set objNewJob = objWMIService.Get("Win32_ScheduledJob")
errJobCreate = objNewJob.Create("malware.exe", objSWbemDateTime.Value, False, , , True, "MaliciousJob")
3.查看上次开机时间
如果从快照还原 VM 后立即查询上次启动时间,则 WMI 数据库可能包含创建 VM 快照时保存的值。如果快照是一年前创建的,即使沙箱更新了上次启动时间,计算出的系统正常运行时间也将是一年。
通过该方法可用于检测从快照恢复的虚拟机。此外,上次启动时间中的任何异常都可以用作沙箱指标:
系统正常运行时间太大(数月甚至数年)
系统正常运行时间太短(不到几分钟)
使用其他方法获取(可以参考“定时”)的上次启动时间与使用WMI获取的上次启动时间不同
通过该方法可用于检测从快照恢复的虚拟机。此外,上次启动时间中的任何异常都可以用作沙箱指标:
系统正常运行时间太大(数月甚至数年)
系统正常运行时间太短(不到几分钟)
使用其他方法获取(可以参考“定时”)的上次启动时间与使用WMI获取的上次启动时间不同
strComputer = "."
Set objWMIService = GetObject("winmgmts:" & "{impersonationLevel=impersonate}!\\" & strComputer & "\root\cimv2")
Set colOperatingSystems = objWMIService.ExecQuery ("Select * from Win32_OperatingSystem")
For Each objOS in colOperatingSystems
dtmBootup = objOS.LastBootUpTime
dtmLastBootUpTime = WMIDateStringToDate(dtmBootup)
dtmSystemUptime = DateDiff("n", dtmLastBootUpTime, Now)
Wscript.Echo "System uptime minutes: " & dtmSystemUptime
Next
Function WMIDateStringToDate(dtm)
WMIDateStringToDate = CDate(Mid(dtm, 5, 2) & "/" & _
Mid(dtm, 7, 2) & "/" & Left(dtm, 4) & " " & Mid (dtm, 9, 2) & ":" & _
Mid(dtm, 11, 2) & ":" & Mid(dtm, 13, 2))
End Function
4.检查网络适配器上次重置时间
检查是否有任何适配器的上次重置时间。如果时间过久可能表明应用程序正在从快照恢复的虚拟机中运行。
strComputer = "."
Set objWMIService = GetObject("winmgmts:" & "{impersonationLevel=impersonate}!\\" & strComputer & "\root\cimv2")
Set colOperatingSystems = objWMIService.ExecQuery ("Select * from Win32_NetworkAdapter")
For Each objOS in colNetworkAdapters
dtmLastReset = objOS.TimeOfLastReset
dtmLastResetTime = WMIDateStringToDate(dtmLastReset) 'WMIDateStringToDate function from the previous example
dtmAdapterUptime = DateDiff("n", dtmLastResetTime, Now)
Wscript.Echo "Adapter uptime minutes: " & dtmAdapterUptime
Next