NDISLWF how to modify the packet

http://www.osronline.com/showThread.cfm?link=172579

You are not generally permitted to modify something that your driver doesnot 'own'. A NBL indicated to your driver is usually treated as'read-only'. To 'modify' the packet, your driver typically would copy theNBL, modify the copy, indicate the copy, and when the copy is returned, free it and return the original (unmodified) NBL to the entity that indicated it to you.


本来只想简单的block stream,因为对ndislwf不熟悉,不想把驱动写得太复杂,但朋友玩QQ里的彩虹砖块197分,自认为没有那么厉害,于是抓包一看,如果修改了包信息能否骗过游戏,提高我的成绩呢?

1.抓包信息如下:

NDISLWF how to modify the packet_第1张图片


2.我要做的就是找到这个stream,然后修改其中的内容。我用了AC算法进行数据包的扫描,当找到对应的NBL后,我写了一个函数,进行NBL的拷贝,函数如下:

PNET_BUFFER_LIST FltCopyNetBufferList(
        IN PMS_FILTER				pFilter,
	IN PNET_BUFFER_LIST			pNBL
	)
{
	BOOLEAN             bFalse = FALSE;
	PMDL				pMdl,pnextMdl,pnewMdl;
	PMDL				pFirstMDL =	NULL;
	PUCHAR				pMDLAddress = NULL;
	PNET_BUFFER_LIST	pNetBufferList = NULL;
	PNET_BUFFER			pCurrentNetBuffer = NULL;
	LONG				dataLength = 0;
	LONG				TotalLength = 0;
	PUCHAR				pAddress;
	LONG				lOffset;
	//LONG				NBDL;
	//LONG				NBDO;
	
	DEBUGP(DL_TEST,("==============>CopyNetBufferList\n"));  

	pnextMdl = NULL;

	pCurrentNetBuffer =  NET_BUFFER_LIST_FIRST_NB(pNBL);
//	for(pCurrentNetBuffer =  NET_BUFFER_LIST_FIRST_NB(pNBL);
//		pCurrentNetBuffer != NULL;
//		pCurrentNetBuffer =  NET_BUFFER_NEXT_NB(pCurrentNetBuffer)
//		)
//	{
		pMdl = NET_BUFFER_CURRENT_MDL(pCurrentNetBuffer);
		lOffset = NET_BUFFER_CURRENT_MDL_OFFSET(pCurrentNetBuffer);
		//NBDL = NET_BUFFER_DATA_LENGTH(pCurrentNetBuffer);
		//NBDO = NET_BUFFER_DATA_OFFSET(pCurrentNetBuffer);
		do{
			NdisQueryMdl(pMdl, &pAddress, &dataLength, NormalPagePriority);
			dataLength -= lOffset;
			pMDLAddress = (PUCHAR)NdisAllocateMemoryWithTagPriority(pFilter->FilterHandle, dataLength, FILTER_ALLOC_TAG, LowPoolPriority);   
			if(NULL == pMDLAddress)
			{
				return NULL;
			}
			NdisZeroMemory(pMDLAddress, dataLength);  

			//add a discreption for the allocate memory
			pFirstMDL = NdisAllocateMdl(pFilter->FilterHandle, pMDLAddress, dataLength);
			pFirstMDL->Next = NULL;
			if(pFirstMDL == NULL)	
			{	
				DEBUGP(DL_TEST,("PMDL Fail....\n"));
				break;
			}  

			pNetBufferList = NdisAllocateNetBufferAndNetBufferList(  
				pFilter->SNBLPool,
				0,//sizeof(FILTER_SEND_NETBUFLIST_RSVD), Request control offset delta	
				0,			 // back fill size	 
				pFirstMDL,	
				0,			// Data offset	 
				dataLength);   
			if(pNetBufferList == NULL)	
			{	
				NdisFreeMdl(pFirstMDL); 
				break;	
			}
			//change the checksum
			//NDIS_TCP_IP_CHECKSUM_NET_BUFFER_LIST_INFO
			NET_BUFFER_LIST_INFO(pNetBufferList, TcpIpChecksumNetBufferListInfo) = NET_BUFFER_LIST_INFO(pNBL, TcpIpChecksumNetBufferListInfo);			
			pNetBufferList->SourceHandle = pFilter->FilterHandle;
			TotalLength += dataLength;
			NdisMoveMemory((pMDLAddress + 0),(pAddress + lOffset), dataLength);//the first mdl OK
			//the following MDL , and the next MDL, they offet is 0!
			pMdl = pMdl->Next;
			pnextMdl = pFirstMDL;
			while(NULL != pMdl){
				NdisQueryMdl(pMdl, &pAddress, &dataLength, NormalPagePriority);
				pMDLAddress = (PUCHAR)NdisAllocateMemoryWithTagPriority(pFilter->FilterHandle, dataLength, FILTER_ALLOC_TAG, LowPoolPriority);   
				if(NULL == pMDLAddress)
				{
					return NULL;
				}
				NdisZeroMemory(pMDLAddress, dataLength);  

				//add a discreption for the allocate memory
				pnewMdl = NdisAllocateMdl(pFilter->FilterHandle, pMDLAddress, dataLength);
				if(pnewMdl == NULL)	
				{	
					DEBUGP(DL_TEST,("NEWMDL Fail....\n"));
					break;
				} 
				TotalLength += dataLength;
				NdisMoveMemory(pMDLAddress, pAddress, dataLength);
				*(pMDLAddress+dataLength-1) = 'T';
				pMdl = pMdl->Next;
				pnextMdl->Next = pnewMdl;
				pnextMdl = pnewMdl;
				pnextMdl->Next = NULL;
			} 	
		}while(bFalse);
		//AFFTER COPY THE MDL, THEN WE SHOULD MODIFY THE NET_BUFFER
		NET_BUFFER_DATA_LENGTH(NET_BUFFER_LIST_FIRST_NB(pNetBufferList)) = TotalLength;
		NET_BUFFER_LIST_NEXT_NBL(pNetBufferList) = NULL;
//	}
	DEBUGP(DL_TEST,("<==============CopyNetBufferList\n")); 	
	return pNetBufferList;
}
在这个函数中,我把只是简单把COPY的数据最后一个字节改为了'T'。


3.修改后,捕包截图如下:

NDISLWF how to modify the packet_第2张图片


3.针对修改score我修改了上面的函数,成绩可以改为200,不过服务器那边很可能用key做了验证,因为改为200后,返回数据包如下:

NDISLWF how to modify the packet_第3张图片


4.与前面block stream类似,将original NBL block掉,将copied NBL通过NdisFSendNetBufferLists传给底层。在FilterSendNetBufferListsComplete中:

if( NdisGetPoolFromNetBufferList(NetBufferLists) == pFilter->SNBLPool ){
		NdisFreeNetBufferList(NetBufferLists);
	} else {		
		NdisFSendNetBufferListsComplete(pFilter->FilterHandle, NetBufferLists, SendCompleteFlags);
	}
进行相应NBL的释放。

5.对于NDISLWF,我并不熟悉,所以在上面的copy函数中,如果一个NBL中存在多个NB该如何处理呢?也许需要动态分配NB,然后将它们链接起来。


在写修改包内容的示例过程中,很难在网上找到相关信息,我参考了如下几个网站:

http://blog.donews.com/uuty/archive/2011/03/24/1473377.aspx

http://yexin218.iteye.com/blog/648533

NDIS 6 Net Buffer Lists and Net Buffers

http://www.codemachine.com/article_ndis6nbls.html

你可能感兴趣的:(Stream,list,filter,服务器,null,buffer)