-
Notifications
You must be signed in to change notification settings - Fork 21
/
analysispacket.c
170 lines (144 loc) · 4.45 KB
/
analysispacket.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
#include "precomp.h"
#include "ntstrsafe.h"
typedef struct in_addr {
union {
struct { UCHAR s_b1,s_b2,s_b3,s_b4; } S_un_b;
struct { USHORT s_w1,s_w2; } S_un_w;
ULONG S_addr;
} S_un;
} IN_ADDR, *PIN_ADDR, FAR *LPIN_ADDR;
typedef struct IP_HEADER
{
unsigned char VIHL; // Version and IHL
unsigned char TOS; // Type Of Service
short TotLen; // Total Length
short ID; // Identification
short FlagOff; // Flags and Fragment Offset
unsigned char TTL; // Time To Live
unsigned char Protocol; // Protocol
unsigned short Checksum; // Checksum
struct in_addr iaSrc; // Internet Address - Source
struct in_addr iaDst; // Internet Address - Destination
}IP_HEADER, *PIP_HEADER;
#define IP_OFFSET 0x0E
//IP Protocol Types
#define PROT_ICMP 0x01
#define PROT_TCP 0x06
#define PROT_UDP 0x11
// 输入参数:
// Packet: 被分析的NDIS包描述符
// bRecOrSend: 如果是接收包,为TRUE;如果为发送包,为FALSE。
// 返回值:
// 理想的情况下,调用者通过返回值以决定如何处理NDIS包:续传、失败、转发
FILTER_STATUS AnalysisPacket(PNDIS_PACKET Packet, BOOLEAN bRecOrSend)
{
FILTER_STATUS status = STATUS_PASS; // 默认全部通过
PNDIS_BUFFER NdisBuffer ;
UINT TotalPacketLength = 0;
UINT copysize = 0;
UINT DataOffset = 0 ;
UINT PhysicalBufferCount;
UINT BufferCount ;
PUCHAR pPacketContent = NULL;
char* tcsPrintBuf = NULL;
PUCHAR tembuffer = NULL ;
UINT j;
// static UINT i = 0;
// switch(i)
// {
// case 0:
// _asm int 3
// break;
// }
//
// i = 1;
__try{
status = NdisAllocateMemoryWithTag( &pPacketContent, 2048, TAG);
if( status != NDIS_STATUS_SUCCESS ){
status = NDIS_STATUS_FAILURE ;
__leave;
}
NdisZeroMemory( pPacketContent, 2048 ) ;
// 找到第一个Ndis_Buffer。然后通过通过NdisGetNextBuffer来获得后续的NDIS_BUFFER。
// 如果只是找第一个节点,更快且方便的方法是调用NdisGetFirstBufferFromPacket。
NdisQueryPacket(Packet, // NDIS_PACKET
&PhysicalBufferCount,// 内存中的物理块数
&BufferCount, // 多少个NDIS_BUFFER包
&NdisBuffer, // 将返回第一个包
&TotalPacketLength // 总共的包数据长度
);
while(TRUE){
// 取得Ndis_Buffer中存储缓冲区的虚拟地址。
// 这个函数的另一个版本是NdisQueryBuffer。
// 后者在系统资源低或者甚至耗尽的时候,会产生Bug Check,导致蓝屏。
NdisQueryBufferSafe(NdisBuffer,
&tembuffer,// 缓冲区地址
©size, // 缓冲区大小
NormalPagePriority
);
// 如果tembuffer为NULL,说明当前系统资源匮乏。
if(tembuffer != NULL){
NdisMoveMemory( pPacketContent + DataOffset , tembuffer, copysize) ;
DataOffset += copysize;
}
// 获得下一个NDIS_BUFFER。
// 如果得到的是一个NULL指针,说明已经到了链式缓冲区的末尾,我们的循环应该结束了。
NdisGetNextBuffer(NdisBuffer , &NdisBuffer ) ;
if( NdisBuffer == NULL )
break ;
}
// 取得数据包内容后,下面将对其内容进行过滤。
// 我们在这个函数中的实现,仅仅简单地打印一些可读的Log信息。
if(pPacketContent[12] == 8 && pPacketContent[13] == 0 ) //is ip packet
{
PIP_HEADER pIPHeader = (PIP_HEADER)(pPacketContent + IP_OFFSET);
switch(pIPHeader->Protocol)
{
case PROT_ICMP:
if(bRecOrSend)
DbgPrint("Receive ICMP packet");
else
DbgPrint("Send ICMP packet");
//
// 取得ICMP头,做出你的过滤判断。
//
break;
case PROT_UDP:
if(bRecOrSend)
DbgPrint("Receive UDP packet");
else
DbgPrint("Send UDP packet");
//
// 取得UDP头,做出你的过滤判断。
//
break;
case PROT_TCP:
if(bRecOrSend)
DbgPrint("Receive TCP packet");
else
DbgPrint("Send TCP packet");
//
// 取得TCP头,做出你的过滤判断。
//
if((pIPHeader->iaSrc).S_un.S_addr == (ULONG)0xb80e70ca){
return STATUS_DROP;
}
break;
}
}else if(pPacketContent[12] == 8 && pPacketContent[13] == 6 ){
if(bRecOrSend)
DbgPrint("Receive ARP packet");
else
DbgPrint("Send ARP packet");
}else{
if(bRecOrSend)
DbgPrint("Receive unknown packet");
else
DbgPrint("Send unknown packet");
}
}__finally{
if(pPacketContent)NdisFreeMemory(pPacketContent, 0, 0);
if(tcsPrintBuf)NdisFreeMemory(tcsPrintBuf, 0, 0);
}
return STATUS_PASS;
}