이쿠의 슬기로운 개발생활

함께 성장하기 위한 보안 개발자 EverNote 내용 공유

코딩/C and C++

C++ WMI library사용

이쿠우우 2021. 12. 22. 11:43
반응형

 

 

C++ WMI library사용

 
 

목적

C++로 Windows OS 종류를 확인해야 했었음.
방법을 찾다가 WMI에 대해 알게되었음.
WMI에 대해 알아보도록 함.
 

 

 

WMI(Windows Management Instrumentation) 란?

 
WMI란 Windows Management Instrumentation으로
Windows에 대한 Microsoft의 주요 관리 기술이라고 불려짐.
 
MS에서 확인해보면 WMI 설명이 약간 복잡하게 되어있는데
요약해서 중점만 설명하자면
WMI는 원격으로 Windows host의 정보를 확인 할 수 있는 tool임.
알아보고자 하는 windows host의 network 정보, host name, 계정 정보 등 각종 windows 리소스를 확인 할 수 있음.
 
WMI는 host의 거의 모든 정보를 알아낼 수 있는 강력한 tool로 
좋게 사용된다면 매우 편리하지만
강력한 tool인 만큼 악성코드에도 많이 사용된다함.
 

 

 

Windows WMI Namespace 목록 확인.

 
주의 : 관리자 권한으로 실행해야함. 일반권한으로하면 일부 namespace만 나옴.
 
[명령어]
Get-WMIObject -namespace "root" -class "__Namespace" | Select Name
또는
Get-WMIObject -namespace "root" -query "select * from __Namespace"  | Select Name
 
[일반 유저 권한으로 실행한 결과]

 


 
 
 

Windows WMI Namespace에서 지원하는 Class 목록 확인.

 
주의 : 관리자 권한으로 실행해야함. 일반권한으로하면 일부 namespace만 나옴.
 
[명령어]
# list all classes that live in namespace "root\cimv2"...
Get-CimClass -Namespace 'root\cimv2' |
# take only the class name...

 

Select-Object -ExpandProperty CimClassName |
# and sort the output:
Sort-Object

 


 
 

Windows WMI Tester 사용해보기

 
C++에서 바로 wmi 라이브러리를 사용하는 것 보다
WMI tester를 사용해서 결과와 value를 확인하고 코딩하는게 편함.
 

1. WMI Tester 실행

실행(Ctrl + R) 에서 wbemtest 입력.

 

2. namespace 연결 클릭

이와 같은 창이 나옴.
namespace를 설정하고 연결 클릭
OS version 확인을 위해서는 root/cimv2 를 사용해야함.

 

3. test 쿼리 실행

쿼리를 클릭

c++에서 사용하고자 하는 쿼리를 사용해봄.
SELECT * FROM Win32_OperatingSystem

 

결과로 나온 Win32_OperatingSystem=@ 클릭

해당 창에서 결과 확인 가능.

 

 


 
 

c++ wmi 코드 예제


#define _WIN32_DCOM
#include <iostream>
using namespace std;
#include <comdef.h>
#include <Wbemidl.h>


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

int main()
{
    HRESULT hres;
    wchar_t wmi_namespace[] = L"ROOT/CIMV2"
    wchar_t wmi_request[] = L"SELECT * FROM Win32_OperatingSystem"
    wchar_t wmi_key[] = L"Caption"

    // 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\cimv2 namespace with
    // the current user and obtain pointer pSvc
    // to make IWbemServices calls.
    hres = pLoc->ConnectServer(
         _bstr_t(wmi_namespace), // 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 (for example, 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\\CIMV2 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(wmi_request),
        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 = NULL;
    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(wmi_key, 0, &vtProp, 0, 0);
        wcout << " check os result : " << vtProp.bstrVal << endl;
        VariantClear(&vtProp);

        pclsObj->Release();
    }


    // Cleanup
    // ========
    
    pSvc->Release();
    pLoc->Release();
    pEnumerator->Release();
    CoUninitialize();


    return 0;   // Program successfully completed.
}

 

 


 

 

(WMI 찾기 까지의 과정 요약..) windows Os version 확인 방법

 

[방법 1 : cmd]

[cmd 명령]
systeminfo | findstr /B /C:"OS Name" /C:"OS Version"
systeminfo | findstr /B /C:"OS 이름" /C:"OS 버전"

해당 명령을 사용하면 os version이 나옴.
하지만 OS 언어 설정에 따라 한국어 패치가 된 OS의 경우
findstr 설정을 한글로 처리해야 정상적으로 결과가 나옴.
추가로 속도가 느림.
 
[결론]
이 방법은 OS 언어 패치를 확인해야하는 작업이 필요하기 때문에 Pass함.
 
[참고]
c++에서 cmd명령 실행하는 방법으로는 popen이 있음.
#ifdef _WIN32
#define popen _popen
#define pclose _pclose
endif
 
 
 

[방법 2 : cmd]

 
[cmd 명령]
ver
OS 종류가 나오지 않음.
 
[결론]
원하는 결과가 아님으로 PASS
 
 

[방법 3 : cmd]

 
[cmd 명령]
wmic os get Caption /value

OS 종류가 정확하게 나오고 언어 패치에 영향도 없음.
 
[결론]
c++ popen 함수로 cmd 명령을 사용해서 해당 값을 가져오는 방법 시도.
 

[방법 4 : wmi] = 선정

 
[사용 라이브러리]
comdef.h
Wbemidl.h
 
[결과]
wmi에 대해 알아보던 중 c++에서 wmi 함수를 지원하는 것을 확인.
해당 라이브러리로 구현하기로 함.

 

반응형

'코딩 > C and C++' 카테고리의 다른 글

C++ gtest  (0) 2022.01.02
C/C++ base64 encoding/decoding  (0) 2021.12.22
C++ windows 로컬 그룹 정책 확인  (1) 2021.12.22
C++ Windows console 결과 영어로 출력  (0) 2021.12.22
동적라이브러리 (DLL) 코딩 및 적용  (0) 2020.11.30