/ |
02 | // DrvFltIp.h文件 |
03 | |
04 | #ifndef __DRVFLTIP_H__ |
05 | #define __DRVFLTIP_H__ |
06 | |
07 | // 自定义设备类型,在创建设备对象时使用 |
08 | // 注意,自定义值的范围是32768-65535 |
09 | #define FILE_DEVICE_DRVFLTIP 0x00654322 |
10 | |
11 | // 自定义的IO控制代码,用于区分不同的设备控制请求 |
12 | // 注意,自定义值的范围是2048-4095 |
13 | #define DRVFLTIP_IOCTL_INDEX 0x830 |
14 | |
15 | // |
16 | // 定义各种设备控制代码。分别是开始过滤、停止过滤、添加过滤规则、清除过滤规则 |
17 | // |
18 | #define START_IP_HOOK CTL_CODE(FILE_DEVICE_DRVFLTIP, \ |
19 | DRVFLTIP_IOCTL_INDEX, METHOD_BUFFERED, FILE_ANY_ACCESS) |
20 | #define STOP_IP_HOOK CTL_CODE(FILE_DEVICE_DRVFLTIP, \ |
21 | DRVFLTIP_IOCTL_INDEX+1, METHOD_BUFFERED, FILE_ANY_ACCESS) |
22 | #define ADD_FILTER CTL_CODE(FILE_DEVICE_DRVFLTIP, \ |
23 | DRVFLTIP_IOCTL_INDEX+2, METHOD_BUFFERED, FILE_WRITE_ACCESS) |
24 | #define CLEAR_FILTER CTL_CODE(FILE_DEVICE_DRVFLTIP, \ |
25 | DRVFLTIP_IOCTL_INDEX+3, METHOD_BUFFERED, FILE_ANY_ACCESS) |
26 | |
27 | // 定义过滤规则的结构 |
28 | struct CIPFilter |
29 | { |
30 | USHORT protocol; // 使用的协议 |
31 | |
32 | ULONG sourceIP; // 源IP地址 |
33 | ULONG destinationIP; // 目标IP地址 |
34 | |
35 | ULONG sourceMask; // 源地址屏蔽码 |
36 | ULONG destinationMask; // 目的地址屏蔽码 |
37 | |
38 | USHORT sourcePort; // 源端口号 |
39 | USHORT destinationPort; // 目的端口号 |
40 | |
41 | BOOLEAN bDrop; // 是否丢弃此封包 |
42 | }; |
43 | |
44 | #endif // __DRVFLTIP_H__ |
[文件] internal.h ~ 1KB 下载(53)
01 | /// |
02 | // internal.h文件 |
03 | |
04 | |
05 | // 过滤列表 |
06 | struct CFilterList |
07 | { |
08 | CIPFilter ipf; // 过滤规则 |
09 | CFilterList* pNext; // 指向下一个CFilterList结构 |
10 | }; |
11 | |
12 | typedef struct IPHeader |
13 | { |
14 | UCHAR iphVerLen; // 版本号和头长度(各占4位) |
15 | UCHAR ipTOS; // 服务类型 |
16 | USHORT ipLength; // 封包总长度,即整个IP报的长度 |
17 | USHORT ipID; // 封包标识,惟一标识发送的每一个数据报 |
18 | USHORT ipFlags; // 标志 |
19 | UCHAR ipTTL; // 生存时间,就是TTL |
20 | UCHAR ipProtocol; // 协议,可能是TCP、UDP、ICMP等 |
21 | USHORT ipChecksum; // 校验和 |
22 | ULONG ipSource; // 源IP地址 |
23 | ULONG ipDestination; // 目标IP地址 |
24 | } IPPacket; |
25 | |
26 | |
27 | typedef struct _TCPHeader |
28 | { |
29 | USHORT sourcePort; // 源端口号 |
30 | USHORT destinationPort; // 目的端口号 |
31 | ULONG sequenceNumber; // 序号 |
32 | ULONG acknowledgeNumber; // 确认序号 |
33 | UCHAR dataoffset; // 数据指针 |
34 | UCHAR flags; // 标志 |
35 | USHORT windows; // 窗口大小 |
36 | USHORT checksum; // 校验和 |
37 | USHORT urgentPointer; // 紧急指针 |
38 | } TCPHeader; |
39 | |
40 | typedef struct _UDPHeader |
41 | { |
42 | USHORT sourcePort; // 源端口号 |
43 | USHORT destinationPort; // 目的端口号 |
44 | USHORT len; // 封包长度 |
45 | USHORT checksum; // 校验和 |
46 | } UDPHeader; |
[文件] DrvFltIp.cpp ~ 9KB 下载(48)
001 | // DrvFltIp.cpp文件 |
002 | |
003 | |
004 | extern "C" |
005 | { |
006 | #include <ntddk.h> |
007 | #include <ntddndis.h> |
008 | #include <pfhook.h> |
009 | } |
010 | |
011 | #include "DrvFltIp.h" |
012 | #include "internal.h" |
013 | |
014 | // 自定义函数的声明 |
015 | NTSTATUS DispatchCreateClose(PDEVICE_OBJECT pDevObj, PIRP pIrp); |
016 | void DriverUnload(PDRIVER_OBJECT pDriverObj); |
017 | NTSTATUS DispatchIoctl(PDEVICE_OBJECT pDevObj, PIRP pIrp); |
018 | NTSTATUS AddFilterToList(CIPFilter* pFilter); |
019 | void ClearFilterList(); |
020 | NTSTATUS SetFilterFunction(PacketFilterExtensionPtr filterFun); |
021 | PF_FORWARD_ACTION FilterPackets(unsigned char *, unsigned char *, unsigned int , unsigned int , unsigned int , IPAddr, IPAddr); |
022 | |
023 | // 过滤列表首地址 |
024 | struct CFilterList* g_pHeader = NULL; |
025 | |
026 | |
027 | // 驱动内部名称和符号连接名称 |
028 | #define DEVICE_NAME L"\\Device\\devDrvFltIp" |
029 | #define LINK_NAME L"\\??\\DrvFltIp" |
030 | |
031 | |
032 | NTSTATUS DriverEntry(PDRIVER_OBJECT pDriverObj, PUNICODE_STRING pRegistryString) |
033 | { |
034 | NTSTATUS status = STATUS_SUCCESS; |
035 | |
036 | // 初始化各个派遣例程 |
037 | pDriverObj->MajorFunction[IRP_MJ_CREATE] = DispatchCreateClose; |
038 | pDriverObj->MajorFunction[IRP_MJ_CLOSE] = DispatchCreateClose; |
039 | pDriverObj->MajorFunction[IRP_MJ_DEVICE_CONTROL] = DispatchIoctl; |
040 | pDriverObj->DriverUnload = DriverUnload; |
041 | |
042 | // 创建、初始化设备对象 |
043 | // 设备名称 |
044 | UNICODE_STRING ustrDevName; |
045 | RtlInitUnicodeString(&ustrDevName, DEVICE_NAME); |
046 | // 创建设备对象 |
047 | PDEVICE_OBJECT pDevObj; |
048 | status = IoCreateDevice(pDriverObj, |
049 | 0, |
050 | &ustrDevName, |
051 | FILE_DEVICE_DRVFLTIP, |
052 | 0, |
053 | FALSE, |
054 | &pDevObj); |
055 | if (!NT_SUCCESS(status)) |
056 | { |
057 | return status; |
058 | } |
059 | |
060 | // 创建符号连接名称 |
061 | // 符号连接名称 |
062 | UNICODE_STRING ustrLinkName; |
063 | RtlInitUnicodeString(&ustrLinkName, LINK_NAME); |
064 | // 创建关联 |
065 | status = IoCreateSymbolicLink(&ustrLinkName, &ustrDevName); |
066 | if (!NT_SUCCESS(status)) |
067 | { |
068 | IoDeleteDevice(pDevObj); |
069 | return status; |
070 | } |
071 | |
072 | return STATUS_SUCCESS; |
073 | } |
074 | |
075 | |
076 | void DriverUnload(PDRIVER_OBJECT pDriverObj) |
077 | { |
078 | // 卸载过滤函数 |
079 | SetFilterFunction(NULL); |
080 | // 释放所有资源 |
081 | ClearFilterList(); |
082 | |
083 | // 删除符号连接名称 |
084 | UNICODE_STRING strLink; |
085 | RtlInitUnicodeString(&strLink, LINK_NAME); |
086 | IoDeleteSymbolicLink(&strLink); |
087 | |
088 | // 删除设备对象 |
089 | IoDeleteDevice(pDriverObj->DeviceObject); |
090 | } |
091 | |
092 | // 处理IRP_MJ_CREATE、IRP_MJ_CLOSE功能代码 |
093 | NTSTATUS DispatchCreateClose(PDEVICE_OBJECT pDevObj, PIRP pIrp) |
094 | { |
095 | pIrp->IoStatus.Status = STATUS_SUCCESS; |
096 | // pIrp->IoStatus.Information = 0; |
097 | // 完成此请求 |
098 | IoCompleteRequest(pIrp, IO_NO_INCREMENT); |
099 | |
100 | return STATUS_SUCCESS; |
101 | } |
102 | |
103 | |
104 | // I/O控制派遣例程 |
105 | NTSTATUS DispatchIoctl(PDEVICE_OBJECT pDevObj, PIRP pIrp) |
106 | { |
107 | NTSTATUS status = STATUS_SUCCESS; |
108 | |
109 | // 取得此IRP(pIrp)的I/O堆栈指针 |
110 | PIO_STACK_LOCATION pIrpStack = IoGetCurrentIrpStackLocation(pIrp); |
111 | |
112 | // 取得I/O控制代码 |
113 | ULONG uIoControlCode = pIrpStack->Parameters.DeviceIoControl.IoControlCode; |
114 | // 取得I/O缓冲区指针和它的长度 |
115 | PVOID pIoBuffer = pIrp->AssociatedIrp.SystemBuffer; |
116 | ULONG uInSize = pIrpStack->Parameters.DeviceIoControl.InputBufferLength; |
117 | |
118 | // 响应用户的命令 |
119 | switch (uIoControlCode) |
120 | { |
121 | case START_IP_HOOK: // 开始过滤 |
122 | status = SetFilterFunction(FilterPackets); |
123 | break ; |
124 | |
125 | case STOP_IP_HOOK: // 停止过滤 |
126 | status = SetFilterFunction(NULL); |
127 | break ; |
128 | |
129 | case ADD_FILTER: // 添加一个过滤规则 |
130 | if (uInSize == sizeof (CIPFilter)) |
131 | status = AddFilterToList((CIPFilter*)pIoBuffer); |
132 | else |
133 | status = STATUS_INVALID_DEVICE_REQUEST; |
134 | break ; |
135 | |
136 | case CLEAR_FILTER: // 释放过滤规则列表 |
137 | ClearFilterList(); |
138 | break ; |
139 | |
140 | default : |
141 | status = STATUS_INVALID_DEVICE_REQUEST; |
142 | break ; |
143 | } |
144 | |
145 | // 完成请求 |
146 | pIrp->IoStatus.Status = status; |
147 | pIrp->IoStatus.Information = 0; |
148 | IoCompleteRequest(pIrp, IO_NO_INCREMENT); |
149 | |
150 | return status; |
151 | } |
152 | |
153 | |
154 | |
155 | /// |
156 | //过滤列表 |
157 | |
158 | // 向过滤列表中添加一个过滤规则 |
159 | NTSTATUS AddFilterToList(CIPFilter* pFilter) |
160 | { |
161 | // 为新的过滤规则申请内存空间 |
162 | CFilterList* pNew = (CFilterList*)ExAllocatePool(NonPagedPool, sizeof (CFilterList)); |
163 | if (pNew == NULL) |
164 | return STATUS_INSUFFICIENT_RESOURCES; |
165 | |
166 | // 填充这块内存 |
167 | RtlCopyMemory(&pNew->ipf, pFilter, sizeof (CIPFilter)); |
168 | |
169 | // 连接到过滤列表中 |
170 | pNew->pNext = g_pHeader; |
171 | g_pHeader = pNew; |
172 | |
173 | return STATUS_SUCCESS; |
174 | } |
175 | |
176 | // 清除过滤列表 |
177 | void ClearFilterList() |
178 | { |
179 | CFilterList* pNext; |
180 | // 释放过滤列表占用的所有内存 |
181 | while (g_pHeader != NULL) |
182 | { |
183 | pNext = g_pHeader->pNext; |
184 | // 释放内存 |
185 | ExFreePool(g_pHeader); |
186 | g_pHeader = pNext; |
187 | } |
188 | } |
189 | |
190 | |
191 | //过滤函数 |
192 | |
193 | // 过滤钩子回调函数 |
194 | PF_FORWARD_ACTION FilterPackets( |
195 | unsigned char *PacketHeader, |
196 | unsigned char *Packet, |
197 | unsigned int PacketLength, |
198 | unsigned int RecvInterfaceIndex, |
199 | unsigned int SendInterfaceIndex, |
200 | IPAddr RecvLinkNextHop, |
201 | IPAddr SendLinkNextHop) |
202 | { |
203 | // 提取IP头 |
204 | IPHeader* pIPHdr = (IPHeader*)PacketHeader; |
205 | |
206 | if (pIPHdr->ipProtocol == 6) // 是TCP协议? |
207 | { |
208 | // 提取TCP头 |
209 | TCPHeader* pTCPHdr = (TCPHeader*)Packet; |
210 | // 我们接受所有已经建立连接的TCP封包 |
211 | if (!(pTCPHdr->flags & 0x02)) |
212 | { |
213 | return PF_FORWARD; |
214 | } |
215 | } |
216 | |
217 | // 与过滤规则相比较,决定采取的行动 |
218 | CFilterList* pList = g_pHeader; |
219 | while (pList != NULL) |
220 | { |
221 | // 比较协议 |
222 | if (pList->ipf.protocol == 0 || pList->ipf.protocol == pIPHdr->ipProtocol) |
223 | { |
224 | // 查看源IP地址 |
225 | if (pList->ipf.sourceIP != 0 && |
226 | (pList->ipf.sourceIP & pList->ipf.sourceMask) != pIPHdr->ipSource) |
227 | { |
228 | pList = pList->pNext; |
229 | continue ; |
230 | } |
231 | |
232 | // 查看目标IP地址 |
233 | if (pList->ipf.destinationIP != 0 && |
234 | (pList->ipf.destinationIP & pList->ipf.destinationMask) != pIPHdr->ipDestination) |
235 | { |
236 | pList = pList->pNext; |
237 | continue ; |
238 | } |
239 | |
240 | // 如果是TCP封包,查看端口号 |
241 | if (pIPHdr->ipProtocol == 6) |
242 | { |
243 | TCPHeader* pTCPHdr = (TCPHeader*)Packet; |
244 | if (pList->ipf.sourcePort == 0 || pList->ipf.sourcePort == pTCPHdr->sourcePort) |
245 | { |
246 | if (pList->ipf.destinationPort == 0 |
247 | || pList->ipf.destinationPort == pTCPHdr->destinationPort) |
248 | { |
249 | // 现在决定如何处理这个封包 |
250 | if (pList->ipf.bDrop) |
251 | return PF_DROP; |
252 | else |
253 | return PF_FORWARD; |
254 | } |
255 | } |
256 | } |
257 | |
258 | // 如果是UDP封包,查看端口号 |
259 | else if (pIPHdr->ipProtocol == 17) |
260 | { |
261 | UDPHeader* pUDPHdr = (UDPHeader*)Packet; |
262 | if (pList->ipf.sourcePort == 0 || pList->ipf.sourcePort == pUDPHdr->sourcePort) |
263 | { |
264 | if (pList->ipf.destinationPort == 0 |
265 | || pList->ipf.destinationPort == pUDPHdr->destinationPort) |
266 | { |
267 | // 现在决定如何处理这个封包 |
268 | if (pList->ipf.bDrop) |
269 | return PF_DROP; |
270 | else |
271 | return PF_FORWARD; |
272 | } |
273 | } |
274 | } |
275 | else |
276 | { |
277 | // 对于其它封包,我们直接处理 |
278 | if (pList->ipf.bDrop) |
279 | return PF_DROP; |
280 | else |
281 | return PF_FORWARD; |
282 | } |
283 | } |
284 | |
285 | // 比较下一个规则 |
286 | pList = pList->pNext; |
287 | } |
288 | |
289 | // 我们接受所有没有注册的封包 |
290 | return PF_FORWARD; |
291 | } |
292 | |
293 | // 注册钩子回调函数 |
294 | NTSTATUS SetFilterFunction(PacketFilterExtensionPtr filterFun) |
295 | { |
296 | NTSTATUS status = STATUS_SUCCESS; |
297 | |
298 | // 取得IP过滤驱动设备对象。下面代码执行后,pDeviceObj变量将指向IP过滤驱动设备对象 |
299 | PDEVICE_OBJECT pDeviceObj; |
300 | PFILE_OBJECT pFileObj; |
301 | // 初始化IP过滤驱动的名称 |
302 | UNICODE_STRING ustrFilterDriver; |
303 | RtlInitUnicodeString(&ustrFilterDriver, L "\\Device\\IPFILTERDRIVER" ); |
304 | // 取得设备对象指针 |
305 | status = IoGetDeviceObjectPointer(&ustrFilterDriver, FILE_ALL_ACCESS, &pFileObj, &pDeviceObj); |
306 | if (!NT_SUCCESS(status)) |
307 | { |
308 | return status; |
309 | } |
310 | |
311 | // 使用到IP过滤驱动中设备对象的指针创建一个IRP |
312 | // 填充PF_SET_EXTENSION_HOOK_INFO结构 |
313 | PF_SET_EXTENSION_HOOK_INFO filterData; |
314 | filterData.ExtensionPointer = filterFun; |
315 | |
316 | // 我们需要初始化一个事件对象。 |
317 | // 构建IRP时需要使用这个事件内核对象,当IP过滤取得接受到此IRP,完成工作以后会将它置位 |
318 | KEVENT event; |
319 | KeInitializeEvent(&event, NotificationEvent, FALSE); |
320 | |
321 | // 为设备控制请求申请和构建一个IRP |
322 | PIRP pIrp; |
323 | IO_STATUS_BLOCK ioStatus; |
324 | pIrp = IoBuildDeviceIoControlRequest(IOCTL_PF_SET_EXTENSION_POINTER, // io control code |
325 | pDeviceObj, |
326 | ( PVOID ) &filterData, |
327 | sizeof (PF_SET_EXTENSION_HOOK_INFO), |
328 | NULL, |
329 | 0, |
330 | FALSE, |
331 | &event, |
332 | &ioStatus); |
333 | if (pIrp == NULL) |
334 | { |
335 | // 如果不能申请空间,返回对应的错误代码 |
336 | return STATUS_INSUFFICIENT_RESOURCES; |
337 | } |
338 | |
339 | // 请求安装钩子回调函数 |
340 | // 发送此IRP到IP过滤驱动 |
341 | status = IoCallDriver(pDeviceObj, pIrp); |
342 | // 等待IP过滤驱动的通知 |
343 | if (status == STATUS_PENDING) |
344 | { |
345 | KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL); |
346 | } |
347 | status = ioStatus.Status; |
348 | |
349 | // 清除资源 |
350 | if (pFileObj != NULL) |
351 | ObDereferenceObject(pFileObj); |
352 | return status; |
353 | } |