首页
社区
课程
招聘
[求助]WMI ExecQuery(...) 是否不经过驱动WMIDataDevice拦截
发表于: 2016-3-9 11:36 7089

[求助]WMI ExecQuery(...) 是否不经过驱动WMIDataDevice拦截

2016-3-9 11:36
7089
原贴:
【原创】关于拦截“通过WMI读取硬件序列号”的一些心得
http://bbs.pediy.com/showthread.php?t=127176

本人做了一个WMIDataDevice过滤驱动, 然而似乎并不会拦截到ExecQuery(L"SQL"..)查询硬件序列号??

根据如上,做了一个过淲驱动, 部分代码如下:
//	找过滤目标驱动
		UNICODE_STRING FilterToDriverName;
		RtlInitUnicodeString(&FilterToDriverName, L"\\Device\\WMIDataDevice");
		PFILE_OBJECT FilterToFileObject;
		PDEVICE_OBJECT FilterToDevice;

		status = IoGetDeviceObjectPointer(&FilterToDriverName, FILE_ALL_ACCESS, &FilterToFileObject, &FilterToDevice);
		if (!NT_SUCCESS(status))
		{
			DbgPrint("IoGetDeviceObjectPointer ERR: %wZ, %p", FilterToDriverName, status);
			return 0-__LINE__;
		}
		ObDereferenceObject(FilterToFileObject);
//....
// 一系列初始化
		for (int i = 0; i <= IRP_MJ_MAXIMUM_FUNCTION; i++)
			DriverObject->MajorFunction[i] = DriverWMIFilterDefaultHandler;
//....

NTSTATUS DriverWMIFilterDefaultHandler(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
{

	FilterDriverExtension* fltEx = (FilterDriverExtension*)DeviceObject->DeviceExtension;
	KdPrint(("DriverWMIFilterDefaultHandler: %p %lx, %d", fltEx, Irp->CurrentLocation, fltEx->IrpPenddingCount));
	if (!fltEx || !fltEx->NextDevice)
		return 0-__LINE__;

	IoSkipCurrentIrpStackLocation(Irp);

	return IoCallDriver(fltEx->NextDevice, Irp);
}



当直接createfile 时,能够成拦截:
HANDLE hDev = CreateFile(L"\\\\.\\WMIDataDevice",
		GENERIC_READ | GENERIC_WRITE,
		0,		// share mode none
		NULL,	// no security
		OPEN_EXISTING,
		FILE_ATTRIBUTE_NORMAL,
		NULL );		// no template
	TRACERlsn(L"hDev: %p\r\n", hDev);

	BYTE rd[10];
	ULONG rdsize =0;
	OVERLAPPED vp;
	BOOL bRd = ReadFile(hDev,  rd, 10, &rdsize, &vp);
	TRACERlsn(L"ReadFile: %d, %d\r\n", bRd, rdsize);

	CloseHandle(hDev);


而当使用wmi获取硬件序列号时, 并不能成功拦截. 部分代码如下:
// WQL查询语句
const T_WQL_QUERY szWQLQuery[] = {
	// 网卡原生MAC地址
	"SELECT * FROM Win32_NetworkAdapter WHERE (MACAddress IS NOT NULL) AND (NOT (PNPDeviceID LIKE 'ROOT%'))",
	L"PNPDeviceID",

	// 硬盘序列号
	"SELECT * FROM Win32_DiskDrive WHERE (SerialNumber IS NOT NULL) AND (MediaType LIKE 'Fixed hard disk%')",
	L"SerialNumber",

	// 主板序列号
	"SELECT * FROM Win32_BaseBoard WHERE (SerialNumber IS NOT NULL)",
	L"SerialNumber",	

	// 处理器ID
	"SELECT * FROM Win32_Processor WHERE (ProcessorId IS NOT NULL)",
	L"ProcessorId",

	// BIOS序列号
	"SELECT * FROM Win32_BIOS WHERE (SerialNumber IS NOT NULL)",
	L"SerialNumber",

	// 主板型号
	"SELECT * FROM Win32_BaseBoard WHERE (Product IS NOT NULL)",
	L"Product",

	// 网卡当前MAC地址
	"SELECT * FROM Win32_NetworkAdapter WHERE (MACAddress IS NOT NULL) AND (NOT (PNPDeviceID LIKE 'ROOT%'))",
	L"MACAddress",
};

// 基于Windows Management Instrumentation(Windows管理规范)
INT WMI_DeviceQuery( INT iQueryType, T_DEVICE_PROPERTY *properties, INT iSize )
{
	HRESULT hres;
	INT	iTotal = 0;

	// 判断查询类型是否支持
	if( (iQueryType < 0) || (iQueryType >= sizeof(szWQLQuery)/sizeof(T_WQL_QUERY)) )
	{
		return -1;	// 查询类型不支持
	}

	// 初始化COM
	hres = CoInitializeEx( NULL, COINIT_MULTITHREADED ); 
	if( FAILED(hres) )
	{
		return -2;
	}

	// 设置COM的安全认证级别
	hres = CoInitializeSecurity( 
		NULL, 
		-1, 
		NULL, 
		NULL, 
		RPC_C_AUTHN_LEVEL_DEFAULT, 
		RPC_C_IMP_LEVEL_IMPERSONATE,
		NULL,
		EOAC_NONE,
		NULL
		);
	if( FAILED(hres) )
	{
		CoUninitialize();
		return -2;
	}

	// 获得WMI连接COM接口
	IWbemLocator *pLoc = NULL;
	hres = CoCreateInstance( 
		CLSID_WbemLocator,             
		NULL, 
		CLSCTX_INPROC_SERVER, 
		IID_IWbemLocator,
		reinterpret_cast<LPVOID*>(&pLoc)
		); 
	if( FAILED(hres) )
	{
		CoUninitialize();
		return -2;
	}

	// 通过连接接口连接WMI的内核对象名"ROOT//CIMV2"
	IWbemServices *pSvc = NULL;
	hres = pLoc->ConnectServer(
		_bstr_t( L"ROOT\\CIMV2" ),
		NULL,
		NULL,
		NULL,
		0,
		NULL,
		NULL,
		&pSvc
		);    
	if( FAILED(hres) )
	{
		pLoc->Release(); 
		CoUninitialize();
		return -2;
	}

	// 设置请求代理的安全级别
	hres = 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(hres) )
	{
		pSvc->Release();
		pLoc->Release();     
		CoUninitialize();
		return -2;
	}

	// 通过请求代理来向WMI发送请求
	IEnumWbemClassObject *pEnumerator = NULL;
	hres = pSvc->ExecQuery(
		bstr_t("WQL"), 
		bstr_t( szWQLQuery[iQueryType].szSelect ),
		WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY, 
		NULL,
		&pEnumerator
		);
	if( FAILED(hres) )
	{
		pSvc->Release();
		pLoc->Release();
		CoUninitialize();
		return -3;
	}

	// 循环枚举所有的结果对象  
	while( pEnumerator )
	{
		IWbemClassObject *pclsObj = NULL;
		ULONG uReturn = 0;

		if( (properties != NULL) && (iTotal >= iSize) )
		{
			break;
		}

		pEnumerator->Next(
			WBEM_INFINITE,
			1, 
			&pclsObj,
			&uReturn
			);

		if( uReturn == 0 )
		{
			break;
		}

		if( properties != NULL )
		{	// 获取属性值
			VARIANT vtProperty;

			VariantInit( &vtProperty );	
			pclsObj->Get( szWQLQuery[iQueryType].szProperty, 0, &vtProperty, NULL, NULL );
			StringCchCopy( properties[iTotal].szProperty, PROPERTY_MAX_LEN, W2T(vtProperty.bstrVal) );
			VariantClear( &vtProperty );

			// 对属性值做进一步的处理
			if( WMI_DoWithProperty( iQueryType, properties[iTotal].szProperty, PROPERTY_MAX_LEN ) )
			{
				iTotal++;
			}
		}
		else
		{
			iTotal++;
		}

		pclsObj->Release();
	} // End While

	// 释放资源
	pEnumerator->Release();
	pSvc->Release();
	pLoc->Release();    
	CoUninitialize();

	return iTotal;
}



请教:这是因为WIN7不适用,
还是WMIDataDevice这个驱动名称不对,
还是上面的获取序列号的方法不是WMI,不能用这种拦截方法??
谢谢
//===========================================================
谢谢下面的各位,
现在用的是NtAlpcSendWaitReceivePort;
呵呵,为了方便其它有同样问题的朋友,NtAlpcSendWaitReceivePort相关说明如下:
高手略过,错误指正. 有资料的来点。
	typedef struct _PORT_MESSAGE    //	LPC(/ALPC)接受或发送的消息的信息头结构,其数据紧随其后(数据最大长度0x130??)
	{    
#define LPC_REQUEST 1    //	Type
#define LPC_REPLY 2    
#define LPC_DATAGRAM 3    
#define LPC_LOST_REPLY 4    
#define LPC_PORT_CLOSED 5    
#define LPC_CLIENT_DIED 6    
#define LPC_EXCEPTION 7    
#define LPC_DEBUG_EVENT 8    
#define LPC_ERROR_EVENT 9    
#define LPC_CONNECTION_REQUEST 10
		union    
		{    
			struct    
			{    
				CSHORT DataLength;    //	尾随于结构之后的数据长度
				CSHORT TotalLength;    //	总长度 == (DataLength + TotalLength)
			} s1;    
			ULONG Length;    
		} u1;    
		union    
		{    
			struct    
			{    
				CSHORT Type;    
				CSHORT DataInfoOffset;    
			} s2;    
			ULONG ZeroInit;    
		} u2;    
		union    
		{    
			CLIENT_ID ClientId;    
			double DoNotUseThisField;    // Force quadword alignment
		};    
		ULONG MessageId;			// Identifier of the particular message instance
		union		
		{    
			SIZE_T ClientViewSize;	// only valid for LPC_CONNECTION_REQUEST messages    
			ULONG CallbackId;		// only valid for LPC_REQUEST messages    
		};    
	} PORT_MESSAGE, *PPORT_MESSAGE;
	typedef struct _ALPC_MESSAGE_ATTRIBUTES   	// 此结构后面还有跟有数据
	{   
		ULONG AllocatedAttributes;   
		ULONG ValidAttributes;   
	} ALPC_MESSAGE_ATTRIBUTES, *PALPC_MESSAGE_ATTRIBUTES;
	typedef NTSTATUS (_stdcall *_NtAlpcSendWaitReceivePort)(
		IN HANDLE PortHandle, 
		IN ULONG Flags, 
		IN PPORT_MESSAGE SendMessage, 
		IN OUT OPTIONAL PALPC_MESSAGE_ATTRIBUTES SendMessageAttributes, 
		OUT PPORT_MESSAGE ReceiveMessage, 
		IN OUT OPTIONAL PSIZE_T BufferLength,			//	此处大小 == ReceiveMessage->u1.TotalLength;
		IN OUT OPTIONAL PALPC_MESSAGE_ATTRIBUTES ReceiveMessageAttributes, 
		IN OPTIONAL PLARGE_INTEGER Timeout 
		);

//    我用的是win7系统,
//    当数据很大时,比如0x2000, 数据本身是mapview进来的。
//    NtAlpcSendWaitReceivePort资数很少,为了找到map指针,逆向了下
//    没有完全,勉强能找到map指针
if (ReceiveMessage && 
	ReceiveMessage->u2.s2.Type &  2 &&
	ReceiveMessage->u1.s1.TotalLength >= 0x48 &&
	*(PULONG)(PUCHAR(ReceiveMessage) +0x28) == 0x3 &&
	((*(PUCHAR)(PUCHAR(ReceiveMessage) +0x30)) & 4) && // +34是一种计数
	ReceiveMessageAttributes
	)	//	此时,数据是map进来的
{
	KdPrint((__FUNCTION__ "[%p] haven map region 1, %lx", 
		PsGetCurrentProcessId(), ReceiveMessageAttributes->AllocatedAttributes));

	//	32位与64位获得map指针有区别
	//	不知道内核是如何知道调用它的是32位或是64位, 难道是从PortHandle获得的?
	//	有知道的朋友告知下
	static ULONG AttAllocatedOffset64[] = {0x08, 0, 0x28, 0, 0x28, 0, 0x48, 0, 0x20, 0, 0x40, 0, 0x40, 0, 0x60};
	static ULONG AttAllocatedOffset32[] = {0x08, 0, 0x1c, 0, 0x18, 0, 0x2c, 0, 0x14, 0, 0x28, 0, 0x24, 0, 0x38};
	ULONG offIdx =  ((ReceiveMessageAttributes->AllocatedAttributes >>0x1c) & 8);
	if (offIdx < _countof(AttAllocatedOffset64))
	{
		struct AllocatedInfo64  // 位于ReceiveMessageAttributes +AttAllocatedOffset64[offIdx]
		{
			ULONG_PTR someSign;	// 有位检测bt someSign,0x12
			ULONG_PTR notSure;
			LPVOID memPtr;		//	此处即map指针
			ULONG_PTR memLen;

		};
		struct AllocatedInfo32  // 位于ReceiveMessageAttributes +AttAllocatedOffset32[offIdx]
		{
			ULONG someSign;	// 有位检测bt someSign,0x12
			ULONG notSure;
			ULONG memPtr;	//	此处即map指针
			ULONG memLen;

		};
		AllocatedInfo64* alcInfo = (AllocatedInfo64*)((PUCHAR)ReceiveMessageAttributes +AttAllocatedOffset64[offIdx]);
		LPVOID memPtr = alcInfo->memPtr;
		ULONG_PTR memLeaveLen = *(ULONG_PTR*)(PUCHAR(ReceiveMessage) +0x40);
		ULONG_PTR memLen = alcInfo->memLen;

		//	好吧,如果map指针大于0x7fffffff为32位
		if (memPtr > (LPVOID)0x7fffffff || memLen < memLeaveLen)  
		{
			AllocatedInfo32* alcInfo = (AllocatedInfo32*)((PUCHAR)ReceiveMessageAttributes +AttAllocatedOffset32[offIdx]);
			memPtr = (LPVOID)alcInfo->memPtr;
			memLen = alcInfo->memLen;
		}

		KdPrint(("haven map region 2: %lx, %llx, %llx, %llx, - %llx, \r\n", 
			offIdx, alcInfo->notSure, memPtr, memLen,  memLeaveLen
			));
	}
}

[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)

收藏
免费 0
支持
分享
最新回复 (5)
雪    币: 221
活跃值: (2326)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
2
看代码。没看到你对DriverObject->MajorFunction[IRP_MJ_SYSTEM_CONTROL]  的过滤
2016-3-9 11:52
0
雪    币: 99
活跃值: (110)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
以前我也研究过,具体不记得结果了.
但是后来直接从 NtAlpcSendWaitReceivePort 下手了,WMI WIN7 是基于ALPC通信
2016-3-9 13:13
0
雪    币: 30
活跃值: (765)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
4
注意看下 FastIO
2016-3-9 15:57
0
雪    币: 135
活跃值: (25)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5
呵呵 , 有些查询到信息是不能通过拦截WMI设备得到的。。。。

具体为什么,你可以用IRP工具,自己跟下返回的Buff内容 。。。。。
2016-3-9 17:04
0
雪    币: 11
活跃值: (11)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6
没看到你对DriverObject->MajorFunction[IRP_MJ_SYSTEM_CONTROL] 的过滤

    for (int i = 0; i <= IRP_MJ_MAXIMUM_FUNCTION; i++)
      DriverObject->MajorFunction[i] = DriverWMIFilterDefaultHandler;
   在DriverWMIFilterDefaultHandler中,我Dbg, IRP_MJ_SYSTEM_CONTROL已经包含其中了
注意看下 FastIO

    FastIO也不会触发。

不过在查询 主板序列号 时,如果主板无序列号,那么IRP_MJ_SYSTEM_CONTROL及FastIO倒会触发。

呵呵 , 有些查询到信息是不能通过拦截WMI设备得到的。。IRP工具。。

直接从 NtAlpcSendWaitReceivePort 下手了,WMI WIN7 是基于ALPC通信

IRPTrace在win7下已经不能用了。正在寻找其它。
我看看ALPC.
2016-3-9 19:05
0
游客
登录 | 注册 方可回帖
返回
//