c++ - 如何在 C++ 中获取 Wmi 连接的 SeSecurityPrivilege

标签 c++ wmi

我正在尝试使用 C++ 应用程序实时检测登录到 Windows 中的任何新事件。我读到它可以通过使用 wmi 的 ExecNotificationQuery 方法来完成。但是当它尝试它时,我得到了一个访问冲突异常。它有人说应用程序必须具有 SeSecurityPrivilege。现在我如何在创建 wmi 连接时设置此权限。只需忽略 jni 部分,我正在调用声明并将此函数用作 java 的 native 函数

更新代码:

 HANDLE hToken = NULL ;
    LPCTSTR lpszPrivilege = "SeSecurityPrivilege";
    BOOL bEnablePrivilege = true ; 

    TOKEN_PRIVILEGES tp ; 
    LUID luid ; 

    if ( !LookupPrivilegeValue(
    NULL,
    SE_SECURITY_NAME,
    &luid ))
    {
    cout << "LookupPrivilegeValue error : %u \n" << GetLastError() ;
    return  ; 
    }

    tp.PrivilegeCount = 1 ; 
    tp.Privileges[0].Luid = luid ; 
    if( bEnablePrivilege )
    {
    tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED ; 
    }
    else
    {
    tp.Privileges[0].Attributes = 0 ;
    }

    if(!OpenProcessToken(GetCurrentProcess(),
       TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY , & hToken ))
    {
    cout << "erroe in open process %u\n" << GetLastError();
    return ;
    }

    if( !AdjustTokenPrivileges(
    hToken,
    FALSE ,
    &tp,
    sizeof(TOKEN_PRIVILEGES),
    (PTOKEN_PRIVILEGES) NULL,
    (PDWORD) NULL ))
         {
    cout << "AdjustTokenPrivileges error : %u\n" << GetLastError();
    return; 
         }

        if(GetLastError() == ERROR_NOT_ALL_ASSIGNED)
        {
    cout << "The token does not have the specified privilege \n" ;
    return ;  
        }



    // Initializing the COM
    HRESULT hr ; 
    hr = CoInitializeEx( 0 , COINIT_MULTITHREADED );
    if(FAILED(hr))
    {
    cout << "first failed to initialize COM Library " << hex << hr << endl ; 
    return ;
    }

    //Initialize COM security
    hr = CoInitializeSecurity (
    NULL,
    -1,
    NULL,
    NULL,
    RPC_C_AUTHN_LEVEL_DEFAULT,
    RPC_C_IMP_LEVEL_IDENTIFY,
    NULL,
    EOAC_NONE,
    NULL
    );



    if(FAILED(hr))
    {
    cout << "second failed to initilize security."<< hex << hr << endl ; 
    CoUninitialize();
    return ;
    }

      cout << "Initilized the COM"<< endl ;

    //Initializing the IWbemLocator throught a call to CoCreateInstance.
    IWbemLocator *pLoc = 0 ; 

    hr = CoCreateInstance(CLSID_WbemLocator,0,CLSCTX_INPROC_SERVER,IID_IWbemLocator,(LPVOID*) & pLoc);
    if(FAILED(hr))
    {
    cout << "failed to create IWbemLocator object"<< hex << hr << endl ; 
    CoUninitialize();
    return ;
    }

    //Connect to WMI through a call to ConnectServer method of IWbemLocator
    IWbemServices *pSvc = 0 ; 

    hr = pLoc->ConnectServer(
    _bstr_t(L"ROOT\\CIMV2"),
    NULL,
    NULL,
    0,
    NULL,
    0,
    0,
    &pSvc);

    if(FAILED(hr))
    {
    cout << "could not connect to WMI from ConnectServer method"<<hex<<hr<<endl;
    pLoc->Release();
    CoUninitialize();
    return ;
    }

      cout << "Connected to WMI" << endl ; 

    //Setting security level on a Wmi connection

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

    if(FAILED(hr))
    {
    cout << "could not set security level on wmi connection" << hex << hr << endl;
    pSvc->Release();
    pLoc->Release();
    CoUninitialize();
    return ;
    }

      cout << "Security level set on wmi connection" << endl;


    // Querying for data using executeQuery Method of IWbemServies pointer

    IEnumWbemClassObject* pEnumerator = NULL ; 
    hr = pSvc->ExecNotificationQuery (
    bstr_t("WQL"),
    //bstr_t(Cquery),
    bstr_t("select * from __InstanceCreationEvent where TargetInstance ISA 'Win32_NTLogEvent'"),
    WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY,
    NULL,
    &pEnumerator);

    if(FAILED(hr))
    {
    cout << "Query for operating system failed for Win32_NTLogEvent" << hex << endl ; 
    pSvc->Release();
    pLoc->Release();
    CoUninitialize();
    return ; 
    }
      cout << "data is obtained from the operating system" << endl ; 

    //Getting the data from the query for Win32_NTLogEvent

    IWbemClassObject *pclsobj = NULL ; 
    ULONG uReturn = 0 ; 

    string logname ; int lognum = 0 ;

    while (pEnumerator && lognum < 2 )
    { 
    lognum++ ; 

    HRESULT hr = pEnumerator->Next(WBEM_INFINITE,1,&pclsobj,&uReturn);
    if( 0 == uReturn )
    {
    cout << "loop broke" << endl ;
    cout << "uReturn value :" << uReturn << endl ; 
    break;
    }
      cout << "uReturn value :" << uReturn << endl ; 
    VARIANT vtProp;


    string Properties[11] = {"ComputerName" , "Message" , "Logfile" , "SourceName" , "Type" , "EventCode" , "EventIdentifer" , "EventType" , "RecordNumber" , "TimeGenerated" , "TimeWritten"};



    int index = 0 ; 
    for( index = 0 ; index < 11 ; index++ )
    {

    LPWSTR prop ;
    std::wstring property(Properties[index].begin() , Properties[index].end()) ; 
    prop = (LPWSTR) property.c_str();
    hr = pclsobj->Get(prop, 0 , &vtProp , 0 , 0 );

    if(index < 5 )
    {
    cout << "getting property" << endl ; 
    BSTR bpropertyvalue = vtProp.bstrVal ;


    cout << Properties[index] << "reached here" << endl ;

    std::wstring wpropertyvalue(bpropertyvalue,SysStringLen(bpropertyvalue));**the crash occurs in this point**      //CONVERTING BSTR TO WSTRING
    cout << Properties[index] << "reached here again" << endl ;
    string propertyvalue(wpropertyvalue.begin(),wpropertyvalue.end());
    propertyvalue.assign(wpropertyvalue.begin(),wpropertyvalue.end());             //CONVERTING WSTRING TO C++ STRING

    cout << Properties[index] << ":" <<  propertyvalue << endl ;  
    VariantClear(&vtProp);
    }
    else if( index < 9 )
    {

    int propertyvalue ;             //CONVERTING UINT TO INT

    if( index == 5 )
    { propertyvalue = vtProp.uiVal ;} 
    else if(index == 6 )
    { propertyvalue = vtProp.ulVal ;} 
    else if(index == 7)
    { propertyvalue = vtProp.intVal ;} 
    else 
    { propertyvalue = vtProp.ulVal ; } 

    cout << Properties[index] << ":" <<  propertyvalue << endl ;
    VariantClear(&vtProp);
           }
        else
        {
    CString gendate(vtProp);
    cout << " gendate : " << gendate << endl ;
    string s(gendate); 
    string year(s,0,4);
    string month(s,4,2);
    string day(s,6,2);
    string hour(s,8,2);
    string minute(s,10,2);
    string sec(s,12,2);
    string millisec(s,15,6);

    struct tm t = {0} ; 
    stringstream yearstrm(year) ; 
    int yr = 0 ; yearstrm >> yr ; 
    stringstream monthstrm(month) ;
    int mn = 0 ; monthstrm >> mn ; 
    stringstream daystrm(day) ;
    int dy = 0 ; daystrm >> dy ; 
    stringstream hourstrm(hour) ;
    int hr = 0 ; hourstrm >> hr ; 
    stringstream minstrm(minute) ;
    int min = 0 ;minstrm >> min ; 
    stringstream secstrm(sec) ;
    int sc = 0 ;secstrm >> sc ;
    stringstream millisecstrm(millisec) ;
    int msec = 0 ; millisecstrm >> msec ; 


    t.tm_year = yr-1900 ; 
    t.tm_mon = mn-1 ; 
    t.tm_mday = dy ; 
    t.tm_hour = hr ; 
    t.tm_min = min ; 
    t.tm_sec = sc ; 
    time_t time = mktime(&t) * 1000 + msec ;
    cout << yr <<"-" << mn <<"-" << dy << "-" << hr << ":" <<  min << ":" << sc << endl ; 
    stringstream timegen ; 
    timegen << time ; 
    std::string timestr = timegen.str() ;
    cout << timestr << endl ;  

    VariantClear(&vtProp);

        }
    }


    //cout << "---------------------------------------------" << endl ; 

最佳答案

获取权限通常包括 3 个步骤:查询权限 LUID、获取允许调整权限的入口 token 句柄、调整权限。

// Fill struct.
::TOKEN_PRIVILEGES tkp;
tkp.PrivilegeCount = 1;
tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
if(FALSE == ::LookupPrivilegeValueW(nullptr, SE_SECURITY_NAME, ::std::addressof(tkp.Privileges[0].Luid)))
{
    // Handle error...
}
//  Obtain current process (pseudo) handle.
auto const this_process_handle{::GetCurrentProcess()};
assert(reinterpret_cast<::HANDLE>(-1) == this_process_handle); // No need to call CloseHandle.
//  Obtain privilege token for this process.
::HANDLE naked_token_handle{};
constexpr ::DWORD const access_flags{TOKEN_ADJUST_PRIVILEGES bitor TOKEN_QUERY};
if(FALSE == ::OpenProcessToken(this_process_handle, access_flags, ::std::addressof(naked_token_handle)))
{
    // Handle error...
}
assert(NULL != naked_token_handle); // Must call CloseHandle to cleanup.
//  Enable privilege.
if(FALSE == ::AdjustTokenPrivileges(naked_token_handle, FALSE, ::std::addressof(tkp), 0, nullptr, nullptr))
{
    // Handle error and close handle...
}
if(FALSE = ::CloseHandle(naked_token_handle))
{
    // Handle error...
}

关于c++ - 如何在 C++ 中获取 Wmi 连接的 SeSecurityPrivilege,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48881528/

相关文章:

从字符串中提取数字的正则表达式 (gwmi Win32_OperatingSystem).Name

c# - 如何在 C# 中查找 IIS 站点 ID?

windows - 获取链接速度 - Win32_PerfRawData_Tcpip_NetworkInterface

c++ - Webview - 如何检测 Blackberry Cascades 中的 url 是否无效

c++ - '=' 应初始化所有枚举成员或仅初始化第一个;

c# - 如何为 WMI 查询设置超时?

c# - 如何从 C# 更改 IIS 中应用程序池的用户名/密码?

c++ - Valgrind 报告在一个系统上读取无效,但在另一个系统上没有

c# - 如何从 C# 访问将指针作为输入参数的 C++ 函数

c++ - C 的标准库