📄 filterpkt.c
字号:
////////////////////////////////////////
// 该文件是具体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*)ð,sizeof(eth),0,&uRead);
pEth=ð
}
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 + -