使用 WMI 查询安全软件信息

2024-02-08 06:36

本文主要是介绍使用 WMI 查询安全软件信息,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

在这篇文章中,我们将详细介绍如何使用 Windows Management Instrumentation (WMI) API 来查询当前计算机上安装的安全软件的基本信息。我们将分析代码的各个部分,并解释每个步骤所涉及的技术和原理。

一、什么是 WMI?

WMI 是 Windows Management Instrumentation 的缩写,是微软提供的用于管理 Windows 系统的一种技术。它提供了一种标准的接口,允许开发者通过编程方式获取和操作 Windows 操作系统的各种信息,包括硬件、软件、网络配置等。WMI 是基于 CIM(Common Information Model)标准的实现,它使用了面向对象的方式来组织和表示系统的信息。

二、相关函数解释

以下是代码中使用的一些函数以及它们的参数的解释,摘抄了 MSDN 文档的相关内容:

CoInitializeEx

HRESULT CoInitializeEx(LPVOID pvReserved,DWORD  dwCoInit
);
  • pvReserved:保留参数,必须为 NULL
  • dwCoInit:初始化标志,指定了线程的并发模型。

 详情请参阅:CoInitializeEx function (combaseapi.h)

CoCreateInstance

HRESULT CoCreateInstance(REFCLSID  rclsid,LPUNKNOWN pUnkOuter,DWORD     dwClsContext,REFIID    riid,LPVOID    *ppv
);
  • rclsid:类标识符(CLSID)。
  • pUnkOuter:用于控制对象的外部创建的指针。通常为 NULL
  • dwClsContext:指定服务器的执行环境。
  • riid:接口标识符(IID)。
  • ppv:接收指向所请求接口的指针的地址。

详情请参阅:CoCreateInstance function (combaseapi.h)

CoSetProxyBlanket

HRESULT CoSetProxyBlanket(IUnknown                 *pProxy,DWORD                    dwAuthnSvc,DWORD                    dwAuthzSvc,OLECHAR                  *pServerPrincName,DWORD                    dwAuthnLevel,DWORD                    dwImpLevel,RPC_AUTH_IDENTITY_HANDLE pAuthInfo,DWORD                    dwCapabilities
);
  • pProxy:指向要设置代理参数的接口指针的指针。
  • dwAuthnSvc:身份验证服务。
  • dwAuthzSvc:授权服务。
  • pServerPrincName:服务器的主体名称。
  • dwAuthnLevel:身份验证级别。
  • dwImpLevel:实现级别。
  • pAuthInfo:身份验证信息。
  • dwCapabilities:代理的功能标志。

 详情请参阅:CoSetProxyBlanket function (combaseapi.h)

IWbemServices::ExecQuery

HRESULT ExecQuery([in]          const BSTR   strQueryLanguage,[in]          const BSTR   strQuery,[in]          long         lFlags,[in]          IWbemContext *pCtx,[out]         IEnumWbemClassObject **ppEnum
);
  • strQueryLanguage:查询语言,例如 "WQL"。
  • strQuery:查询字符串。
  • lFlags:标志,指定查询的行为。
  • pCtx:指向 WMI 上下文对象的指针。
  • ppEnum:接收指向查询结果集的指针的地址。

 详情请参阅:IWbemServices::ExecQuery method (wbemcli.h)

IEnumWbemClassObject::Next

HRESULT Next([in]  LONG            lTimeout,[in]  ULONG           uCount,[out] IWbemClassObject **apObj,[out] ULONG           *puReturned
);
  • lTimeout:超时值,以毫秒为单位,或者可以指定为 WBEM_INFINITE 以表示无限超时。
  • uCount:要检索的对象数。
  • apObj:接收对象的数组。
  • puReturned:实际返回的对象数。

 详情请参阅:IEnumWbemClassObject::Next method (wbemcli.h)

这些函数和参数提供了在代码中使用 WMI API 时的基本操作和配置。通过了解这些函数的作用和参数的含义,可以更好地理解代码的功能和实现原理。

三、代码解析

让我们逐步分析代码并解释其中的各个部分。

3.1 初始化 COM

HRESULT hres = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);

这一行代码初始化了 COM(Component Object Model)库,COM 是一种微软提供的用于组件化软件的技术,它允许不同的组件通过接口进行通信和交互。

3.2 创建 WMI Locator

IWbemLocator* pLoc = NULL;
hres = CoCreateInstance(CLSID_WbemLocator, 0, CLSCTX_INPROC_SERVER, IID_IWbemLocator, (LPVOID*)&pLoc);

这段代码创建了一个 WMI Locator 对象,它是用于定位和连接 WMI 服务的接口。 CLSID_WbemLocator 是 WMI Locator 的类标识符,IID_IWbemLocator 是 WMI Locator 的接口标识符。

3.3 连接 WMI 服务

IWbemServices* pSvc = NULL;
hres = pLoc->ConnectServer(_bstr_t(L"ROOT\\SecurityCenter2"), NULL, NULL, 0, NULL, 0, 0, &pSvc);

这段代码连接到了 WMI 服务,并指定了要连接的命名空间为 ROOT\SecurityCenter2。在这个命名空间中,我们可以查询关于安全中心的信息,包括安装的安全软件信息。

3.4 设置代理参数

hres = CoSetProxyBlanket(pSvc,                        RPC_C_AUTHN_WINNT,           RPC_C_AUTHZ_NONE,            NULL,                        RPC_C_AUTHN_LEVEL_CALL,      RPC_C_IMP_LEVEL_IMPERSONATE, NULL,                        EOAC_NONE                    
);

这段代码设置了用于 WMI 服务的代理参数,包括身份验证方式、权限级别等。

3.5 执行查询

hres = pSvc->ExecQuery(bstr_t("WQL"),bstr_t("SELECT * FROM AntiVirusProduct"),WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY,NULL,&pEnumerator
);

这段代码执行了一个 WMI 查询,查询的语句是 “SELECT * FROM AntiVirusProduct”,表示查询 AntiVirusProduct 类的所有实例。

3.6 处理查询结果

while (pEnumerator)
{HRESULT hr = pEnumerator->Next(WBEM_INFINITE, 1, &pclsObj, &uReturn);if (0 == uReturn){break;}// 获取属性值并输出// ...
}

这段代码处理了查询结果,逐个获取实例的属性值并输出。

四、完整代码和测试

完整代码如下所示:

#include <iostream>
#include <comdef.h>
#include <Wbemidl.h># pragma comment(lib, "wbemuuid.lib")using namespace std;int main(int argc, char** argv)
{setlocale(LC_ALL, ".utf8");// Initialize COM. ------------------------------------------ HRESULT hres = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);if (FAILED(hres)){wcout << "CoInitializeEx() failure:" << hex << (unsigned long)hres;return 0;}// Obtain the initial locator to Windows Management // on a particular host computer. IWbemLocator* pLoc = NULL;hres = CoCreateInstance(CLSID_WbemLocator, 0, CLSCTX_INPROC_SERVER, IID_IWbemLocator, (LPVOID*)&pLoc);if (FAILED(hres)){CoUninitialize();wcout << "CreateInstance failure:" << hex << (unsigned long)hres;return 0;}// Connect to WMI through the IWbemLocator::ConnectServer method // Connect to the local ROOT\CIMV2 namespace // and obtain pointer pSvc to make IWbemServices calls. IWbemServices* pSvc = NULL;hres = pLoc->ConnectServer(_bstr_t(L"ROOT\\SecurityCenter2"), NULL, NULL, 0, NULL, 0, 0, &pSvc);if (FAILED(hres)){pLoc->Release();CoUninitialize();wcout << "ConnectServer() failure:" << hex << (unsigned long)hres;return 0;}cout << "Connected to ROOT//SecurityCenter2 WMI namespace" << endl;// Step 5: --------------------------------------------------// Set security levels on the proxy -------------------------hres = CoSetProxyBlanket(pSvc,                        // Indicates the proxy to setRPC_C_AUTHN_WINNT,           // RPC_C_AUTHN_xxxRPC_C_AUTHZ_NONE,            // RPC_C_AUTHZ_xxxNULL,                        // Server principal name RPC_C_AUTHN_LEVEL_CALL,      // RPC_C_AUTHN_LEVEL_xxx RPC_C_IMP_LEVEL_IMPERSONATE, // RPC_C_IMP_LEVEL_xxxNULL,                        // client identityEOAC_NONE                    // proxy capabilities );if (FAILED(hres)){cout << "Could not set proxy blanket. Error code = 0x"<< hex << hres << endl;pSvc->Release();pLoc->Release();CoUninitialize();cin.get();return 1;               // Program has failed.}// Step 6: --------------------------------------------------// Use the IWbemServices pointer to make requests of WMI ----// For example, get the name of the operating systemIEnumWbemClassObject* pEnumerator = NULL;hres = pSvc->ExecQuery(bstr_t("WQL"),bstr_t("SELECT * FROM AntiVirusProduct"),WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY,NULL,&pEnumerator);if (FAILED(hres)){cout << "Query for operating system name failed."<< " Error code = 0x"<< hex << hres << endl;pSvc->Release();pLoc->Release();CoUninitialize();cin.get();return 1;               // Program has failed.}// Step 7: -------------------------------------------------// Get the data from the query in step 6 -------------------IWbemClassObject* pclsObj;ULONG uReturn = 0;while (pEnumerator){HRESULT hr = pEnumerator->Next(WBEM_INFINITE, 1,&pclsObj, &uReturn);if (0 == uReturn){break;}VARIANT vtProp{};// Get the value of the Name propertyhr = pclsObj->Get(L"displayName", 0, &vtProp, 0, 0);wcout << "AntiVirus  Product displayName : " << vtProp.bstrVal << endl;hr = pclsObj->Get(L"companyName", 0, &vtProp, 0, 0);wcout << "AntiVirus  Product companyName : " << vtProp.bstrVal << endl;hr = pclsObj->Get(L"pathToSignedProductExe", 0, &vtProp, 0, 0);wcout << "AntiVirus  Product pathToSignedProductExe : " << vtProp.bstrVal << endl;hr = pclsObj->Get(L"versionNumber", 0, &vtProp, 0, 0);wcout << "AntiVirus  Product versionNumber : " << vtProp.bstrVal << endl;VariantClear(&vtProp);pclsObj->Release();}// Cleanup// ========pSvc->Release();pLoc->Release();pEnumerator->Release();//pclsObj->Release();CoUninitialize();cin.get();return 0;   // Program successfully completed.
}

测试过程的截图如下所示:

测试结果截图

总结

通过使用 WMI API,我们可以方便地查询和管理 Windows 系统的各种信息。在本文中,我们介绍了如何使用 WMI 查询当前计算机上安装的安全软件的基本信息,包括初始化 COM、连接 WMI 服务、执行查询以及处理查询结果等步骤。通过深入了解 WMI API 的使用,我们可以更好地理解和利用 Windows 系统的管理功能。


发布于:2024.02.07,更新于:2024.02.07

这篇关于使用 WMI 查询安全软件信息的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/690176

相关文章

鸿蒙中@State的原理使用详解(HarmonyOS 5)

《鸿蒙中@State的原理使用详解(HarmonyOS5)》@State是HarmonyOSArkTS框架中用于管理组件状态的核心装饰器,其核心作用是实现数据驱动UI的响应式编程模式,本文给大家介绍... 目录一、@State在鸿蒙中是做什么的?二、@Spythontate的基本原理1. 依赖关系的收集2.

Python基础语法中defaultdict的使用小结

《Python基础语法中defaultdict的使用小结》Python的defaultdict是collections模块中提供的一种特殊的字典类型,它与普通的字典(dict)有着相似的功能,本文主要... 目录示例1示例2python的defaultdict是collections模块中提供的一种特殊的字

C++ Sort函数使用场景分析

《C++Sort函数使用场景分析》sort函数是algorithm库下的一个函数,sort函数是不稳定的,即大小相同的元素在排序后相对顺序可能发生改变,如果某些场景需要保持相同元素间的相对顺序,可使... 目录C++ Sort函数详解一、sort函数调用的两种方式二、sort函数使用场景三、sort函数排序

Java String字符串的常用使用方法

《JavaString字符串的常用使用方法》String是JDK提供的一个类,是引用类型,并不是基本的数据类型,String用于字符串操作,在之前学习c语言的时候,对于一些字符串,会初始化字符数组表... 目录一、什么是String二、如何定义一个String1. 用双引号定义2. 通过构造函数定义三、St

Pydantic中Optional 和Union类型的使用

《Pydantic中Optional和Union类型的使用》本文主要介绍了Pydantic中Optional和Union类型的使用,这两者在处理可选字段和多类型字段时尤为重要,文中通过示例代码介绍的... 目录简介Optional 类型Union 类型Optional 和 Union 的组合总结简介Pyd

Vue3使用router,params传参为空问题

《Vue3使用router,params传参为空问题》:本文主要介绍Vue3使用router,params传参为空问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐... 目录vue3使用China编程router,params传参为空1.使用query方式传参2.使用 Histo

使用Python自建轻量级的HTTP调试工具

《使用Python自建轻量级的HTTP调试工具》这篇文章主要为大家详细介绍了如何使用Python自建一个轻量级的HTTP调试工具,文中的示例代码讲解详细,感兴趣的小伙伴可以参考一下... 目录一、为什么需要自建工具二、核心功能设计三、技术选型四、分步实现五、进阶优化技巧六、使用示例七、性能对比八、扩展方向建

使用Python实现一键隐藏屏幕并锁定输入

《使用Python实现一键隐藏屏幕并锁定输入》本文主要介绍了使用Python编写一个一键隐藏屏幕并锁定输入的黑科技程序,能够在指定热键触发后立即遮挡屏幕,并禁止一切键盘鼠标输入,这样就再也不用担心自己... 目录1. 概述2. 功能亮点3.代码实现4.使用方法5. 展示效果6. 代码优化与拓展7. 总结1.

Mybatis 传参与排序模糊查询功能实现

《Mybatis传参与排序模糊查询功能实现》:本文主要介绍Mybatis传参与排序模糊查询功能实现,本文通过实例代码给大家介绍的非常详细,感兴趣的朋友跟随小编一起看看吧... 目录一、#{ }和${ }传参的区别二、排序三、like查询四、数据库连接池五、mysql 开发企业规范一、#{ }和${ }传参的

使用Python开发一个简单的本地图片服务器

《使用Python开发一个简单的本地图片服务器》本文介绍了如何结合wxPython构建的图形用户界面GUI和Python内建的Web服务器功能,在本地网络中搭建一个私人的,即开即用的网页相册,文中的示... 目录项目目标核心技术栈代码深度解析完整代码工作流程主要功能与优势潜在改进与思考运行结果总结你是否曾经