📄 protocol.c
字号:
NdisMSendComplete(pAdapt->MiniportHandle,
Packet,
Status);
}
else
#endif // NDIS51
{
PSEND_RSVD SendRsvd;
SendRsvd = (PSEND_RSVD)(Packet->ProtocolReserved);
Pkt = SendRsvd->OriginalPkt;
#ifndef WIN9X
NdisIMCopySendCompletePerPacketInfo (Pkt, Packet);
#endif
NdisDprFreePacket(Packet);
NdisMSendComplete(pAdapt->MiniportHandle,
Pkt,
Status);
}
//
// Decrease the outstanding send count
//
ADAPT_DECR_PENDING_SENDS(pAdapt);
}
VOID
PtTransferDataComplete(
IN NDIS_HANDLE ProtocolBindingContext,
IN PNDIS_PACKET Packet,
IN NDIS_STATUS Status,
IN UINT BytesTransferred
)
/*++
Routine Description:
Entry point called by NDIS to indicate completion of a call by us
to NdisTransferData.
See notes under SendComplete.
Arguments:
Return Value:
--*/
{
PADAPT pAdapt =(PADAPT)ProtocolBindingContext;
if(pAdapt->MiniportHandle)
{
NdisMTransferDataComplete(pAdapt->MiniportHandle,
Packet,
Status,
BytesTransferred);
}
}
// 读取封包中的数据
VOID
FltReadPacketData(
IN PNDIS_PACKET pPacket,
OUT PUCHAR lpBufferIn)
{
PUCHAR pBuf;
UINT BufLength;
MDL *pNext;
UINT i;
if(pPacket == NULL || lpBufferIn == NULL)
{
DbgPrint("FltReadPacketData: Non-Input!");
return;
}
NdisQueryBufferSafe(pPacket->Private.Head, &pBuf, &BufLength, NormalPagePriority);
NdisMoveMemory(lpBufferIn, pBuf, BufLength);
i = BufLength;
pNext = pPacket->Private.Head;
for(;;)
{
if(pNext == pPacket->Private.Tail)
break;
pNext = pNext->Next; //指针后移
if(pNext == NULL)
break;
NdisQueryBufferSafe(pNext, &pBuf, &BufLength, NormalPagePriority);
NdisMoveMemory(lpBufferIn+i, pBuf, BufLength);
i+=BufLength;
} //End for
}
//过滤函数
BOOLEAN
CheckPacket(
IN PADAPT pAdapt,
IN PUCHAR pPacketContent, //包含数据包全部内容的指针
IN UINT Interface, //接口的代号
IN UINT HeaderLen
)
{
PUCHAR str1="HTTP/",str2,str3,str4,str5,str6;
PUCHAR pstr;
UINT IpLen,TcpLen;//IP和TCP的首部长度
UINT i=0, j=0;
struct node *tmp_head;
NdisDprAcquireSpinLock(&pAdapt->Lock); //获取旋转锁,保持多处理器下数据同步。
//DbgPrint("%d: %d,%d", Interface, (((char *)pPacketContent)[HeaderLen-2] & 0xff), (((char *)pPacketContent)[HeaderLen-1] & 0xff));
//获得IP首部和TCP首部长度
if((((char *)pPacketContent)[HeaderLen-2] & 0xff) == 8 && //如果是IP协议
(((char *)pPacketContent)[HeaderLen-1] & 0xff) == 0 &&
(((char *)pPacketContent)[HeaderLen+9] & 0xff) == 6) //如果是TCP协议
{
IpLen=4*(((char *)pPacketContent)[HeaderLen] & 0xf);
TcpLen=(((char *)pPacketContent)[HeaderLen+IpLen+12] & 0xf0) / 4;
//DbgPrint("%d: I=%d, T=%d", Interface, IpLen, TcpLen);
//反伪造二次握手
if(((char *)pPacketContent)[HeaderLen+IpLen+4] == 0 && //SEQ占用的第一个字节,以太头+IP头+4字节
((char *)pPacketContent)[HeaderLen+IpLen+5] == 0 &&
((char *)pPacketContent)[HeaderLen+IpLen+6] == 0 &&
((char *)pPacketContent)[HeaderLen+IpLen+7] == 1) //SEQ占用的最第四字节
{
DbgPrint("%d: TCP RST Attack Blocked!", Interface);
NdisDprReleaseSpinLock(&pAdapt->Lock);
return FALSE;
} //End_反伪造二次握手
//反插入广告
if(((char *)pPacketContent)[HeaderLen+IpLen] == 0 && //源端口=以太头+IP头长 后面的2字节
((char *)pPacketContent)[HeaderLen+IpLen+1] == 80)
{
//DbgPrint("%d: Port=80", Interface);
pstr=pPacketContent+HeaderLen+IpLen+TcpLen; //以太网头+IP首部+TCP首部
if(strstr((char *)pstr,(char *)str1)!=NULL) //如果是HTTP协议
{
//DbgPrint("%d: %s", Interface, pstr);
pstr=pstr+9; // 跳过对HTTP版本的再次匹配
str2="200 OK";
str3="302 ";
str4="Date:";
str5="Server:";
str6="no-cache";
if(strstr((char *)pstr,(char *)str2)!=NULL || strstr((char *)pstr,(char *)str3)!=NULL) //检查HTTP状态代码
{
if(strstr((char *)pstr,(char *)str6)!=NULL &&
//strstr((char *)pstr,(char *)str5)==NULL &&
strstr((char *)pstr,(char *)str4)==NULL) //检查可疑的HTTP首部_A
{
//DbgPrint("%d: HTTP Header A Found", Interface);
tmp_head=buffer_head->next; //建立一个链表的副本
while (tmp_head!=0) //循环遍历链表内容
{
if(strstr((char *)pstr, (char *)tmp_head->buffer)!=NULL)
{
DbgPrint("%d: AD_A Attack Blocked!... IpLen=%d,TcpLen=%d\n%s", Interface, IpLen, TcpLen, (char *)pstr);
NdisDprReleaseSpinLock(&pAdapt->Lock);
return FALSE;
}
tmp_head=tmp_head->next;
}
} //End_检查可疑的HTTP首部_A
//DbgPrint("%s", buffer_head->buffer);
if(strstr((char *)buffer_head->buffer, "1")) //强制匹配模式
{
//DbgPrint("WARNING: FILTER DRIVER NOW RUN IN MODE C!!!");
tmp_head=buffer_head->next;
while (tmp_head!=0)
{
if(strstr((char *)pstr, (char *)tmp_head->buffer)!=NULL)
{
DbgPrint("%d: AD_C Attack Blocked!... IpLen=%d,TcpLen=%d\n%s", Interface, IpLen, TcpLen, (char *)pstr);
NdisDprReleaseSpinLock(&pAdapt->Lock);
return FALSE;
}
tmp_head=tmp_head->next;
}
}
} //End_检查HTTP状态代码
} //End_如果是HTTP协议
//反伪造RST报文
if((((char *)pPacketContent)[HeaderLen+IpLen+13] & 0x04)== 4 && //MacLen+IPLen+4*3+1
((char *)pPacketContent)[HeaderLen+4] == 0) //IP标识在IP首部第5/6字节,GFW发送(十六进制)[00 40]和[00 81]
{
//DbgPrint("%d: RST Pkt Ide=%d", Interface, ((char *)pPacketContent)[19] & 0xff);
if((((char *)pPacketContent)[HeaderLen+5] & 0xff) == 0x40 ||
(((char *)pPacketContent)[HeaderLen+5] & 0xff) == 0x81 ||
(((char *)pPacketContent)[HeaderLen+5] & 0xff) == 0x00 ||
(((char *)pPacketContent)[HeaderLen+5] & 0xff) == 0x01 ||
(((char *)pPacketContent)[HeaderLen+5] & 0xff) == 0x02)
{
DbgPrint("%d: RST Packet Blocked!... Identification=%d", Interface, ((char *)pPacketContent)[HeaderLen+5] & 0xff);
NdisDprReleaseSpinLock(&pAdapt->Lock);
return FALSE;
}
}
//反伪造RST报文 RST且TCP紧急指针总是00 01
if((((char *)pPacketContent)[HeaderLen+IpLen+13] & 0x04) == 4 &&
(((char *)pPacketContent)[HeaderLen+IpLen+18] & 0xff) == 0x00 && //HeaderLen+IpLen+20-2
(((char *)pPacketContent)[HeaderLen+IpLen+19] & 0xff) == 0x01) //HeaderLen+IpLen+20-1
{
DbgPrint("%d: RST Packet Blocked!", Interface);
NdisDprReleaseSpinLock(&pAdapt->Lock);
return FALSE;
}
//阻止所有RST包
if((((char *)pPacketContent)[27+IpLen] & 0x04) == 4)
{
DbgPrint("%d: Blocked All RST Packet!", Interface);
NdisDprReleaseSpinLock(&pAdapt->Lock);
return FALSE;
}
} //End_反插入广告
} //End_获得IP首部和TCP首部长度
NdisDprReleaseSpinLock(&pAdapt->Lock);
return TRUE;
} //End_过滤函数
NDIS_STATUS
PtReceive(
IN NDIS_HANDLE ProtocolBindingContext,
IN NDIS_HANDLE MacReceiveContext,
IN PVOID HeaderBuffer,
IN UINT HeaderBufferSize,
IN PVOID LookAheadBuffer,
IN UINT LookAheadBufferSize,
IN UINT PacketSize
)
/*++
Routine Description:
Handle receive data indicated up by the miniport below. We pass
it along to the protocol above us.
If the miniport below indicates packets, NDIS would more
likely call us at our ReceivePacket handler. However we
might be called here in certain situations even though
the miniport below has indicated a receive packet, e.g.
if the miniport had set packet status to NDIS_STATUS_RESOURCES.
Arguments:
<see DDK ref page for ProtocolReceive>
Return Value:
NDIS_STATUS_SUCCESS if we processed the receive successfully,
NDIS_STATUS_XXX error code if we discarded it.
--*/
{
PADAPT pAdapt = (PADAPT)ProtocolBindingContext;
PNDIS_PACKET MyPacket, Packet = NULL;
NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
PUCHAR pPacketContent;
UINT PacketLen, BytesTransferred;
//DbgPrint("1: In PtReceive");
//DbgPrint("1: HeaderSize=%d", HeaderBufferSize);
if ((!pAdapt->MiniportHandle) || (pAdapt->MPDeviceState > NdisDeviceStateD0))
{
Status = NDIS_STATUS_FAILURE;
}
else do
{
//
// Get at the packet, if any, indicated up by the miniport below.
//
Packet = NdisGetReceivedPacket(pAdapt->BindingHandle, MacReceiveContext); //如果成功,所有数据会在这个Packet中。
Status = NdisAllocateMemoryWithTag(&pPacketContent, 2000, 'maDN'); //For xp and later
if(Status!=NDIS_STATUS_SUCCESS)
{
DbgPrint("1: Status != Success...");
return Status;
}
if(pPacketContent == NULL)
{
DbgPrint("1: pPacketContent == NULL");
return Status;
}
NdisZeroMemory(pPacketContent, 2000); //初始化内存空间
if (Packet != NULL)
{
//DbgPrint("10: Packet Mode!");
//NdisQueryPacket(Packet, NULL, NULL, NULL, &PacketLen);
FltReadPacketData(Packet, pPacketContent); //读取PNDIS_PACKET结构,存放到pPacketContent
if(CheckPacket(pAdapt, pPacketContent, 10, HeaderBufferSize)==FALSE) //检查过滤规则,匹配就丢包
{
Status=NDIS_STATUS_SUCCESS;
NdisFreeMemory(pPacketContent, 2000, 0); //释放内存
break;
}
NdisFreeMemory(pPacketContent, 2000, 0); //释放内存
//
// The miniport below did indicate up a packet. Use information
// from that packet to construct a new packet to indicate up.
//
#ifdef NDIS51
//
// NDIS 5.1 NOTE: Do not reuse the original packet in indicating
// up a receive, even if there is sufficient packet stack space.
// If we had to do so, we would have had to overwrite the
// status field in the original packet to NDIS_STATUS_RESOURCES,
// and it is not allowed for protocols to overwrite this field
// in received packets.
//
#endif // NDIS51
//
// Get a packet off the pool and indicate that up
//
NdisDprAllocatePacket(&Status,
&MyPacket,
pAdapt->RecvPacketPoolHandle);
if (Status == NDIS_STATUS_SUCCESS)
{
//
// Make our packet point to data from the original
// packet. NOTE: this works only because we are
// indicating a receive directly from the context of
// our receive indication. If we need to queue this
// packet and indicate it from another thread context,
// we will also have to allocate a new buffer and copy
// over the packet contents, OOB data and per-packet
// information. This is because the packet data
// is available only for the duration of this
// receive indication call.
//
NDIS_PACKET_FIRST_NDIS_BUFFER(MyPacket) = NDIS_PACKET_FIRST_NDIS_BUFFER(Packet);
NDIS_PACKET_LAST_NDIS_BUFFER(MyPacket) = NDIS_PACKET_LAST_NDIS_BUFFER(Packet);
//
// Get the original packet (it could be the same packet as the
// one received or a different one based on the number of layered
// miniports below) and set it on the indicated packet so the OOB
// data is visible correctly at protocols above.
//
NDIS_SET_ORIGINAL_PACKET(MyPacket, NDIS_GET_ORIGINAL_PACKET(Packet));
NDIS_SET_PACKET_HEADER_SIZE(MyPacket, HeaderBufferSize);
//
// Copy packet flags.
//
NdisGetPacketFlags(MyPacket) = NdisGetPacketFlags(Packet);
//
// Force protocols above to make a copy if they want to hang
// on to data in this packet. This is because we are in our
// Receive handler (not ReceivePacket) and we can't return a
// ref count from here.
//
NDIS_SET_PACKET_STATUS(MyPacket, NDIS_STATUS_RESOURCES);
//
// By setting NDIS_STATUS_RESOURCES, we also know that we can reclaim
// this packet as soon as the call to NdisMIndicateReceivePacket
// returns.
//
// NOTE: we queue the packet and indicate this packet immediately with
// the already queued packets together. We have to the queue the packet
// first because some versions of NDIS might call protocols'
// ReceiveHandler(not ReceivePacketHandler) if the packet indicate status
// is NDIS_STATUS_RESOURCES. If the miniport below indicates an array of
// packets, some of them with status NDIS_STATUS_SUCCESS, some of them
// with status NDIS_STATUS_RESOURCES, PtReceive might be called, by
// doing this way, we preserve the receive order of packets.
//
PtQueueReceivedPacket(pAdapt, MyPacket, TRUE);
//
// Reclaim the indicated packet. Since we had set its status
// to NDIS_STATUS_RESOURCES, we are guaranteed that protocols
// above are done with it.
//
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -