设为首页收藏本站
查看: 3663|回复: 0

[翻译]规避技术: WMI

[复制链接]
  • TA的每日心情
    开心
    2022-1-9 18:41
  • 签到天数: 5 天

    [LV.2]偶尔看看I

    发表于 2021-9-12 16:56:03 | 显示全部楼层 |阅读模式
    备注
    原文地址:https://evasions.checkpoint.com/techniques/wmi.html
    原文标题:Evasions: WMI
    更新日期:2021年6月3日
    此文后期:根据自身所学进行内容扩充
    因自身技术有限,只能尽自身所能翻译国外技术文章,供大家学习,若有不当或可完善的地方,希望可以指出,用于共同完善这篇文章。



    目录
    WMI检测方法
    背景介绍
    1. 通用的WMI查询
    2. 利用WMI逃避追踪
    2.1. 使用WMI启动程序
    2.2. 通过WMI使用任务计划程序启动进程
    3. 检查最后的启动时间
    4. 检查网络适配器的最后重置时间
    识别标志
    反制措施
    归功于

    WMI检测方法
    Windows管理接口(WMI)查询是获得操作系统和硬件信息的另一种方式。WMI使用COM接口和它们的方法。
    背景介绍
    标准COM函数被用来处理查询。它们的调用顺序如下所述,可分为6个步骤。
    1. COM的初始化。
    • CoInitialize/CoInitializeEx

    2. 创建所需的接口实例。
    • 创建接口实例:CoCreateInstance/CoCreateInstanceEx

    3. 通过接口实例连接到特定的服务,其功能如下。
    • ConnectServer

    4. 用这些函数获取服务的方法并设置其参数。
    • Method (to get methods)
    • Put (to set arguments)

    5. 从服务中检索信息,并用下面的函数执行服务的方法。左边的函数是右边的函数的代理--这些函数在内部被调用。
    • ExecQuery -> IWbemServices_ExecQuery (检索信息)
    • ExecMethod -> IWbemServices_ExecMethod (执行方法)
    • ExecMethodAsync -> IWbemServices_ExecMethodAsync (执行方法)

    6. 用以下函数检查查询的结果。
    • [enumerator]->Next
    • [object]->Get

    要想了解所描述的理论是如何应用于实践的,请查看下面的例子。
    1. 通用的WMI查询
    由于WMI提供了另一种收集系统信息的方式,它可以被用来执行其他文章中描述的规避技术,例如:
    • 检查处理器数量是否不足
    • 检查硬盘大小是否小
    • 检查MAC地址是否特定
    • 检查CPU温度信息是否可用

    代码样本:
    1. /*
    2. Check number of cores using WMI
    3. */
    4. BOOL number_cores_wmi()
    5. {
    6.   IWbemServices *pSvc = NULL;
    7.   IWbemLocator *pLoc = NULL;
    8.   IEnumWbemClassObject *pEnumerator = NULL;
    9.   BOOL bStatus = FALSE;
    10.   HRESULT hRes;
    11.   BOOL bFound = FALSE;

    12.   // Init WMI
    13.   bStatus = InitWMI(&pSvc, &pLoc);
    14.   if (bStatus)
    15.   {
    16.     // If success, execute the desired query
    17.     bStatus = ExecWMIQuery(&pSvc, &pLoc, &pEnumerator, _T("SELECT * FROM Win32_Processor"));
    18.     if (bStatus)
    19.     {
    20.       // Get the data from the query
    21.       IWbemClassObject *pclsObj = NULL;
    22.       ULONG uReturn = 0;
    23.       VARIANT vtProp;

    24.       // Iterate over our enumator
    25.       while (pEnumerator)
    26.       {
    27.         hRes = pEnumerator->Next(WBEM_INFINITE, 1, &pclsObj, &uReturn);
    28.         if (0 == uReturn)
    29.           break;

    30.         // Get the value of the Name property
    31.         hRes = pclsObj->Get(_T("NumberOfCores"), 0, &vtProp, 0, 0);
    32.         if (V_VT(&vtProp) != VT_NULL) {

    33.           // Do our comparaison
    34.           if (vtProp.uintVal < 2) {
    35.             bFound = TRUE; break;
    36.           }

    37.           // release the current result object
    38.           VariantClear(&vtProp);
    39.           pclsObj->Release();
    40.         }
    41.       }

    42.       // Cleanup
    43.       pEnumerator->Release();
    44.       pSvc->Release();
    45.       pLoc->Release();
    46.       CoUninitialize();
    47.     }
    48.   }

    49.   return bFound;
    50. }


    51. /*
    52. Check hard disk size using WMI
    53. */
    54. BOOL disk_size_wmi()
    55. {
    56.   IWbemServices *pSvc = NULL;
    57.   IWbemLocator *pLoc = NULL;
    58.   IEnumWbemClassObject *pEnumerator = NULL;
    59.   BOOL bStatus = FALSE;
    60.   HRESULT hRes;
    61.   BOOL bFound = FALSE;
    62.   INT64 minHardDiskSize = (80LL * (1024LL * (1024LL * (1024LL))));

    63.   // Init WMI
    64.   bStatus = InitWMI(&pSvc, &pLoc);
    65.   if (bStatus)
    66.   {
    67.     // If success, execute the desired query
    68.     bStatus = ExecWMIQuery(&pSvc, &pLoc, &pEnumerator, _T("SELECT * FROM Win32_LogicalDisk"));
    69.     if (bStatus)
    70.     {
    71.       // Get the data from the query
    72.       IWbemClassObject *pclsObj = NULL;
    73.       ULONG uReturn = 0;
    74.       VARIANT vtProp;

    75.       // Iterate over our enumator
    76.       while (pEnumerator)
    77.       {
    78.         hRes = pEnumerator->Next(WBEM_INFINITE, 1, &pclsObj, &uReturn);
    79.         if (0 == uReturn)
    80.           break;

    81.         // Get the value of the Name property
    82.         hRes = pclsObj->Get(_T("Size"), 0, &vtProp, 0, 0);
    83.         if (V_VT(&vtProp) != VT_NULL) {

    84.           // Do our comparaison
    85.           if (vtProp.llVal < minHardDiskSize) { // Less than 80GB
    86.             bFound = TRUE; break;
    87.           }

    88.           // release the current result object
    89.           VariantClear(&vtProp);
    90.           pclsObj->Release();
    91.         }
    92.       }

    93.       // Cleanup
    94.       pEnumerator->Release();
    95.       pSvc->Release();
    96.       pLoc->Release();
    97.       CoUninitialize();
    98.     }
    99.   }

    100.   return bFound;
    101. }
    复制代码

    该代码样本的作者:al-khaser项目
    代码样本(PowerShell):
    1. (Get-CimInstance -ClassName Win32_BIOS -Property SerialNumber).SerialNumber
    复制代码

    识别标志:
    如果下面的函数包含来自表列 "
    Query
    "的第3个参数:
    • IWbemServices_ExecQuery(..., query, ...)

    则表明该应用程序试图使用规避技术。
    检查表:
    [tr][/tr]
    以下WMI查询可用于检测虚拟环境:
    Query查询方式
    Field字段
    Value值
    Detect检测
    Comments注释
    SELECT * FROM Win32_Processor
    NumberOfCores
    < 2
    [general]

    ProcessorId
    [empty]

    SELECT * FROM Win32_LogicalDisk
    Size
    < 60GB

    SELECT * FROM Win32_BaseBoard
    SerialNumber
    None

    Version
    None

    SELECT * FROM MSAcpi_ThermalZoneTemperature
    CurrentTemperature
    "Not supported"

    SELECT * FROM Win32_PnPEntity
    DeviceId
    PCI\VEN_80EE&DEV_CAFE
    VirtualBox

    IDE\CDROOMVBOX
    IDE\DISKVBOX*
    VEN_VMWARE
    VMware

    PROD_VMWARE_VIRTUAL
    SELECT * FROM Win32_NetworkAdapterConfiguration
    MACAddress
    08:00:27
    VirtualBox
    See "Check if MAC address is specific" section in "Network" chapter
    00:1C:42
    Parallels

    00:05:69
    VMware

    00:0C:29
    00:1C:14
    00:50:56
    00:16:E3
    XEN

    SELECT * FROM Win32_Bios
    Serial Number
    VMware-
    VMware

    0
    VirtualBox

    Version
    INTEL - 6040000
    VMware
    See "SystemBiosVersion" in "Check if particular registry keys contain specified strings" section in "Registry" chapter
    BOCHS
    BOCHS

    PARALLELS
    Parallels

    QEMU
    QEMU

    VBOX
    VirtualBox

    SELECT * FROM Win32_ComputerSystem
    Model
    VMware
    VMware

    VirtualBox
    VirtualBox

    Manufacturer
    VMware
    VMware

    innotek GmbH
    VirtualBox

    SELECT * FROM Win32_VideoController
    AdapterCompatibility
    VMware
    VMware

    Oracle Corporation
    VirtualBox

    Caption
    VMware
    VMware

    VirtualBox
    VirtualBox

    Description
    VMware
    VMware

    VirtualBox
    VirtualBox

    Name
    VMware
    VMware

    VirtualBox
    VirtualBox

    SELECT * FROM Win32_PointingDevice
    Description
    VMware
    VMware

    表中所列的查询并不是唯一可能的,提出这些查询是为了让人们了解它们是如何工作的,以及用这些调用可以检索到什么信息
    反制措施:
    反制措施取决于通过WMI方法实现的特定检查,它们与相关文章中描述的相应方法相同。此外,你必须重新启动 "winmgmt "服务。
    2. 利用WMI逃避追踪
    WMI提供了一种创建新进程和安排任务的方法。沙盒通常使用CreateProcessInternalW函数挂钩来跟踪子进程。然而,当你使用WMI创建进程时,函数CreateProcessInternalW不会在父进程中被调用。因此,使用WMI创建的进程可能不会被沙盒跟踪,其行为也不会被记录。
    2.1. 使用WMI启动程序
    你可以通过WMI使用 "Win32_Process "类的 "Create "方法来创建一个新的进程。
    代码样本:
    1. // Initialize COM
    2. CoInitializeEx(NULL, COINIT_MULTITHREADED);

    3. //  Set general COM security levels
    4. hres = CoInitializeSecurity(NULL, -1, NULL, NULL, RPC_C_AUTHN_LEVEL_DEFAULT, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, 0, NULL);
    5. if (FAILED(hres) && hres != RPC_E_TOO_LATE)
    6.     break;

    7. // create an instance of WbemLocator
    8. CoCreateInstance(CLSID_WbemLocator, NULL, CLSCTX_INPROC_SERVER, IID_IWbemLocator, (LPVOID*)&wbemLocator);
    9. wbemLocator->ConnectServer(CComBSTR("ROOT\\CIMV2"), NULL, NULL, NULL, 0, NULL, NULL, &wbemServices);

    10. // get Win32_Process object
    11. wbemServices->GetObject(CComBSTR("Win32_Process"), 0, NULL, &oWin32Process, &callResult);
    12. wbemServices->GetObject(CComBSTR("Win32_ProcessStartup"), 0, NULL, &oWin32ProcessStartup, &callResult);
    13. oWin32Process->GetMethod(CComBSTR("Create"), 0, &oMethCreate, &oMethCreateSignature);
    14. oMethCreate->SpawnInstance(0, &instWin32Process);
    15. oWin32ProcessStartup->SpawnInstance(0, &instWin32ProcessStartup);
    16. // set startup information for process
    17. instWin32ProcessStartup->Put(CComBSTR("CreateFlags"), 0, &varCreateFlags, 0);
    18. instWin32Process->Put(CComBSTR("CommandLine"), 0, &varCmdLine, 0);
    19. instWin32Process->Put(CComBSTR("CurrentDirectory"), 0, &varCurDir, 0);
    20. CComVariant varStartupInfo(instWin32ProcessStartup);
    21. instWin32Process->Put(CComBSTR("ProcessStartupInformation"), 0, &varStartupInfo, 0);
    22. wbemServices->ExecMethod(CComBSTR("Win32_Process"), CComBSTR("Create"), 0, NULL, instWin32Process, &pOutParams, &callResult);
    复制代码

    代码样本取自InviZzzible工具
    识别标志:
    如果用第2个参数 "Win32_Process "和第3个参数 "Create "调用以下函数之一:
    • IWbemServices_ExecMethod(..., BSTR("Win32_Process"), BSTR("Create"), ...)
    • IWbemServices_ExecMethodAsync(..., BSTR("Win32_Process"), BSTR("Create"), ...)

    那么它就表明该应用程序试图使用规避技术。

    反制措施:

    如果你使用内核模式的监控器,用PsSetCreateProcessNotifyRoutineEx拦截目标函数或注册进程创建时的回调。
    2.2. 通过WMI使用任务计划程序启动进程(Windows 7)
    该技术与 "定时 "一章中的 "使用任务计划程序推迟执行 "一节中描述的基本相同。WMI只是提供了另一种安排任务的方式。
    你可以通过WMI使用 "Win32_ScheduledJob "类中的 "Create "方法创建一个新的任务。

    然而,"Win32_ScheduledJob "WMI类被设计为与AT命令一起使用,而AT命令从Windows 8开始被废弃。

    在Windows 8和更高版本中,只有当注册表键 "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Schedule\Configuration "有一个REG_DWORD类型的值 "EnableAt"="1",你才能用WMI创建预定工作。因此,这种技术不太可能在“正常环境下”成功使用。
    代码样本(VB)
    1. strComputer = "."
    2. Set objWMIService = GetObject("winmgmts:" & "{impersonationLevel=Impersonate}!\" & strComputer & "\root\cimv2")
    3. Set objSWbemDateTime = CreateObject("WbemScripting.SWbemDateTime")
    4. objSWbemDateTime.SetVarDate(DateAdd("n", 1, Now()))
    5. Set objNewJob = objWMIService.Get("Win32_ScheduledJob")
    6. errJobCreate = objNewJob.Create("malware.exe", objSWbemDateTime.Value, False, , , True, "MaliciousJob")
    复制代码

    识别标志:
    如果用第2个参数 "Win32_ScheduledJob "和第3个参数 "Create "调用以下函数之一:
    • IWbemServices_ExecMethod(..., BSTR("Win32_ScheduledJob"), BSTR("Create"), ...)
    • IWbemServices_ExecMethodAsync(..., BSTR("Win32_ScheduledJob"), BSTR("Create"), ...)

    则表明该应用程序试图使用规避技术。
    反制措施:
    使用内核模式的监控器,用PsSetCreateProcessNotifyRoutineEx注册进程创建时的回调。
    3. 检查最后的启动时间
    如果在从快照恢复虚拟机后立即查询最后启动时间,WMI 数据库可能包含创建虚拟机快照时保存的值。如果快照是一年前创建的,即使沙盒更新了最后的启动时间,计算出的系统正常运行时间也是一年。

    这一事实可以用来检测从快照中恢复的虚拟机。另外,最后一次启动时间的任何异常情况都可以作为沙盒指标:
    • 系统正常运行时间太长(几个月甚至几年)。
    • 系统正常运行时间太短(少于几分钟)。
    • 使用其它方法获得的最后一次启动时间与使用WMI获得的最后一次启动时间不同

    代码样本 (VB):
    1. strComputer = "."
    2. Set objWMIService = GetObject("winmgmts:" & "{impersonationLevel=impersonate}!\" & strComputer & "\root\cimv2")
    3. Set colOperatingSystems = objWMIService.ExecQuery ("Select * from Win32_OperatingSystem")

    4. For Each objOS in colOperatingSystems
    5.     dtmBootup = objOS.LastBootUpTime
    6.     dtmLastBootUpTime = WMIDateStringToDate(dtmBootup)
    7.     dtmSystemUptime = DateDiff("n", dtmLastBootUpTime, Now)
    8.     Wscript.Echo "System uptime minutes: " & dtmSystemUptime
    9. Next

    10. Function WMIDateStringToDate(dtm)
    11.     WMIDateStringToDate =  CDate(Mid(dtm, 5, 2) & "/" & _
    12.         Mid(dtm, 7, 2) & "/" & Left(dtm, 4) & " " & Mid (dtm, 9, 2) & ":" & _
    13.         Mid(dtm, 11, 2) & ":" & Mid(dtm, 13, 2))
    14. End Function
    复制代码

    代码样本取自微软文档
    识别标志:
    如果用第3个参数BSTR("Win32_OperatingSystem")调用以下函数:
    • IWbemServices_ExecQuery(..., BSTR("Win32_OperatingSystem"), ...)

    那么它可能是应用程序试图使用规避技术的一个指标。
    反制措施:
    • 调整KeBootTime值
    • 在调整KeBootTime值后,重置WMI存储库或重新启动 "winmgmt "服务

    4. 检查网络适配器的最后重置时间
    我们需要检查是否有任何适配器在很久以前被重置过。这可能表明应用程序是在一个从快照恢复的虚拟机中运行。
    代码样本 (VB):
    1. strComputer = "."
    2. Set objWMIService = GetObject("winmgmts:" & "{impersonationLevel=impersonate}!\" & strComputer & "\root\cimv2")
    3. Set colOperatingSystems = objWMIService.ExecQuery ("Select * from Win32_NetworkAdapter")

    4. For Each objOS in colNetworkAdapters
    5.     dtmLastReset = objOS.TimeOfLastReset
    6.     dtmLastResetTime = WMIDateStringToDate(dtmLastReset)  'WMIDateStringToDate function from the previous example
    7.     dtmAdapterUptime = DateDiff("n", dtmLastResetTime, Now)
    8.     Wscript.Echo "Adapter uptime minutes: " & dtmAdapterUptime
    9. Next
    复制代码

    识别标志:
    如果用第3个参数BSTR("Win32_OperatingSystem")调用以下函数:
    • IWbemServices_ExecQuery(..., BSTR("Win32_NetworkAdapter"), ...)

    那么它可能是应用程序试图使用规避技术的一个指标。
    反制措施:
    • 确保网络适配器有足够的最后重置时间
    • 重置WMI资源库或重启 "winmgmt "服务

    反制措施
    反措施在上述适当的分节中提出。
    归功于


    您需要登录后才可以回帖 登录 | 注册

    本版积分规则

    红盟社区--红客联盟 

    Processed in 0.057294 second(s), 21 queries.

    站点统计| 举报| Archiver| 手机版| 黑屋 |   

    备案号:冀ICP备20006029号-1 Powered by HUC © 2001-2021 Comsenz Inc.

    手机扫我进入移动触屏客户端

    关注我们可获取更多热点资讯

    Honor accompaniments. theme macfee

    快速回复 返回顶部 返回列表