⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 filterpkt.c

📁 一个截取网络包的驱动。它与DDK文档正是NDIS中间驱动不同
💻 C
📖 第 1 页 / 共 3 页
字号:
////////////////////////////////////////
//		该文件是具体HOOK实现的文件
//
////////////////////////////////////////

#include "VDFltIpDef.h"
#include "DriverDef.h"
#include "DriverTool.c"
#include "DriverList.c"

//HOOK某个协议例程
int HookProtoProc(SHookProc *pHookProc,void **ppOldProc,void *pNewProc,void *pParentHandle)
{
	if((*ppOldProc)==NULL) return 0;

	if(pHookProc==(*ppOldProc))
	{
		DbgPrint("\n!!!!! HookProtoProc Same OldFunc\n");
		return 0;
	}

	if( (*ppOldProc)>=(void*)g_AdapterHandles &&
		(*ppOldProc)<=(void*)(g_AdapterHandles+MAX_ADAPTERHANDLE) )
	{
		DbgPrint("\n!!!!! PtrInAdapterHandle\n");
		return 0;
	}

	if( (*ppOldProc)>=(void*)g_ProtoHandles &&
		(*ppOldProc)<=(void*)(g_ProtoHandles+MAX_PROTOHANDLE) )
	{
		DbgPrint("\n!!!!! PtrInProtoHandle\n");
		return 0;
	}

	pHookProc->code1_0x58=0x58;
	pHookProc->code2_0x68=0x68;
	pHookProc->code3_0x50=0x50;
	pHookProc->code4_0xE9=0xE9;

	pHookProc->pThis=pHookProc;
	pHookProc->uHookProcOffset=((ULONG)pNewProc)-(((ULONG)&pHookProc->uHookProcOffset) + sizeof(ULONG));

	pHookProc->pParentHandle=pParentHandle;

	pHookProc->pOldProc=*ppOldProc;
	*ppOldProc=pHookProc;

	return 1;
}

#ifdef _WIN32_WINNT
//	g_bHookSend:由于NT是采用HOOK NDIS绑定句柄即NDIS_OPEN_BLOCK绑定的SEND函数
//	当系统切换IP或者网线重连后,系统会重新分配NDIS_OPEN_BLOCK,而我们也要
//	重新HOOK,g_bHookSend就是用来是否HOOK SEND的标志
BOOLEAN g_bHookSend=FALSE;
#endif

//	在发广播包时,系统自己也能收到。g_sendbrdtm用来记录
//	发广播包的时间,然后跟当前接收时间判断是否是本机发送的包。
static ULONG g_sendbrdtm;

//由拨号客户端设置的一些变量
BOOLEAN g_bOnline=FALSE;		//是否上线标志
static UCHAR g_gwmac[6];		//网关MAC
static UCHAR g_onlinemac[6];	//上线网卡MAC
ULONG g_onlineip=0;				//上线网卡IP
ULONG g_gwip=0;					//网关IP

//记录AS广播的信息,连续180秒没收到则认为没收到
SMyDhcp g_mydhcp;
ULONG g_md_time=0;
#define	RecvMyDhcp()	(g_md_time && (GetSystemTime()-g_md_time)<180)

//判断系统是否要限制代理,3个条件缺一不可:
//1-上线了;2-收到MYDHCP,表明在AS下端;3-AS配置为限制代理
int LimitProxy()
{
	if(!g_bOnline) return 0;
	if(!RecvMyDhcp()) return 0;
	return !g_mydhcp.bAllowProxy;
}

//用来发送的PacketPool和BufferPool
NDIS_HANDLE  g_PacketPool;
NDIS_HANDLE  g_BufferPool;

//进行初始化的工作
void InitFilter()
{
	NDIS_STATUS Status;
	NdisAllocatePacketPool(
		&Status,
		&g_PacketPool,
		0xFF,
		sizeof(PNDIS_PACKET));

	NdisAllocateBufferPool(
		&Status,
		&g_BufferPool,
		0xFF);

#ifdef _WIN32_WINNT
	KeInitializeSpinLock(&g_AdapterHandleLock);
	KeInitializeSpinLock(&g_ProtoHandleLock);
#endif
}

//释放
void ExitFilter()
{
	NdisFreeBufferPool(g_BufferPool);
	NdisFreePacketPool(g_PacketPool);
}


//创建发送UDP包缓冲区szPacket,nCode:发送交易码,dmac:目标MAC,uDIp:目标IP,pSendData:要发送数据
void CreateRawUdpPacket(char szPacket[],long nCode,UCHAR dmac[],ULONG uDIp,const void *pSendData)
{
	SEth *pEth=(SEth*)szPacket;
	SIp *pIp=(SIp*)(pEth+1);
	SUdp *pUdp=(SUdp*)(pIp+1);
	SDrvPkt *pDrvPkt=(SDrvPkt*)(pUdp+1);

	memcpy(pEth->dmac,dmac,6);
	memcpy(pEth->smac,g_onlinemac,6);
	pEth->proto=UTIL_htons(ETH_P_IP);

	pIp->ip_v=4;
	pIp->ip_hl=5;
	pIp->ip_tos=0;
	pIp->ip_len=UTIL_htons(sizeof(SIp)+sizeof(SUdp)+sizeof(SDrvPkt));
	pIp->ip_id=UTIL_htons(547);
	pIp->ip_off=0;
	pIp->ip_ttl=0x40;
	pIp->ip_p=17;
	pIp->ip_src=g_onlineip;
	pIp->ip_dst=uDIp;
	pIp->ip_sum=0;
	pIp->ip_sum=checksum((USHORT*)pIp,sizeof(SIp));

	pUdp->dport=MAC_PORT;
	pUdp->sport=MAC_PORT;
	pUdp->len=UTIL_htons(sizeof(SUdp)+sizeof(SDrvPkt));
	pUdp->sum=0;

	pDrvPkt->nCode=nCode;
	switch(nCode)
	{
	case MAC_REQUEST:
		memcpy(pDrvPkt->proxy.mac1,dmac,6);
		pDrvPkt->proxy.nCode=MAC_REPLY;
		memcpy(pDrvPkt->proxy.mac2,g_onlinemac,6);
		break;
	case MAC_REPLY:
	case MAC_DECLINE:
		memcpy(pDrvPkt->proxy.mac1,g_onlinemac,6);
		break;
	case NOTIFY_STOPPROC:
		strcpy(pDrvPkt->szStopProc,pSendData);
		break;
	default:
		break;
	}

	pUdp->sum=udpcksum(pIp,pUdp);
}

//对于我们发送包的清理
BOOLEAN SendVDPacketComplt(PNDIS_PACKET pPacket)
{
	PNDIS_BUFFER pBuffer=NULL;

	if(pPacket->Private.Pool != g_PacketPool) return FALSE;
	
	NdisUnchainBufferAtFront(pPacket, &pBuffer);
	if(pBuffer) NdisFreeBuffer(pBuffer);

	//  recyle the packet
	NdisReinitializePacket(pPacket);
	NdisFreePacket(pPacket);
//	DbgPrint("SendVDPacketComplt TmpPacket");

	return TRUE;
}

//通过NdisBindHandle发送包,nCode:发送交易码,dmac:目标MAC,uDIp:目标IP,pSendData:要发送数据
void SendVDPacket(NDIS_HANDLE NdisBindHandle,UCHAR uCode,UCHAR dmac[],ULONG uDIp,const void *pSendData)
{
	NDIS_STATUS Status;
	PNDIS_PACKET pPacket;
	PNDIS_BUFFER pNdisBuffer=NULL;

	static char szBuffer[256];
	CreateRawUdpPacket(szBuffer,uCode,dmac,uDIp,pSendData);

	NdisAllocateBuffer(&Status,&pNdisBuffer,g_BufferPool,szBuffer,
		sizeof(SEth)+sizeof(SIp)+sizeof(SUdp)+sizeof(SDrvPkt));
//	PMDL pBuffer=IoAllocateMdl(szPacket,VDPACKET_LEN,FALSE,FALSE,NULL);

	if (pNdisBuffer == NULL)
	{
		DbgPrint("SendVDPacket: unable to allocate the MDL.\n");
		return;
	}
	
	NdisAllocatePacket(&Status, &pPacket, g_PacketPool);
	if (Status != NDIS_STATUS_SUCCESS)
	{
		NdisFreeBuffer(pNdisBuffer);
		return;
	}

//	MmBuildMdlForNonPagedPool(pBuffer);	// XXX can this line be removed?
//	pBuffer->Next = NULL;
	NdisChainBufferAtFront(pPacket,pNdisBuffer);

	NdisSend(&Status,NdisBindHandle,pPacket);
//	DbgPrint("SendVDPacket code=%d Status=%d",uCode,Status);
	if(Status!=NDIS_STATUS_PENDING)
	{
		SendVDPacketComplt(pPacket);
	}
}

//通过所有TCPIP NdisBindHandle发送包,nCode:发送交易码,dmac:目标MAC,uDIp:目标IP,pSendData:要发送数据
void SendAllBindVDPacket(UCHAR uCode,UCHAR dmac[],ULONG uDIp,const void *pSendData)
{
	int j;

	for(j=0;j<g_nTcpIpBindNum;j++)
	{
		SendVDPacket(g_pTcpIpBindHandles[j]->NdisBindingHandle,uCode,dmac,uDIp,pSendData);
	}
}

//通知所有连接的主机,本机已经下线
void DeclineAllMac()
{
	ULONG uCurTime=GetSystemTime();
	int i;

	for(i=0;i<g_maccount;i++)
	{
		if(MAC_OK(uCurTime,&g_macs[i]))
		{
			SendAllBindVDPacket(MAC_DECLINE,g_macs[i].mac,g_macs[i].ip,NULL);
		}
	}
}

//主接收包过滤器
NDIS_STATUS FilterRecv(PNDIS_PACKET inPacket,SEth *pEth,SIp *pIp,UINT IpLen)
{
	ULONG uRead;
	SEth eth;
	SUdp udp,*pUdp=NULL;
	SMac *pMac=NULL;
	ULONG uSIp;

	//取以太头
	if(inPacket)
	{
		ReadOnPacket(inPacket,(UCHAR*)&eth,sizeof(eth),0,&uRead);
		pEth=&eth;
	}
	if(pEth==NULL) return NDIS_STATUS_NOT_ACCEPTED;

	if(LimitProxy()
#ifdef _WIN32_WINNT
		&& g_bHookSend
#endif
		)
	{
		//若限制代理,则判断收到包源MAC是否与上线MAC相同
		if(memcmp(pEth->smac,g_onlinemac,6)==0 && memcmp(pEth->dmac,g_onlinemac,6)!=0)
		{
			//是否是广播包或多播包
			int bStop=!IsBroadcastExMac(pEth->dmac);

			if(!bStop)	//是,则通过接收时间判断是否是本机发的包
			{
				ULONG uSub=GetMSTime()-g_sendbrdtm;
				bStop=uSub>500;
				if(bStop) DbgPrint("Mac err sub time=%d",uSub);
			}
			else	//不是,那就是其它机器发的包
				PrintMac("Mac err dmac",pEth->dmac);

			if(bStop)
			{
				NotifyStopProc(NULL,SPWHY_MAC);	//通知客户端MAC出错
				return NDIS_STATUS_NOT_ACCEPTED;
			}
		}
	}

	if(pEth->proto!=UTIL_htons(ETH_P_IP)) return NDIS_STATUS_SUCCESS;

	//取UDP头
	if(inPacket)
	{
		UCHAR proto=0;
		ReadOnPacket(inPacket,&proto,sizeof(proto),sizeof(SEth)+9,&uRead);	//取协议
		if(proto==IPPROTO_UDP)
		{
			ReadOnPacket(inPacket,(UCHAR*)&udp,sizeof(udp),sizeof(SEth)+sizeof(SIp),&uRead);
			pUdp=&udp;
		}
		ReadOnPacket(inPacket,(UCHAR*)&uSIp,sizeof(uSIp),sizeof(SEth)+12,&uRead);	//取源IP
	}
	else if(pIp)
	{
		if(pIp->ip_p==IPPROTO_UDP) pUdp=(SUdp*)(pIp+1);
		uSIp=pIp->ip_src;
	}

	if(pUdp)
	{
		if(pUdp->sport==UTIL_htons(67) && pUdp->dport==UTIL_htons(68))	//DHCP
		{
			char mydhcp[256];
			char buf[sizeof(mydhcp)+MAX_RAND1+MAX_RAND4+32];
			int nVarLen=0;
			USHORT ip_len=pIp ? UTIL_htons(pIp->ip_len) : IpLen;
			if(IpLen<ip_len) return NDIS_STATUS_SUCCESS;

			//取AS发的MYDHCP
			if(inPacket)
			{
				ReadOnPacket(inPacket,buf,sizeof(buf),
					sizeof(SEth)+sizeof(SIp)+sizeof(SUdp),&uRead);
				nVarLen=DecryptVarLenPacket(buf,uRead,mydhcp,sizeof(mydhcp));
			}
			else if(ip_len>=(sizeof(SIp)+sizeof(SUdp)+sizeof(SMyDhcp)))
			{
				nVarLen=DecryptVarLenPacket((UCHAR*)(pUdp+1),ip_len-sizeof(SIp)-sizeof(SUdp),
					mydhcp,sizeof(mydhcp));
			}

//			DbgPrint("Is Dhcp inPacket=%X,IpLen=%d,ip_len=%d,nVarLen=%d\n",
//				inPacket,IpLen,ip_len,nVarLen);

			if(nVarLen>0)	//获取成功,更新g_mydhcp
			{
				memcpy(&g_mydhcp,mydhcp,sizeof(g_mydhcp));
				g_md_time=GetSystemTime();
				return NDIS_STATUS_NOT_ACCEPTED;
			}

			if(g_bOnline && RecvMyDhcp())	//DHCP保护
			{
				return (uSIp==0x58585858) ? NDIS_STATUS_SUCCESS : NDIS_STATUS_NOT_ACCEPTED;
			}
		}

		if( pUdp->dport==pUdp->sport && pUdp->dport==MAC_PORT && LimitProxy() )
		{
			SDrvPkt drvpkt,*pDrvPkt=NULL;

			if(inPacket)
			{
				ReadOnPacket(inPacket,(UCHAR*)&drvpkt,sizeof(drvpkt),
					sizeof(SEth)+sizeof(SIp)+sizeof(SUdp),&uRead);
				pDrvPkt=&drvpkt;
			}
			else if(IpLen>=(sizeof(SIp)+sizeof(SUdp)+sizeof(SDrvPkt)))
			{
				pDrvPkt=(SDrvPkt*)(pUdp+1);
			}

			if(pDrvPkt==NULL) return NDIS_STATUS_SUCCESS;

			//接收到其它机器的交易包
			switch(pDrvPkt->nCode)
			{
			case MAC_REQUEST:
				if(memcmp(pDrvPkt->proxy.mac1,g_onlinemac,6)==0)
				{
					SendAllBindVDPacket(MAC_REPLY,pEth->smac,uSIp,NULL);

					if(pDrvPkt->proxy.nCode==MAC_REPLY)
					{
						AddMac(pDrvPkt->proxy.mac2,uSIp,TRUE);
					}
				}
				break;
			case MAC_REPLY:
				AddMac(pDrvPkt->proxy.mac1,uSIp,TRUE);
				break;
			case MAC_DECLINE:
				{
					int nPos;
					SMac *pMac=FindMac(pDrvPkt->proxy.mac1,&nPos);
					if(pMac)
					{
						pMac->oktime=0;
					//	DelMac(pData->mac);
					}
				}
				break;
			}

			return NDIS_STATUS_NOT_ACCEPTED;
		}
	}

	if(!LimitProxy()) return NDIS_STATUS_SUCCESS;
	if(uSIp==0x58585858) return NDIS_STATUS_SUCCESS;

	//如果限制代理,则必须都上线才能相互通讯
	if(memcmp(g_brdctmac,pEth->dmac,6)==0) return NDIS_STATUS_SUCCESS;
	if(memcmp(g_onlinemac,pEth->dmac,6)!=0) return NDIS_STATUS_NOT_ACCEPTED;
	if(memcmp(g_gwmac,pEth->smac,6)==0) return NDIS_STATUS_SUCCESS;

	pMac=AddMac(pEth->smac,uSIp,FALSE);
	if(pMac)
	{
		ULONG uCurTime=GetSystemTime();
//		DbgPrint("uCurTime=%d,pMac->oktime=%d",uCurTime,pMac->oktime);
		if(MAC_OK(uCurTime,pMac))
		{
			if(MAC_CHKOK(uCurTime,pMac))	//判断有效时间是否快到期
			{
//				PrintMac("PreMAC_REQUEST",pMac->mac);
				SendAllBindVDPacket(MAC_REQUEST,pEth->smac,uSIp,NULL);	//提前查询
			}
			return NDIS_STATUS_SUCCESS;
		}
		if(uCurTime-pMac->chktime<=3) return NDIS_STATUS_NOT_ACCEPTED;
		pMac->chktime=uCurTime;

		//发送查询请求
//		PrintMac("MAC_REQUEST",pMac->mac);
		SendAllBindVDPacket(MAC_REQUEST,pEth->smac,uSIp,NULL);
	}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -