[原创]基于Filter-HookDriver(使用ipfirewall.h)的IP过滤驱动
文章标题:[原创]基于Filter-HookDriver(使用ipfirewall.h)的IP过滤驱动顶部 fleshwound 发布于:2007-02-2716:02 [楼主][原创]基于Filter-HookDriver(使用ipfirewall.h)的IP过滤驱动
文章作者:fleshwound[smatrix](fleshwound@https://www.wendangku.net/doc/8f6122506.html,)
信息来源:邪恶八进制信息安全团队(https://www.wendangku.net/doc/8f6122506.html,)
注意:本文章首发安全矩阵(https://www.wendangku.net/doc/8f6122506.html,),后由原创作者友情提交到邪恶八进制信息安全团队。
IP过滤驱动可以广泛的应用于网络安全产品的研发,NDIS和TDI的驱动资料很多,有比较成熟的代码可以参考,但是使用IPFIREWALL.h开发的IP过滤驱动的资料非常少,这次自己做一个软件的时候参考VCKBASE上的一篇文章《开发Windows2000/XP下的防火墙》(作者:JesúsO)的基础上,写了一个驱动,代码都做了详细的注释了,只要稍微有点驱动设计基础的都可以看得懂,我把自己的特殊的回调函数去掉了,保留了基本的完整框架,牛人就不需要看了,初学者都可以在此基础上继续快速开发。
1SmatrixIPDiv.cpp文件
2protocol.h头文件
3SmatrixIPDiv.h头文件
Copycode
/*Copyright(c)2007,安全矩阵(SecurityMatrix)
*Allrightsreserved.
*
*文件名称:SmatrixIPDiv.cpp
*文件标识:S
*摘 要:IP过滤驱动,利用ipfirewall捕获包、分析包、过滤包
*开始时间:2006年12月26Ri
*
*当前版本:1.0
*作 者:fleshwound@https://www.wendangku.net/doc/8f6122506.html,
*相关信息:https://www.wendangku.net/doc/8f6122506.html,
*完成Ri期:2007年1月2Ri
*/
extern"C"
{
#include
#include
#include
#include
#include
#include
#include
#include
}
#include"SmatrixIPDiv.h"
#include"protocol.h"
/////////////////////////自定义函数的声明///////////////////////
//关闭打开驱动函数
NTSTATUSDispatchCreateClose(PDEVICE_OBJECTpDevObj,PIRPpIrp);
//驱动卸载函数
voidDriverUnload(PDRIVER_OBJECTpDriverObj);
//IO控制派遣函数(内核消息处理)
NTSTATUSDispatchIoctl(PDEVICE_OBJECTpDevObj,PIRPpIrp);
//向过滤列表中添加一个过滤规则
NTSTATUSAddFilterToList(CIPFilter*pFilter);
//清除过滤列表
voidClearFilterList();
//注册钩子回调函数
NTSTATUSSetFilterFunction(IPPacketFirewallPtrfilterFunction,BOOLEANload);
//包过滤函数
FORWARD_ACTIONFilterPacket(unsignedchar*PacketHeader,
unsignedchar*Packet,
unsignedintPacketLength,
DIRECTION_Edirection,
unsignedintRecvInterfaceIndex,
unsignedintSendInterfaceIndex);
//IP过滤器函数
FORWARD_ACTIONIPFilterFunction(VOID **pData,
UINT RecvInterfaceIndex,
UINT *pSendInterfaceIndex,
UCHAR *pDestinationType,
VOID *pContext,
UINT ContextLength,
structIPRcvBuf**pRcvBuf);
//过滤列表首地址
structC
FilterList*g_pHeader=NULL;
//驱动内部名称和符号连接名称
#defineDEVICE_NAMEL"\\Device\\DevSMFltIP"
#defineLINK_NAMEL"\\DosDevices\\DrvSMFltIp"
//驱动入口函数
NTSTATUSDriverEntry(PDRIVER_OBJECTpDriverObj,PUNICODE_STRINGpRegistryString)
{
NTSTATUSstatus=STATUS_SUCCESS;
//初始化各个派遣例程
pDriverObj->MajorFunction[IRP_MJ_CREATE]=DispatchCreateClose;
pDriverObj->MajorFunction[IRP_MJ_CLOSE]=DispatchCreateClose;
pDriverObj->MajorFunction[IRP_MJ_DEVICE_CONTROL]=DispatchIoctl;
pDriverObj->DriverUnload=DriverUnload;
//创建、初始化设备对象
//设备名称
UNICODE_STRINGustrDevName;
RtlInitUnicodeString(&ustrDevName,DEVICE_NAME);
//创建设备对象
PDEVICE_OBJECTpDevObj;
status=IoCreateDevice(pDriverObj,
0,
&ustrDevName,
FILE_DEVICE_DRVFLTIP,
0,
FALSE,
&pDevObj);
if(!NT_SUCCESS(status))
{
returnstatus;
}
//创建符号连接名称
//符号连接名称
UNICODE_STRINGustrLinkName;
RtlInitUnicodeString(&ustrLinkName,LINK_NAME);
//创建关联
status=IoCreateSymbolicLink(&ustrLinkName,&ustrDevName);
if(!NT_SUCCESS(status))
{
IoDeleteDevice(pDevObj);
returnstatus;
}
returnSTATUS_SUCCESS;
}
voidDriverUnload(PDRIVER_OBJECTpDriverObj)
{
//卸载过滤函数
SetFilterFunction(IPFilterFunction,FALSE);
//释放所有资源
ClearFilterList();
//删除符号连接名称
UNICODE_STRINGstrLink;
RtlInitUnicodeString(&strLink,LINK_NAME);
IoDeleteSymbolicLink(&strLink);
//删除设备对象
IoDeleteDevice(pDriverObj->DeviceObject);
}
//处理IRP_MJ_CREATE、IRP_MJ_CLOSE功能代码
NTSTATUSDispatchCreateClose(PDEVICE_OBJECTpDevObj,PIRPpIrp)
{
pIrp->IoStatus.Status=STATUS_SUCCESS;
// pIrp->https://www.wendangku.net/doc/8f6122506.html,rmation=0;
//完成此请求
IoCompleteRequest(pIrp,IO_NO_INCREMENT);
returnSTATUS_SUCCESS;
}
//I/O控制派遣例程
NTSTATUSDispatchIoctl(PDEVICE_OBJECTpDevObj,PIRPpIrp)
{
NTSTATUSstatus=STATUS_SUCCESS;
//取得此IRP(pIrp)的I/O堆栈指针
PIO_STACK_LOCATIONpIrpStack=IoGetCurrentIrpStackLocation(pIrp);
//取得I/O控制代码
ULONGuIoControlCode=pIrpStack->Parameters.DeviceIoControl.IoControlCode;
//取得I/O缓冲区指针和它的长度
PVOIDpIoBuffer=pIrp->AssociatedIrp.SystemBuffer;
ULONGuInSize=pIrpStack->Parameters.DeviceIoControl.InputBufferLength;
//响应用户的命令
switch(uIoControlCode)
{
caseSTART_IP_HOOK: //开始过滤
status=SetFilterFunction(IPFilterFunction,TRUE);
break;
caseSTOP_IP_HOOK: //停止过滤
status=SetFilterFunction(IPFilterFunction,FALSE);
break;
caseADD_FILTER: //添加一个过滤规则
if(uInSize==sizeof(CIPFilter))
status=AddFilterToList((CIPFilter*)pIoBuffer);
else
status=STATUS_INVALID_DEVICE_REQUEST;
break;
caseCLEAR_FILTER: //释放过滤规则列表
ClearFilterList();
break;
default:
status=STATUS_INVALID_DEVICE_REQUEST;
break
;
}
//完成请求
pIrp->IoStatus.Status=status;
pIrp->https://www.wendangku.net/doc/8f6122506.html,rmation=0;
IoCompleteRequest(pIrp,IO_NO_INCREMENT);
returnstatus;
}
///////////////////////////////////////////////////////////////////
//过滤列表
//向过滤列表中添加一个过滤规则
NTSTATUSAddFilterToList(CIPFilter*pFilter)
{
//为新的过滤规则申请内存空间
CFilterList*pNew=(CFilterList*)ExAllocatePool(NonPagedPool,sizeof(CFilterList));
if(pNew==NULL)
returnSTATUS_INSUFFICIENT_RESOURCES;
//填充这块内存
RtlCopyMemory(&pNew->ipf,pFilter,sizeof(CIPFilter));
//连接到过滤列表中
pNew->pNext=g_pHeader;
g_pHeader=pNew;
returnSTATUS_SUCCESS;
}
//清除过滤列表
voidClearFilterList()
{
CFilterList*pNext;
//释放过滤列表占用的所有内存
while(g_pHeader!=NULL)
{
pNext=g_pHeader->pNext;
//释放内存
ExFreePool(g_pHeader);
g_pHeader=pNext;
}
}
//包过滤函数
FORWARD_ACTIONFilterPacket(unsignedchar*PacketHeader,
unsignedchar*Packet,
unsignedintPacketLength,
DIRECTION_Edirection,
unsignedintRecvInterfaceIndex,
unsignedintSendInterfaceIndex)
{
//提取IP头
IPHeader*pIPHdr=(IPHeader*)PacketHeader;
TCPHeader*pTCPHdr=NULL;
UDPHeader*pUDPHdr=NULL;
if(pIPHdr->ipProtocol==6)//是TCP协议
{
//提取TCP头
pTCPHdr=(TCPHeader*)Packet;
//我们接受所有已经建立连接的TCP封包
if(!(pTCPHdr->flags&0x02))
{
returnFORWARD;
}
}
//与过滤规则相比较,决定采取的行动
CFilterList*pList=g_pHeader;
while(pList!=NULL)
{
//比较协议
if(pList->ipf.protocol==0||pList->ipf.protocol==pIPHdr->ipProtocol)
{
//查看源IP地址
if(pList->ipf.sourceIP!=0&
(pList->ipf.sourceIP&pList->ipf.sourceMask)!=pIPHdr->ipSource)
{
pList=pList->pNext;
continue;
}
//查看目标IP地址
if(pList->ipf.destinationIP!=0&
(pList->ipf.destinationIP&pList->ipf.destinationMask)!=pIPHdr->ipDestination)
{
pList=pList->pNext;
continue;
}
//如果是TCP封包,查看端口号
if(pIPHdr->ipProtocol==6)
{
pTCPHdr=(TCPHeader*)Packet;
if(pList->ipf.sourcePort==0||pList->ipf.sourcePort==pTCPHdr->sourcePort)
{
if(pList->ipf.destinationPort==0
||pList->ipf.destinationPort==pTCPHdr->destinationPort)
{
//现在决定如何处理这个封包
if(pList->ipf.bDrop)
returnDROP;
else
returnFORWARD;
}
}
}
//如果是UDP封包,查看端口号
elseif(pIPHdr->ipProtocol==17)
{
pUDPHdr=(UDPHeader*)Packet;
if(pList->ipf.sourcePort==0||pList->ipf.sourcePort==pUDPHdr->sourcePort)
{
if(pList->ipf.destinationPort==0
||pList->ipf.destinationPort==pUDPHdr->destinationPort)
{
//现在决定如何处理这个封包
if(pList->ipf.bD
rop)
returnDROP;
else
returnFORWARD;
}
}
}
else
{
//对于其它封包,我们直接处理
if(pList->ipf.bDrop)
returnDROP;
else
returnFORWARD;
}
}
//比较下一个规则
pList=pList->pNext;
}
//我们接受所有没有注册的封包
returnFORWARD;
}
//注册钩子回调函数
NTSTATUSSetFilterFunction(IPPacketFirewallPtrfilterFunction,BOOLEANload)
{
//{变量定义BEGIN}
NTSTATUSstatus=STATUS_SUCCESS; //内核状态
NTSTATUSwaitStatus=STATUS_SUCCESS; //受信状态
PDEVICE_OBJECTpDeviceObj=NULL; //pDeviceObj变量将指向IP过滤驱动设备对象
PFILE_OBJECTpFileObj=NULL; //内核过滤器设备
IP_SET_FIREWALL_HOOK_INFOfilterData; //IP_SET_FIREWALL_HOOK_INFO结构
UNICODE_STRINGustrFilterDriver; //IP过滤驱动的名称
KEVENTevent; //
IO_STATUS_BLOCKioStatus; //
PIRPpIrp; //
//{变量定义END}
//初始化IP过滤驱动的名称
RtlInitUnicodeString(&ustrFilterDriver,DD_IP_DEVICE_NAME);
//取得设备对象指针
status=IoGetDeviceObjectPointer(&ustrFilterDriver,STANDARD_RIGHTS_ALL,&pFileObj,&pDeviceObj);
if(!NT_SUCCESS(status))
{
returnstatus;
}
///////////使用到IP过滤驱动中设备对象的指针创建一个IRP///////////////////////////
//填充IP_SET_FIREWALL_HOOK_INFO结构
filterData.FirewallPtr=filterFunction;
filterData.Priority=1;
filterData.Add=load;
//我们需要初始化一个事件对象。
//构建IRP时需要使用这个事件内核对象,当IP过滤取得接受到此IRP,完成工作以后会将它置位
KeInitializeEvent(&event,NotificationEvent,FALSE);
//为设备控制请求申请和构建一个IRP
pIrp=IoBuildDeviceIoControlRequest(IOCTL_IP_SET_FIREWALL_HOOK,//iocontrolcode
pDeviceObj,
(PVOID)&filterData,
sizeof(IP_SET_FIREWALL_HOOK_INFO),
NULL,
0,
FALSE,
&event,
&ioStatus);
if(NULL==pIrp)
{
//如果不能申请空间得到pIrp,返回对应的错误代码
returnSTATUS_INSUFFICIENT_RESOURCES;
}
////////////////////////////////////////////////////////////////
///////////////请求安装钩子回调函数/////////////////////////////
//发送此IRP到IP过滤驱动
status=IoCallDriver(pDeviceObj,pIrp);
//等待IP过滤驱动的通知
if(status==STATUS_PENDING)
{
waitStatus=KeWaitForSingleObject(&event,Executive,KernelMode,FALSE,NULL);
if(!NT_SUCCESS(waitStatus))//受信状态不成功,返回
{
returnwaitStatus;
}
}
status=ioStatus.Status;
if(!NT_SUCCESS(status))//状态不成功,返回
{
returnstatus;
}
/////////////////////////////////////////////////////////////////////////
//////////////////////清除内核资源/////////////////////////////////////
if(pFileObj!=NULL)
ObDereferenceObject(pFileObj);
pDeviceObj=NULL; //避免
产生野指针
pFileObj=NULL; //避免产生野指针
returnstatus;
}
//IP过滤器函数
FORWARD_ACTIONIPFilterFunction(VOID **pData,
UINT RecvInterfaceIndex,
UINT *pSendInterfaceIndex,
UCHAR *pDestinationType,
VOID *pContext,
UINT ContextLength,
structIPRcvBuf**pRcvBuf)
{
FORWARD_ACTIONresult=FORWARD;
unsignedchar*packet=NULL;
intbufferSize=0;
structIPRcvBuf*buffer=(structIPRcvBuf*)*pData;
PFIREWALL_CONTEXT_TfwContext=(PFIREWALL_CONTEXT_T)pContext;
DIRECTION_Edirection=IP_RECEIVE;
//如果包指针不为空,IPRcvBuf中存在数据
if(buffer!=NULL)
{
bufferSize=buffer->ipr_size;
while(buffer->ipr_next!=NULL)//得到整个IPRcvBuf缓冲链中数据总长度
{
buffer=buffer->ipr_next;
bufferSize+=buffer->ipr_size;
}
//分配一个不分页的内存,将整个IPRcvBuf缓冲链放入其中
packet=(unsignedchar*)ExAllocatePool(NonPagedPool,bufferSize);
if(packet!=NULL)
{
IPHeader*ipp=(IPHeader*)packet;
unsignedintoffset=0;
buffer=(structIPRcvBuf*)*pData;
memcpy(packet,buffer->ipr_buffer,buffer->ipr_size);
while(buffer->ipr_next!=NULL)
{
offset+=buffer->ipr_size;
buffer=buffer->ipr_next;
memcpy(packet+offset,buffer->ipr_buffer,buffer->ipr_size);
}
if(NULL!=fwContext)
{
direction=fwContext->Direction;
}
else
{
direction=(DIRECTION_E)0;
}
//调用包检测函数,通过返回FORWARD,否则返回DROP
result=FilterPacket(packet,
packet+(ipp->ipHeaderLength*4),
bufferSize-(ipp->ipHeaderLength*4),
direction,
RecvInterfaceIndex,
(pSendInterfaceIndex!=NULL)?*pSendInterfaceIndex:0);
}
}
//释放分配的临时包缓存
if(NULL!=packet)ExFreePool(packet);
returnresult;
}
2定义常见的封包结构信息
Copycode
//文件名称:protocol.h
typedefstructIPHeader
{ UCHAR ipHeaderLength:4; //头长度
UCHAR ipVersion:4; //版本号
UCHAR ipTOS; //服务类型
USHORT ipLength; //封包总长度,即整个IP报的长度
USHORT ipID; //封包标识,惟一标识发送的每一个数据报
USHORT ipFlags; //标志
UCHAR ipTTL; //生存时间,就是TTL
UCHAR ipProtocol; //协议,可能是TCP、UDP、ICMP等
USHORT ipChecksum; //校验和
ULONG ipSource; //源IP地址
ULONG ipDestination;//目标IP地址
}IPPacket;
typedefstruct_TCPHeader
{
USHORT sourcePort; //源端口号
USHORT destinationPort; //目的端口号
ULONG sequenceNumber; //序号
ULONG acknowledgeNumber; //确认序号
UCHAR dataoffset; //数据指针
UCHAR flags; //标志
USHORT windows; //窗口大小
USHORT checksum; //校验和
USHORT urgentPointer; //紧急指针
}TCPHeader;
typedefstruct_UDPHeader
{
USHORT sourcePort; //源
端口号
USHORT destinationPort; //目的端口号
USHORT len; //封包长度
USHORT checksum; //校验和
}UDPHeader;
enum
{
IPPROTO_IP =0, //DummyprotocolforTCP.
IPPROTO_HOPOPTS =0, //IPv6Hop-by-Hopoptions.*/
IPPROTO_ICMP =1, //InternetControlMessageProtocol.*/
IPPROTO_IGMP =2, //InternetGroupManagementProtocol.*/
IPPROTO_IPIP =4, //IPIPtunnels(olderKA9Qtunnelsuse94).*/
IPPROTO_TCP =6, //TransmissionControlProtocol.*/
IPPROTO_EGP =8, //ExteriorGatewayProtocol.*/
IPPROTO_PUP =12, // PUPprotocol.*/
IPPROTO_UDP =17, // UserDatagramProtocol.*/
IPPROTO_IDP =22, //XNSIDPprotocol.*/
IPPROTO_TP =29, //SOTransportProtocolClass4.*/
IPPROTO_IPV6 =41, // IPv6header.*/
IPPROTO_ROUTING =43, // IPv6routingheader.*/
IPPROTO_FRAGMENT =44, // IPv6fragmentationheader.*/
IPPROTO_RSVP =46, //ReservationProtocol.*/
IPPROTO_GRE =47, //GeneralRoutingEncapsulation.*/
IPPROTO_ESP =50, //encapsulatingsecuritypayload.*/
IPPROTO_AH =51, //authenticationheader.*/
IPPROTO_ICMPV6 =58, //ICMPv6.*/
IPPROTO_NONE =59, /*IPv6nonextheader.*/
IPPROTO_DSTOPTS =60, /*IPv6destinationoptions.*/
IPPROTO_MTP =92, /*MulticastTransportProtocol.*/
IPPROTO_ENCAP =98, /*EncapsulationHeader.*/
IPPROTO_PIM =103, /*ProtocolIndependentMulticast.*/
IPPROTO_COMP =108, /*CompressionHeaderProtocol.*/
IPPROTO_RAW =255, /*RawIPpackets.*/
IPPROTO_MAX
};
3IP过滤驱动相关结构和宏定义
Copycode
//文件名称:SmatrixIPDiv.h
#ifndef__SMATRIXIPDIV_H__
#define__SMATRIXIPDIV_H__
//自定义设备类型,在创建设备对象时使用
//注意,自定义值的范围是32768-65535
#defineFILE_DEVICE_DRVFLTIP0x00654322
//自定义的IO控制代码,用于区分不同的设备控制请求
//注意,自定义值的范围是2048-4095
#defineDRVFLTIP_IOCTL_INDEX0x830
//
//定义各种设备控制代码。分别是开始过滤、停止过滤、添加过滤规则、清除过滤规则
//
#defineSTART_IP_HOOK CTL_CODE(FILE_DEVICE_DRVFLTIP,\
DRVFLTIP_IOCTL_INDEX,METHOD_BUFFERED,FILE_ANY_ACCESS)
#defineSTOP_IP_HOOK CTL_CODE(FILE_DEVICE_DRVFLTIP,\
DRVFLTIP_IOCTL_INDEX+1,METHOD_BUFFERED,FILE_ANY_ACCESS)
#defineADD_FILTER CTL_CODE(FILE_DEVICE_DRVFLTIP,\
DRVFLTIP_IOCTL_INDEX+2,METHOD_BUFFERED,FILE_WRITE_ACCESS)
#defineCLEAR_FILTER CTL_CODE(FILE_DEVICE_DRVFLTIP,\
DRVFLTIP_IOCTL_INDEX+3,METHOD_BUFFERED,FILE_ANY_ACCESS)
//定义过滤规则的结构
structCIPFilter
{
USHORTprotocol; //使用的协议
ULONGsourceIP; //源IP地址
ULONGdestinationIP; //目标IP地址
ULONGsourceMask; //源地址屏蔽码
ULONGdestinationMask; //目的地址屏蔽码
USHORTsourcePort; //源端口号
USHORTdestinationPort; //目的端口号
BOOLEANbDrop; //是否丢弃此封包
};
//过滤列表
structCFilterList
{
CIPFilteripf; //过滤规则
CFilterList*pNext; //指向下一个CFilterList结构
};
#endif//__SMATRIXIPDIV_H__
注:这里感谢下sinister和驱动网若干牛人的热情指导和建议,需要驱动开发向导文件得可以到https://www.wendangku.net/doc/8f6122506.html,/bbs下。
byfleshwound
参考文献:
1开发Windows2000/XP下的防火墙,https://www.wendangku.net/doc/8f6122506.html,/document/viewdoc/?id=1067(c)Copyleft2003-2007,EvilOctalSecurityTeam.
ThisfileisdecompiledbyanunregisteredversionofChmDecompiler.
Regsiteredversiondoesnotshowthismessage.
YoucandownloadChmDecompilerat:https://www.wendangku.net/doc/8f6122506.html,/