欢迎来到 黑吧安全网 聚焦网络安全前沿资讯,精华内容,交流技术心得!

VC之获得系统安装的反病毒软件[Using WMI in C++]

来源:转载 作者:佚名 时间:2010-05-18 TAG: 我要投稿

在学习本文前,你需要一点点的VBS基础,WMI了解常识,COM接口皮毛就行。

今天的问题是,如何获得系统中安装的杀毒软件?有人会说遍历注册表之类的。其实用不着这么麻烦。每个正式的AV(Anti-Virus)软件,都要向系统注册自己。通过查看WMI中的\root\SecurityCenter这个名称空间,我们就能知道其中装了那些反病毒产品。

我们来看一段Vbs代码:

strComputer = "." 
Set objComputer = CreateObject("Shell.LocalMachine")  
Set oWMI = GetObject("winmgmts:\\" & strComputer & "\root\SecurityCenter")  
Set colAV = oWMI.ExecQuery("Select * from AntiVirusProduct")  
  For Each objAntiVirusProduct In colAV  
   If IsNull(objAntiVirusProduct.instanceGuid) Then 
    strSubject = "Anti-virus is not running on " & objComputer.MachineName  
    strTextbody = "You will need to check on " & objComputer.MachineName   
    Call SmtpServer    
   Else 
    strCompany = objAntiVirusProduct.companyName  
    strAV = objAntiVirusProduct.displayName  
    strScanning = objAntiVirusProduct.onAccessScanningEnabled  
    strUptodate = objAntiVirusProduct.productUptoDate 
strComputer = "."
Set objComputer = CreateObject("Shell.LocalMachine")
Set oWMI = GetObject("winmgmts:\\" & strComputer & "\root\SecurityCenter")
Set colAV = oWMI.ExecQuery("Select * from AntiVirusProduct")
  For Each objAntiVirusProduct In colAV
   If IsNull(objAntiVirusProduct.instanceGuid) Then
    strSubject = "Anti-virus is not running on " & objComputer.MachineName
    strTextbody = "You will need to check on " & objComputer.MachineName
    Call SmtpServer 
   Else
    strCompany = objAntiVirusProduct.companyName
    strAV = objAntiVirusProduct.displayName
    strScanning = objAntiVirusProduct.onAccessScanningEnabled
    strUptodate = objAntiVirusProduct.productUptoDate

如果以上代码你觉得很难懂的话,那么不推荐你继续看下去,请稍微补习下Vbs和Wmi相关的知识。

Select * from AntiVirusProduct是一条WQL语句,用来查询所有的反病毒软件,并返回一个集合。我们用WMITools里面的WMI CIM Studio进行查看下\root\SecurityCenter这个名称空间里面有哪些Win32 Class

 


 在左边,看到了么,AntiVirusProduct。还有FireWallProduct,防火墙产品,本机没有防火墙,就用查看反病毒软件来做说明吧。

右边的呢,都是AntiVirusProduct这个类的属性(Properties)。里面有产品名,产品公司名,版本号等等。那么我现在需要的,就是通过C++获取到和Vbs一样的信息。上面的Vbs脚本不知道你执行过了么?

我们接下来看C++代码

#define _WIN32_DCOM  
 
#include <iostream>  
 
using namespace std;  
 
#include <comdef.h>  
 
#include <Wbemidl.h>  
 
 
# pragma comment(lib, "wbemuuid.lib")  
 
 
int main(int argc, char **argv)  
 
{  
 
    HRESULT hres;  
 
 
    // Step 1: --------------------------------------------------  
 
    // Initialize COM. ------------------------------------------  
 
 
    hres =  CoInitializeEx(0, COINIT_MULTITHREADED);   
 
    if (FAILED(hres))  
 
    {  
 
        cout << "Failed to initialize COM library. Error code = 0x"   
 
            << hex << hres << endl;  
 
        return 1;                  // Program has failed.  
 
    }  
 
 
    // Step 2: --------------------------------------------------  
 
    // Set general COM security levels --------------------------  
 
 
    hres =  CoInitializeSecurity(  
 
        NULL,   
 
        -1,                          // COM authentication  
 
        NULL,                        // Authentication services  
 
        NULL,                        // Reserved  
 
        RPC_C_AUTHN_LEVEL_DEFAULT,   // Default authentication   
 
        RPC_C_IMP_LEVEL_IMPERSONATE, // Default Impersonation    
 
        NULL,                        // Authentication info  
 
        EOAC_NONE,                   // Additional capabilities   
 
        NULL                         // Reserved  
 
        );            
 
    if (FAILED(hres))  
 
    {  
 
        cout << "Failed to initialize security. Error code = 0x"   
 
            << hex << hres << endl;  
 
        CoUninitialize();  
 
        return 1;                    // Program has failed.  
 
    }  
 
 
    // Step 3: ---------------------------------------------------  
 
    // Obtain the initial locator to WMI -------------------------  
 
 
    IWbemLocator *pLoc = NULL;  
 
 
    hres = CoCreateInstance(  
 
        CLSID_WbemLocator,               
 
        0,   
 
        CLSCTX_INPROC_SERVER,   
 
        IID_IWbemLocator, (LPVOID *) &pLoc);  
 
 
    if (FAILED(hres))  
 
    {  
 
        cout << "Failed to create IWbemLocator object." 
 
            << " Err code = 0x" 
 
            << hex << hres << endl;  
 
        CoUninitialize();  
 
        return 1;                 // Program has failed.  
 
    }  
 
 
    // Step 4: -----------------------------------------------------  
 
    // Connect to WMI through the IWbemLocator::ConnectServer method  
 
 
    IWbemServices *pSvc = NULL;  
 
    // Connect to the root\SecurityCenter namespace with  
 
    // the current user and obtain pointer pSvc  
 
    // to make IWbemServices calls.  
 
    hres = pLoc->ConnectServer(  
 
         _bstr_t(L"ROOT\\SecurityCenter"), // Object path of WMI namespace  
 
         NULL,                    // User name. NULL = current user  
 
         NULL,                    // User password. NULL = current  
 
         0,                       // Locale. NULL indicates current  
 
         NULL,                    // Security flags.  
 
         0,                       // Authority (e.g. Kerberos)  
 
         0,                       // Context object   
 
         &pSvc                    // pointer to IWbemServices proxy  
 
         );  
 
 
    if (FAILED(hres))  
 
    {  
 
        cout << "Could not connect. Error code = 0x"   
 
             << hex << hres << endl;  
 
        pLoc->Release();       
 
        CoUninitialize();  
 
        return 1;                // Program has failed.  
 
    }  
 
 
    cout << "Connected to ROOT\\SecurityCenter WMI namespace" << endl;   
 
    // Step 5: --------------------------------------------------  
 
    // Set security levels on the proxy -------------------------  
 
 
    hres = CoSetProxyBlanket(  
 
       pSvc,                        // Indicates the proxy to set  
 
       RPC_C_AUTHN_WINNT,           // RPC_C_AUTHN_xxx  
 
       RPC_C_AUTHZ_NONE,            // RPC_C_AUTHZ_xxx  
 
       NULL,                        // Server principal name   
 
       RPC_C_AUTHN_LEVEL_CALL,      // RPC_C_AUTHN_LEVEL_xxx   
 
       RPC_C_IMP_LEVEL_IMPERSONATE, // RPC_C_IMP_LEVEL_xxx  
 
       NULL,                        // client identity  
 
       EOAC_NONE                    // proxy capabilities   
 
    );  
 
 
    if (FAILED(hres))  
 
    {  
 
        cout << "Could not set proxy blanket. Error code = 0x"   
 
            << hex << hres << endl;  
 
        pSvc->Release();  
 
        pLoc->Release();       
 
        CoUninitialize();  
 
        return 1;               // Program has failed.  
 
    }  
 
 
    // Step 6: --------------------------------------------------  
 
    // Use the IWbemServices pointer to make requests of WMI ----  
 
 
    // For example, get the name of the operating system  
 
    IEnumWbemClassObject* 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();  
 
        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 property  
 
        hr = pclsObj->Get(L"displayName", 0, &vtProp, 0, 0);  
 
        wcout << "AV  Product displayName : " << vtProp.bstrVal << endl;  
 
        hr = pclsObj->Get(L"companyName", 0, &vtProp, 0, 0);  
 
        wcout << "AV  Product companyName : " << vtProp.bstrVal << endl;  
 
        hr = pclsObj->Get(L"pathToSignedProductExe", 0, &vtProp, 0, 0);  
 
        wcout << "AV  Product pathToSignedProductExe : " << vtProp.bstrVal << endl;           
 
        hr = pclsObj->Get(L"versionNumber", 0, &vtProp, 0, 0);  
 
        wcout << "AV  Product versionNumber : " << vtProp.bstrVal << endl;             
 
        VariantClear(&vtProp);   
 
        pclsObj->Release();  
 
    }  
 
 
    // Cleanup  
 
    // ========  
 
 
    pSvc->Release();  
 
    pLoc->Release();  
 
    pEnumerator->Release();  
 
    //pclsObj->Release();  
 
    CoUninitialize();  
 
 
    return 0;   // Program successfully completed.  
 

#define _WIN32_DCOM

#include <iostream>

using namespace std;

#include <comdef.h>

#include <Wbemidl.h>


# pragma comment(lib, "wbemuuid.lib")


int main(int argc, char **argv)

{

    HRESULT hres;


    // Step 1: --------------------------------------------------

    // Initialize COM. ------------------------------------------


    hres =  CoInitializeEx(0, COINIT_MULTITHREADED);

    if (FAILED(hres))

    {

        cout << "Failed to initialize COM library. Error code = 0x"

            << hex << hres << endl;

        return 1;                  // Program has failed.

    }


    // Step 2: --------------------------------------------------

    // Set general COM security levels --------------------------


    hres =  CoInitializeSecurity(

        NULL,

        -1,                          // COM authentication

        NULL,                        // Authentication services

        NULL,                        // Reserved

        RPC_C_AUTHN_LEVEL_DEFAULT,   // Default authentication

        RPC_C_IMP_LEVEL_IMPERSONATE, // Default Impersonation 

        NULL,                        // Authentication info

        EOAC_NONE,                   // Additional capabilities

        NULL                         // Reserved

        );         

    if (FAILED(hres))

    {

        cout << "Failed to initialize security. Error code = 0x"

            << hex << hres << endl;

        CoUninitialize();

        return 1;                    // Program has failed.

    }


    // Step 3: ---------------------------------------------------

    // Obtain the initial locator to WMI -------------------------


    IWbemLocator *pLoc = NULL;


    hres = CoCreateInstance(

        CLSID_WbemLocator,            

        0,

        CLSCTX_INPROC_SERVER,

        IID_IWbemLocator, (LPVOID *) &pLoc);


    if (FAILED(hres))

    {

        cout << "Failed to create IWbemLocator object."

            << " Err code = 0x"

            << hex << hres << endl;

        CoUninitialize();

        return 1;                 // Program has failed.

    }


    // Step 4: -----------------------------------------------------

    // Connect to WMI through the IWbemLocator::ConnectServer method


    IWbemServices *pSvc = NULL;

    // Connect to the root\SecurityCenter namespace with

    // the current user and obtain pointer pSvc

    // to make IWbemServices calls.

    hres = pLoc->ConnectServer(

         _bstr_t(L"ROOT\\SecurityCenter"), // Object path of WMI namespace

         NULL,                    // User name. NULL = current user

         NULL,                    // User password. NULL = current

         0,                       // Locale. NULL indicates current

         NULL,                    // Security flags.

         0,                       // Authority (e.g. Kerberos)

         0,                       // Context object

         &pSvc                    // pointer to IWbemServices proxy

         );


    if (FAILED(hres))

    {

        cout << "Could not connect. Error code = 0x"

             << hex << hres << endl;

        pLoc->Release();    

        CoUninitialize();

        return 1;                // Program has failed.

    }


    cout << "Connected to ROOT\\SecurityCenter WMI namespace" << endl;

    // Step 5: --------------------------------------------------

    // Set security levels on the proxy -------------------------


    hres = CoSetProxyBlanket(

       pSvc,                        // Indicates the proxy to set

       RPC_C_AUTHN_WINNT,           // RPC_C_AUTHN_xxx

       RPC_C_AUTHZ_NONE,            // RPC_C_AUTHZ_xxx

       NULL,                        // Server principal name

       RPC_C_AUTHN_LEVEL_CALL,      // RPC_C_AUTHN_LEVEL_xxx

       RPC_C_IMP_LEVEL_IMPERSONATE, // RPC_C_IMP_LEVEL_xxx

       NULL,                        // client identity

       EOAC_NONE                    // proxy capabilities

    );


    if (FAILED(hres))

    {

        cout << "Could not set proxy blanket. Error code = 0x"

            << hex << hres << endl;

        pSvc->Release();

        pLoc->Release();    

        CoUninitialize();

        return 1;               // Program has failed.

    }


    // Step 6: --------------------------------------------------

    // Use the IWbemServices pointer to make requests of WMI ----


    // For example, get the name of the operating system

    IEnumWbemClassObject* 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();

        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 property

        hr = pclsObj->Get(L"displayName", 0, &vtProp, 0, 0);

        wcout << "AV  Product displayName : " << vtProp.bstrVal << endl;

        hr = pclsObj->Get(L"companyName", 0, &vtProp, 0, 0);

        wcout << "AV  Product companyName : " << vtProp.bstrVal << endl;

        hr = pclsObj->Get(L"pathToSignedProductExe", 0, &vtProp, 0, 0);

        wcout << "AV  Product pathToSignedProductExe : " << vtProp.bstrVal << endl;        

        hr = pclsObj->Get(L"versionNumber", 0, &vtProp, 0, 0);

        wcout << "AV  Product versionNumber : " << vtProp.bstrVal << endl;          

        VariantClear(&vtProp);

        pclsObj->Release();

    }


    // Cleanup

    // ========


    pSvc->Release();

    pLoc->Release();

    pEnumerator->Release();

    //pclsObj->Release();

    CoUninitialize();


    return 0;   // Program successfully completed.

}
 
这份代码是我从MSDN中的C++ WMI例子中抠出来然后针对具体情况进行修改,所以并不能算是真正意义上的原创。但是呢,这个教材文章确实是原创的 (Tr0j4n *_*)
运行效果:


注释大部分都是微软加的,所以非常详细。它本来是用来查询ROOT\\CIMV2这个名称空间中的Win32_OperatingSystem类,然后获得操作系统的名称。说实话,用C++调用WMI就为了得到操作系统名称,这简直是一种浪费,简单的Win32 API调用就能实现了。所以我把它改成了查看本机的反病毒产品的代码。

C++操作WMI执行WQL返回,其实就是一个模板,所以我认为大家有掌握的必要。而且可以举一反三。

Step1:Initialize COM parameters with a call to CoInitializeEx.
For more information, see Initializing COM for a WMI Application.

Step2:Initialize COM process security by calling CoInitializeSecurity.
Windows 2000:  Specify the default authentication credentials for a user by using a SOLE_AUTHENTICATION_LIST structure in the pAuthList parameter of CoInitializeSecurity.
For more information, see Setting the Default Process Security Level Using C++.

Step3:Obtain the initial locator to WMI by calling CoCreateInstance.
For more information, see Creating a Connection to a WMI Namespace.

Step4:Obtain a pointer to IWbemServices for the root\cimv2 namespace on the local computer by calling IWbemLocator::ConnectServer. To connect to a remote computer, see Example: Getting WMI Data from a Remote Computer.
For more information, see Creating a Connection to a WMI Namespace.

Step5:Set IWbemServices proxy security so the WMI service can impersonate the client by calling CoSetProxyBlanket.
For more information, see Setting the Security Levels on a WMI Connection.

Step6:Use the IWbemServices pointer to make requests of WMI. This example executes a query for the name of the operating system by calling IWbemServices::ExecQuery.
The following WQL query is one of the method arguments.

SELECT * FROM Win32_OperatingSystem   这就是WQL语句

The result of this query is stored in an IEnumWbemClassObject pointer. This allows the data objects from the query to be retrieved semisynchronously with the IEnumWbemClassObject interface. For more information, see Enumerating WMI. For getting the data asynchronously, see Example: Getting WMI Data from the Local Computer Asynchronously.
For more information about making requests to WMI, see Manipulating Class and Instance Information, Querying WMI, and Calling a Method.

Step7:Get and display the data from the WQL query. The IEnumWbemClassObject pointer is linked to the data objects that the query returned, and the data objects can be retrieved with the IEnumWbemClassObject::Next method. This method links the data objects to an IWbemClassObject pointer that is passed into the method. Use the IWbemClassObject::Get method to get the desired information from the data objects.

以上解释出自MSDN。MSDN用得好,对编程能力是一个很大的帮助。如果觉得英语不行,只能去恶补咯。

其实,关键在4,6,7步。第四步弄的是名称空间,第六步写的是WQL语句,第七步获得返回值。至于第七步。你对比那个While循环中的C++语句,和文章开头的Vbs语句中的For each对比,你看出了什么名堂了吗?

Vbs通过For each枚举类实例,而C++中通过IEnumWbemClassObject接口指针。

如何获得IEnumWbemClassObject接口指针呢?微软告诉我们有4种方法。我用的是第一种,执行一个WQL语句,获得一个AntiVirusProduct类实例的枚举接口指针。

IWbemServices::ExecQuery
IWbemServices::CreateInstanceEnum
IWbemServices::CreateClassEnum
IWbemServices::ExecNotificationQuery

我是怎么实现变量的呢?我用的是枚举接口指针的Next方法,其实它还有别的方法,比如Skip跳过,NextAsync异步下一个。

今后有什么WMI的代码想在VC中实现,只要按这个模板一套用,属于你自己的C++ WMI代码就出炉的。对C++ WMI编程感兴趣的同学,可以参考 这里

本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/Tr0j4n/archive/2010/01/19/5214384.aspx

【声明】:黑吧安全网(http://www.myhack58.com)登载此文出于传递更多信息之目的,并不代表本站赞同其观点和对其真实性负责,仅适于网络安全技术爱好者学习研究使用,学习中请遵循国家相关法律法规。如有问题请联系我们,联系邮箱admin@myhack58.com,我们会在最短的时间内进行处理。
  • 最新更新
    • 相关阅读
      • 本类热门
        • 最近下载