驱动开发之四:NDIS过滤钩子驱动实现ip包过滤

转载 2006年06月15日 11:37:00
作者:FLASHSKY
EMAIL:flashsky@xfocus.org
站点:www.xfocus.net www.shopsky.com
转载请注明原作者安全焦点

在普通的WINDOWS 2000下实现实现包过滤的方法主要是书写NDIS过滤驱动程序,需要的技巧比较高,而且烦琐,需要考虑很多细节。但是对于很多应用而言,只需要能更方便的对ip包进行过滤处理,其实NDIS对于ip包的过滤提供一种书写过滤钩子驱动的方式,主要方法是:
驱动中建立一个普通的设备,然后通过IOCTL_PF_SET_EXTENSION_POINTER操作将你的内核模式的过滤钩子挂接到系统默认的ip过滤驱动上,这样你就可以在自己的过滤钩子里面实现完整的基于包的各种分析和过滤的处理了。
下面就是一个完整的NDIS过滤钩子驱动的代码拒绝所有外来的TCP带S的建立连接的请求。
注意事项:
1。需要在DDK环境中编译
2。需要修改注册表中LMHK/System//CurrentControlSet//Services//IPFILTERDRIVER的START类型为3,让他随系统启动而启动
3。编译生成了sys文件后需要拷贝到winnt/system32/drivers目录下
4。需要运行一个程序后手动生成注册表项
5。使用时用net start fxfilthook启动驱动,用net stop fxfilthook停止驱动
6。此方法只能对ip包进行过滤,其他的协议不会经过这个过滤钩子进行处理。

//驱动程序的头文件
#include "ntddk.h"
#include "ntddndis.h"
#include "pfhook.h"
#ifndef __NTHANDLE_H
#define __NTHANDLE_H

#define NT_DEVICE_NAME L"//Device//Fxfilthook"
#define DOS_DEVICE_NAME L"//DosDevices//Fxfilthook"

#define PROT_TCP 6

#include "ntddk.h"
#include "xfilthook.h"

typedef struct IPHeader {
UCHAR iph_verlen; // Version and length
UCHAR iph_tos; // Type of service
USHORT iph_length; // Total datagram length
USHORT iph_id; // Identification
USHORT iph_offset; // Flags, fragment offset
UCHAR iph_ttl; // Time to live
UCHAR iph_protocol; // Protocol
USHORT iph_xsum; // Header checksum
ULONG iph_src; // Source address
ULONG iph_dest; // Destination address
} IPHeader;

NTSTATUS
DriverEntry(
IN PDRIVER_OBJECT DriverObject,
IN PUNICODE_STRING RegistryPath);

NTSTATUS
CreateFilterHook
(IN PDRIVER_OBJECT DriverObject);

VOID
DriverUnload
(IN PDRIVER_OBJECT DriverObject);

PF_FORWARD_ACTION
IpFilterHook(
IN unsigned char *PacketHeader,
IN unsigned char *Packet,
IN unsigned int PacketLength,
IN unsigned int RecvInterfaceIndex,
IN unsigned int SendInterfaceIndex,
IN IPAddr RecvLinkNextHop,
IN IPAddr SendLinkNextHop);
#endif

//驱动程序的c文件
#define PROT_TCP 6
#include "ntddk.h"
#include "ntddndis.h"
#include "pfhook.h"
#include "fxfilthook.h"

PDEVICE_OBJECT deviceObject;
UNICODE_STRING win32DeviceName;

//住驱动入口点
NTSTATUS
DriverEntry(
IN PDRIVER_OBJECT DriverObject,
IN PUNICODE_STRING RegistryPath
)
{
NTSTATUS status = STATUS_SUCCESS;
UNICODE_STRING ntDeviceName;

RtlInitUnicodeString(&ntDeviceName,NT_DEVICE_NAME);
//建立一个过滤钩子驱动设备
status = IoCreateDevice (DriverObject,0,&ntDeviceName,FILE_DEVICE_UNKNOWN,0,TRUE,&deviceObject);
if (!NT_SUCCESS (status)) {
goto ERROR;
}
RtlInitUnicodeString(&win32DeviceName, DOS_DEVICE_NAME);
//建立一个过滤钩子驱动设备符号连接
status = IoCreateSymbolicLink( &win32DeviceName, &ntDeviceName );
if (!NT_SUCCESS(status)) // If we couldn't create the link then
{ // abort installation.
goto ERROR;
}
//申明卸载例程
DriverObject->DriverUnload = DriverUnload;
//建立钩子挂接
status = CreateFilterHook(DriverObject);
if (!NT_SUCCESS(status)) // If we couldn't create the link then
{ // abort installation.
IoDeleteSymbolicLink(&win32DeviceName);
goto ERROR;
}
return(STATUS_SUCCESS);
ERROR:
if(deviceObject)
IoDeleteDevice(deviceObject);
//DbgPrint( "Leave DriverEntry failed/n" );
return status;
}

NTSTATUS
CreateFilterHook(IN PDRIVER_OBJECT DriverObject)
{
PIRP nirp;
NTSTATUS status = STATUS_SUCCESS;
PFILE_OBJECT filtfileob;
UNICODE_STRING ntDeviceName;
PDEVICE_OBJECT filtdeviceob;
PF_SET_EXTENSION_HOOK_INFO filthook;
IO_STATUS_BLOCK filtstatus;

RtlInitUnicodeString(&ntDeviceName,L"//Device//IPFILTERDRIVER");
//将钩子挂接函数放入结构中
filthook.ExtensionPointer = IpFilterHook;
//获得系统ipfilterdriver驱动的设备指针
status = IoGetDeviceObjectPointer(&ntDeviceName,FILE_GENERIC_READ|FILE_GENERIC_WRITE,&filtfileob,&filtdeviceob);
if(status!=STATUS_SUCCESS)
return status;
//绑定过滤钩子到系统ipfilterdriver驱动的设备指针
nirp = IoBuildDeviceIoControlRequest(
IOCTL_PF_SET_EXTENSION_POINTER,
filtdeviceob,
&filthook,
sizeof(PF_SET_EXTENSION_HOOK_INFO),
NULL,
0,
FALSE,
NULL,
&filtstatus);
if(nirp==NULL)
return filtstatus.Status;
//调度系统ipfilterdriver设备重新操作irp
return (IoCallDriver(filtdeviceob,nirp));
}

VOID
DriverUnload(IN PDRIVER_OBJECT DriverObject)
{
//与加载一样,只是钩子函数结构中放NULL,让系统ipfilterdriver卸载加载的钩子函数

PIRP nirp;
NTSTATUS status = STATUS_SUCCESS;
PDEVICE_OBJECT filtdeviceob;
PFILE_OBJECT filtfileob;
PF_SET_EXTENSION_HOOK_INFO filthook;
IO_STATUS_BLOCK filtstatus;
UNICODE_STRING ntDeviceName;

RtlInitUnicodeString(&ntDeviceName,L"//Device//IPFILTERDRIVER");
filthook.ExtensionPointer = NULL;
status = IoGetDeviceObjectPointer(&ntDeviceName,FILE_GENERIC_READ|FILE_GENERIC_WRITE,&filtfileob,&filtdeviceob);
if(status==STATUS_SUCCESS)
{
nirp = IoBuildDeviceIoControlRequest(
IOCTL_PF_SET_EXTENSION_POINTER,
filtdeviceob,
&filthook,
sizeof(PF_SET_EXTENSION_HOOK_INFO),
NULL,
0,
FALSE,
NULL,
&filtstatus);
if(nirp!=NULL)
IoCallDriver(filtdeviceob,nirp);
}
IoDeleteSymbolicLink(&win32DeviceName);
IoDeleteDevice(deviceObject);
return;
}

PF_FORWARD_ACTION
IpFilterHook(
unsigned char *PacketHeader,
unsigned char *Packet,
unsigned int PacketLength,
unsigned int RecvInterfaceIndex,
unsigned int SendInterfaceIndex,
IPAddr RecvLinkNextHop,
IPAddr SendLinkNextHop
)
{
//过滤钩子函数,这儿只简单判断属于TCP协议且数据是抵达而且带SYN标志则过滤。大家可以根据需要修改自己的过滤判断和处理。
if(((IPHeader *)PacketHeader)->iph_protocol == PROT_TCP)
{
//Packet[13]==0x2就是TCP中SYN的标志
//SendInterfaceIndex==INVALID_PF_IF_INDEX说明包是抵达而不是发送的,因此这样过滤就不会影响自己的包出去,但是外来带SYN请求的包则会拒绝。
if(Packet[13]==0x2 && SendInterfaceIndex==INVALID_PF_IF_INDEX)
return PF_DROP;
}
return PF_FORWARD;
}

//简单的建立注册表项的程序

unsigned char sysdir[256];
unsigned char drivcedir[256];
int RegHandelDev(char * exename)
{
//修改注册表启动一个NTHANDLE驱动程序
char subkey[200];
int buflen;
HKEY hkResult;
char Data[4];
DWORD isok;
buflen = sprintf(subkey,"System//CurrentControlSet//Services//%s",exename);
subkey[buflen]=0;
isok = RegCreateKey(HKEY_LOCAL_MACHINE,subkey,&hkResult);
if(isok!=ERROR_SUCCESS)
return FALSE;
Data[0]=3;
Data[1]=0;
Data[2]=0;
Data[3]=0;
isok=RegSetValueEx(hkResult,"Start",0,4,(const unsigned char *)Data,4);
Data[0]=1;
isok=RegSetValueEx(hkResult,"Type",0,4,(const unsigned char *)Data,4);
isok=RegSetValueEx(hkResult,"ErrorControl",0,4,(const unsigned char *)Data,4);
GetSystemDirectory(sysdir,256);
buflen = sprintf(drivcedir,"%s//Drivers//FxFiltHook.sys",sysdir);
buflen = sprintf(subkey,"//??//%s",drivcedir);
subkey[buflen]=0;
isok=RegSetValueEx(hkResult,"ImagePath",0,1,(const unsigned char *)subkey,buflen);
RegCloseKey(hkResult);
buflen = sprintf(subkey,"//Registry//Machine//System//CurrentControlSet//Services//%s",exename);
subkey[buflen]=0;
return TRUE;
}

int main(int argc,char *argv[])
{
//注册驱动程序
if(RegHandelDev("Fxfilthook")==FALSE)
return FALSE;
return TRUE;
}

驱动开发之四:NDIS过滤钩子驱动实现ip包过滤

作者:FLASHSKY EMAIL:flashsky@xfocus.org 站点:www.xfocus.net www.shopsky.com 转载请注明原作者安全焦点 在普通的WINDO...
  • cosmoslife
  • cosmoslife
  • 2012年06月18日 06:08
  • 516

NDIS LWF网络过滤驱动开发(一):LWF简介及数据结构说明

写在之前:换工作了,做Win驱动开发,还是网络过滤驱动。之前从未接触过这些,只是做着单机的桌面应用程序,所以一切是从头开始。从驱动到网络,很多的不懂,一步步走来,现在多少有些进展了,现在就总结下这段过...
  • mdcire
  • mdcire
  • 2016年09月27日 21:44
  • 997

书写NDIS过滤钩子驱动实现ip包过滤

 在普通的WINDOWS 2000下实现实现包过滤的方法主要是书写NDIS过滤驱动程序,需要的技巧比较高,而且烦琐,需要考虑很多细节。但是对于很多应用而言,只需要能更方便的对ip包进行过滤处理,其实N...
  • sun201201
  • sun201201
  • 2007年04月22日 16:22
  • 294

IP包过滤

IP包过滤2004-05-27 zzwinner  /*利用操作系统提供的API编写防火墙.该程序涉及到的API说明请访问微软的MSDN Library代码在C++ Builder 5编译通过如果您想...
  • godtorch
  • godtorch
  • 2005年02月12日 14:48
  • 706

ndis协议驱动开发

协议驱动的开发流程: 首先,一个协议驱动调用函数ndisRegisterProtocol()先把自己注册为协议驱动,此举的意义告诉windows,我是一个ndis协议驱动,并将约定好的回调函数的列表...
  • keepdoingit
  • keepdoingit
  • 2015年10月17日 10:48
  • 2521

基于Windows系统下网络数据包过滤方法的分析

1、windows的分层网络构架 可以把windows操作系统的网络构架粗略划分为6层,其中逻辑链路层、网络层和传输层都是通过传输驱动程序实现的,也叫做协议驱动程序。网络驱动接口标准(NDIS)用于...
  • chenyujing1234
  • chenyujing1234
  • 2012年07月31日 15:14
  • 6700

基于Filter-Hook Driver(使用ipfirewall.h)的IP过滤驱动

Author:  fleshwoundEmail:   fleshwound@126.comHomepage:http://www.smatrix.org IP过滤驱动可以广泛的应用于网络安全产品的研...
  • wzsy
  • wzsy
  • 2007年03月13日 11:03
  • 1151

AFD驱动

首先来介绍一下AFD驱动。大家可能对NDIS及TDI了解的比较多,AFD驱动相对会少一些。NDIS及TDI是微软提供的内核网络驱动模型中的编程接口规范,而AFD驱动是微软Windows操作一个驱动部件...
  • sding
  • sding
  • 2011年11月24日 10:04
  • 4009

NDIS过滤驱动开发手记(完成)

不知道对于一个从未了解NDIS的人来说,2天时间搞出一个基于NDIS的过滤驱动,并且稳定运行,代表什么呢?我都没想到自己能做得这么快,我开始感觉怎么不得2周啊。####################...
  • robur
  • robur
  • 2007年03月04日 15:47
  • 1967

微软引入了两种新的网络过滤系统,WFP和NDISfilter

Windows 8是微软公司推出的最新的客户端OS,内部名称Windows NT 80。相对于Windows NT 5.x,其网络结构变化非常大,原有的TDI,NDIS系统挂接方法不再适用。在Wi...
  • swanabin
  • swanabin
  • 2014年11月22日 10:19
  • 5762
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:驱动开发之四:NDIS过滤钩子驱动实现ip包过滤
举报原因:
原因补充:

(最多只允许输入30个字)