怎样才能滤网址?(300分)

  • 主题发起人 主题发起人 whbest
  • 开始时间 开始时间
W

whbest

Unregistered / Unconfirmed
GUEST, unregistred user!
想做一个过滤网址的程序,以前接触过BHO方式绑定IE的(觉得不通用,而且在win2003下无效)!请教各位高手帮小弟解决一下,不胜感激!
 
直接在IE里面设置。在程序里写还要用HOOK麻烦
 
如果不用IE,用其它游览器呢,而且可能要安装到很多机器上,也不能让人随便去改!
 
通过路由来做不可以吗?
 
应该是你没有写好,BHO是可以实现的,我觉得跟操作系统没有什么关系,最多跟IE的版本有关!
 
[:D]10k人民币,可以给你一个驱动的代码
 
to 爱元元的哥哥:
你那个驱动的代码是用什么语言编写?
 
win2003 你把选项第三方插件打沟就可以了
 
to gigi788:驱动都是用C写的,可以提供delphi的调用例子
 
现在我找了一个人,他可提供给我一个dll调用库,可实现这种功能,不过我还是想要有一个delphi的源码是最好的了
 
To爱元元的哥哥
10k啊,太贵了吧,我可不富有啊![:)]
 
基于SPI的Delphi的代码我可以提供,少于10K是肯定不行的,呵呵,尊重知识
 
DDE可以实现。
 
穷人付不起啊,这个系统先放一边吧,以后找到相关技术再做了!
 
既然会bho就用bho啊,只是只对ie有用,不存在win2003不能用的问题.
用SPI的话通用性好,1k是不贵的。到底是驱动开发.能用NDIS会更完美点.不过价格肯定就高.
 
TO satanmonkey
呵呵,不是1K啊,是10K(1w啊)
 
希望对各位有兴趣的人有所帮助
======================================
基于SPI的数据报过滤原理与实现

Author: TOo2y [原创]
E-Mail: TOo2y@safechina.net
HomePage: www.safechina.net fz5fz.yeah.net
Date: 11-02-2002

一. 个人防火墙技术概述
二. Winsock 2 SPI介绍
三. 相关程序代码分析
四. 小结与后记
五. 附录之源代码

一)个人防火墙技术概述
随着网络安全问题日益严重,广大用户对网络安全产品也越来越关注。防火墙作为一种网络安全工具,早已受到大家的青睐。在PC机上使用的个人防火墙,很大程度上成为广大网民的安全保护者。Windows下的个人防火墙都是基于对数据报的拦截技术之上。当然在具体的实现方式上它们却有很大的不同。总的来说可分为用户级和内核级数据报拦截两类。其中内核级主要是TDI过滤驱动程序,NDIS中间层过滤驱动程序,NDIS过滤钩子驱动程序等,它们都是利用网络驱动来实现的;而用户级的过滤包括SPI接口,Windows2000包过滤接口等。本文主要讲述基于SPI的包过滤实现,它是Winsock 2的一个新特性。

二)Winsock 2 SPI介绍
Winsock 2 是一个接口,而不是协议,所以它可以用于发现和使用任意数量的底层传输协议所提供的通信能力。起初的Winsock是围绕着TCP/IP协议运行的,但是在Winsock 2中却增加了对更多传输协议的支持。Winsock 2不仅提供了一个供应用程序访问网络服务的Windows socket应用程序编程接口(API),还包含了由传输服务提供者和名字解析服务提供者实现的Winsock服务提供者接口(SPI)和ws2_32.dll。本文仅讨论传输服务提供者及其应用,暂不对名字解析服务提供者进行分析。
Winsock 2的传输服务提供者是以动态链接库的形式(DLL)存在的,它是通过WSPStartup函数为上层函数提供接口,而其他的传输服务提供者函数则是通过分配表的方式来访问WS2_32.DLL。传输服务提供者的动态链接库只有在应用程序需要时才由Ws2_32.dll来装入内存中的,在不需要时则会被自动卸载。以下是winsock 2在传输服务提供者上的WOSA(Windows开放服务结构):

----------------------------
|Windows socket 2 应用程序|
----------------------------Windows socket 2 API
| WS2_32.DLL |
----------------------------Windows socket 2 传输SPI
| 传输服务提供者(DLL) |
----------------------------

Windows socket SPI在服务提供者中使用了以下的函数前缀命名方式:WSP(Windows socket服务提供者),WPU(Windows socket提供者向上调用),WSC(Windows socket配置)。每一个传输服务提供者都有它自己所支持的传输协议,它是使用WSAPROTCOL_INFOW结构来实现的。传输服务提供者把所有的相关信息都存放在这个结构中,而应用程序就是通过这个结构的内容来将自己和相应的传输服务提供者相关联。
Windows socket SPI提供三种协议:分层协议,基础协议和协议链。分层协议是在基础协议的上层,依靠底层基础协议实现更高级的通信服务。基础协议是能够独立,安全地和远程端点实现数据通信的协议,它是相对与分层协议而言的。协议链是将一系列的基础协议和分层协议按特点的顺序连接在一起的链状结构,请参见下图:

API------------------------
| WS2_32.DLL |
SPI------------------------
| 分层协议 |
SPI-------------
| 分层协议 |
SPI------------------------
| 基础协议 |
------------------------

Ws2_32.dll数据传输部分的主要功能是在服务提供者和应用程序之间提供流量管理的功能。每个应用程序通过Ws2_32.dll和相应的服务提供者进行严格的数据交换。Ws2_32.dll根据应用程序在创建套接字时所提供的参数来选择特定的服务提供者,然后把应用程序的实现过程转发由所选创建套接字的服务提供者来管理。也就是说,Ws2_32.dll只是一个中间过程,而应用程序只是一个接口,数据通信的实现却是有服务提供者来完成的。我们说过,Ws2_32.dll是通过创建套接字的API函数WSASocket或socket的参数来确定使用哪一个服务提供者。而WSASocket/socket的参数中包括了地址族,套接字类型和协议类型,这三个因素共同决定了创建套接字的服务提供者。Ws2_32.dll在服务提供者中寻找第一个和前面三因素相匹配的WSAPROTOCOL_INFOW结构,然后就调用这个WSAPROTOCOL_INFOW结构相应的WSPStartup函数,(所有的数据传输服务提供者以DLL的形式,它们对外的接口就只有WSPStartup,其他的服务提供者函数都是通过WSPStartup来调用的),进而调用如WSPSocket的函数来创建套接字,WSPConnect的函数来建立连接等等。除了流量管理功能外,Ws2_32.dll还提供了其他的服务,比如协议枚举,基于线程的阻塞钩子管理和在Ws2_32.dll和服务提供者之间进行版本协商。
传输服务提供者实现的功能包括建立连接,传输数据,实现流控制和差错控制等函数。其实Ws2_32.dll并不知道服务提供者的请求等活动是如何实现了,Ws2_32.dll在应用程序和服务提供者之间实现了媒介的功能。传输服务提供者可分为两类:套接字描述符是可安装的文件系统(IFS)句柄的提供者;剩下的是非IFS的提供者。在我们的程序中选用了非IFS提供者。可见,服务提供者实现了底层的与网络相关的协议。Ws2_32.dll提供了介质级别的流量管理,应用程序则提供了有关如何实现网络相关的操作,它实现了用户所希望的功能。
在传输服务提供者的实现过程中,安装顺序是非常重要的。我们不仅要正确的安装服务提供者,而且还必须在Windows socket中注册,将相关的系统信息保存在数据库中,这样Ws2_32.dll才能够方便的获得下层服务提供者的相关信息。在Ws2_32.dll中提供了用来安装服务提供者的函数WSCInstallProvider,它需要服务提供者的有关数据,比如DLL的名称和路径。同时Ws2_32.dll还提供了卸载服务提供者的函数WSCDeinstallProvider,在不需要时通过它将特定的服务提供者从系统中删除。为什么说传输服务者的安装顺序很重要呢?在服务提供者配置函数中的WSCEnumProtocols是用来枚举系统中所有已安装的服务提供者,它按照服务提供者的安装顺序相应的列出他们。在前面我们也提到过,Ws2_32.dll在服务提供者中按安装顺序搜寻和WSASocket/socket提供的三个参数相匹配的服务提供者,所以安装顺序在一定程度上是决定了服务提供者是否被正确调用的关键。Windows socket 2还提供了一个动态链接库Sporder.dll,它提供了对已安装的所有服务提供者顺序的重新排列(此DLL系统没有自带,common目录中已提供)。在附录中的T-Sporder.exe是一个查询当前已安装所有数据传输服务提供者属性的工具。
服务提供者系统中区分基础协议,分层协议和协议链是通过结构WSAPROTOCOL_INFOW中的Protocolchain结构的ChainLen值来实现的。分层协议的ChainLen值为0,基础协议的值为1,而协议链的值是大于1。在数据传输服务提供者的实现方式中分层协议和基础协议几乎是相同的,它们的不同之处在安装上。Windows中,现有的系统服务提供者(系统自带)几乎已提供了所有基本的服务,因此我们所写的服务提供者程序,都可以对数据报进行适当“修饰”后调用系统服务提供者来完成绝大部分剩下的功能,无论是基础服务提供者还是分层服务提供者都可以使用这种技术,免去不必要的劳动。基础服务提供者的实现过程主要是替换当前系统服务提供者的安装路径为自己的服务提供者的安装路径即可,当然我们必须保存所以系统服务者的相关数据,在我们卸载自己的服务提供者还原系统服务提供者时要用到这些信息,如系统服务者DLL的名称和路径。而协议链就不同了,首先我们必须安装好所有的基础协议和分层协议后,再构造协议链的WSAPROTOCOL_INFOW结构链,组成协议链的每个协议都会在协议链的ProtocolChain.ChainEntries数组中被定义,协议链数组中的第一个协议应该是第一个分层服务提供者。当然在安装分层协议及协议链时我们不会改变系统服务提供者,最多只是改变系统服务提供者的安装顺序罢了。在此,我们以分层服务提供者为例来说明数据传输服务提供者的安装过程。
Ws2_32.dll是使用标准的动态链接库来加载服务提供者接口的DLL到系统中去的,并调用WSPStartup来初始化。WSPStartup是Windows Socket 2应用程序调用SPI程序的初始化函数,也就是入口函数。WSPStartup的参数LPWSAPROTOCOL_INFOW指针提供应用程序所期望的协议信息,然后通过这个结构指针我们可以获得所保存的系统服务提供者的DLL名称和路径,加载系统服务提供者后查找到系统SPI程序的WSPStartup函数的指针,通过这个指针我们就可以将自己服务提供者的WSPStartup函数和系统SPI程序的WSPStartup函数相关联,进而调用系统的各个服务提供者函数。在数据传输服务提供者的实现中,我们需要两个程序,一个是可执行文件用来安装传输服务提供者;另一个就是DLL形式的数据传输服务提供者。下面我们就对安装程序(instif.exe)和实现程序(ipfilter.dll)所使用的主要函数进行简要分析。

三)相关程序代码分析
1.instif.exe
可执行程序instif.exe的主要功能是安装我们自己的分层传输服务提供者,并重新排列所有传输服务提供者的顺序,使我们的服务提供者位于协议链的顶端,这样相应类型的应用程序就会首先进入我们的传输服务提供者接口。本程序只有一个参数,就是安装(-install)或卸载(-remove)。作为演示,本程序只安装了IP分层协议及与UDP相关的协议链。(在ipfilter.dll中,我们只过滤目标端口为8000的UDP数据报)
自定义函数:
BOOL getfilter(); //获得所有已经安装的传输服务提供者
void freefilter(); //释放存储空间
void installfilter(); //安装分层协议,协议链及排序
void removefilter(); //卸载分层协议和协议链

代码分析:
protoinfo=(LPWSAPROTOCOL_INFOW)GlobalAlloc(GPTR,protoinfosize);
//分配WSAPROTOCOL_INFOW结构的存储空间
totalprotos=WSCEnumProtocols(NULL,protoinfo,&protoinfosize,&errorcode);
//获得系统中已安装的所有服务提供者
GetCurrentDirectory(MAX_PATH,filter_path);
//得到当前的路径
_tcscpy(filter_name,_T("//ipfilter.dll"));
//构造服务提供者文件ipfilter.dll的路径全名
WSCInstallProvider(&filterguid,filter_path,&iplayerinfo,1,&errorcode);
//安装自定义的IP分层协议
iplayercataid=protoinfo.dwCatalogEntryId;
//获得已安装自定义IP分层协议的由Ws2_32.dll分配的唯一标志
udpchaininfo.ProtocolChain.ChainEntries[0]=iplayercataid;
//将自定义的IP分层协议作为自定义UDP协议链的根分层服务提供者安装在协议链的顶端
WSCInstallProvider(&filterchainguid,filter_path,chainarray,provcnt,&errorcode);
//安装协议链
WSCWriteProviderOrder(cataentries,totalprotos);
//更新所有服务提供者的安装顺序,把自定义的服务提供者排在所有协议的最前列
WSCDeinstallProvider(&filterguid,&errorcode);
//卸载IP分层协议
WSCDeinstallProvider(&filterchainguid,&errorcode);
//卸载协议链

2.ipfilter.dll
传输服务提供者都是以动态链接库的形式存在的,在应用程序需要时由Ws2_32.dll加载,在用完之后就被卸载。本文的ipfilter.dll提供了对发送的UDP数据报进行过滤的功能。也就是自定义WSPSendTo函数,在调用系统服务提供者之前进行过滤,判断是否继续向下调用,而其他的函数都是直接调用下层的系统服务提供者由它们直接处理。传输服务提供者只有一个入口函数就是WSPStartup,它是Windows Socket 应用程序调用SPI的初始化函数,其他SPI函数的调用都是通过WSPStartup的参数WSPUPCALLTABLE来实现的。
自定义函数:
int WSPAPI WSPSendTo(SOCKET s,LPWSABUF lpbuffer,DWORD dwbuffercount,LPDWORD lpnumberofbytessent,
DWORD dwflags,const struct sockaddr FAR *lpto,int itolen,LPWSAOVERLAPPED lpoverlapped,
LPWSAOVERLAPPED_COMPLETION_ROUTINE lpcompletionroutine,LPWSATHREADID lpthreadid,LPINT lperrno);
//SPI函数WSPSendTo和Windows Socket 2的API函数WSASendTo相对应
int WSPAPI WSPStartup( WORD wversionrequested,LPWSPDATA lpwspdata,LPWSAPROTOCOL_INFOW lpprotoinfo,
WSPUPCALLTABLE upcalltable,LPWSPPROC_TABLE lpproctable);
//SPI函数WSPStartup和Windows Socket 2的API函数WSAStartup相对应,WSPStartup是唯一的入口函数,剩下的30个SPI函数则是通过参数upcalltable来实现的,它们只能在内部调用,不向外提供入口

代码分析:
GetModuleFileName(NULL,processname,MAX_PATH);
//获得调用本服务提供者动态链接库的可执行文件的全名
OutputDebugString(_T("WSPSendTo Tencent Filtered"));
//输出调试信息
nextproctable.lpWSPSendTo(s,lpbuffer,dwbuffercount,lpnumberofbytessent,dwflags,lpto,
itolen,lpoverlapped,lpcompletionroutine,lpthreadid,lperrno);
//如果数据报满足发送条件,调用下层系统服务提供者发送数据
layerid=protoinfo.dwCatalogEntryId;
//获得已安装自定义IP分层协议的由Ws2_32.dll分配的唯一标志
nextlayerid=lpprotoinfo->ProtocolChain.ChainEntries[i+1];
//获得下一层传输服务提供者的标志信息
WSCGetProviderPath(&protoinfo.ProviderId,filterpath,&filterpathlen,&errorcode);
//获得下一层传输服务提供者的安装路径
ExpandEnvironmentStrings(filterpath,filterpath,MAX_PATH);
//扩展环境变量
hfilter=LoadLibrary(filterpath));
//装载下一层传输服务提供者
wspstartupfunc=(LPWSPSTARTUP)GetProcAddress(hfilter,"WSPStartup"));
//获得下一层传输服务提供者的入口函数WSPStartup,以便调用
wspstartupfunc(wversionrequested,lpwspdata,lpprotoinfo,upcalltable,lpproctable);
//调用下一层传输服务提供者的WSPStartup函数,实现钩子功能
nextproctable=*lpproctable;
//保存下一层服务提供者的30个服务函数指针
lpproctable->lpWSPSendTo=WSPSendTo;
//调用自定义函数WSPSendTo

由于以动态链接库形式的服务提供者要向外提供一个入口函数,因此还须一个配置文件ipfilter.def:
EXPORTS WSPStartup
//向外提供入口函数WSPStartup

3.T-Sporder.exe
T-Sporder.exe是一个辅助工具,用来查看当前系统中所有已经安装的传输服务提供者的属性。
totalprotocols=WSCEnumProtocols(NULL,protoinfo,&protoinfosize,&errorcode);
//获得系统中的所有传输服务提供者,然后根据参数输出它们的各项属性。

四)小结与后记
本文向大家介绍了Windows Socket 2的一个新特性,那就是服务提供者接口SPI(Service Provider Interface)。它不仅包括我们主要讲解的传输服务提供者接口,还包括名字空间服务提供者接口。当然,基于SPI的包过滤安全措施并不是特别的好,因为很多建立在TDI上面的数据传输并不会受到SPI的影响,所以当前流行的防火墙大都是建立在NDIS之上的。
传输服务提供者是以DLL的形式存在于系统之中的,在基于IP协议的网络程序运行时,如果参数相匹配就会加载我们的传输服务提供者程序。而且在Windows下有很多系统网络服务,它们都是在系统启动时自动加载的,这就为我们隐藏木马的进程提供了有利的条件。也就是说在传输服务提供者程序里嵌入木马程序,很多基于IP协议的网络系统程序在开机时运行,这样我们嵌入的木马程序就会在系统启动时自动加载,在系统关闭时才会卸载。它的特点是只要安装一次后每每系统启动就会加载我们的传输服务提供者(里面包含木马程序),而不必像远程注入线程那样在系统每次启动时执行安装程序,并且它可同时被多个系统网络程序加载。
已编译好的可执行文件(过滤QQ数据报),您可以在我们的网站(fz5fz.yeah.net)下载。

五)附录之源程序
1.instif.exe

#define UNICODE
#define _UNICODE

#include <stdio.h>
#include <tchar.h>
#include <string.h>
#include <ws2spi.h>
#include <sporder.h>

GUID filterguid={0x4d1e91fd,0x116a,0x44aa,{0x8f,0xd4,0x1d,0x2c,0xf2,0x7b,0xd9,0xa9}};

GUID filterchainguid={0xd3c21121,0x85e1,0x48f3,{0x9a,0xb6,0x23,0xd9,0x0c,0x73,0x07,0xef}};

BOOL getfilter();
void freefilter();
void installfilter();
void removefilter();
void start();
void usage();

int totalprotos=0;
DWORD protoinfosize=0;
LPWSAPROTOCOL_INFOW protoinfo=NULL;

int main(int argc,char *argv[])
{
start();

if(argc==2)
{
if(strcmp(argv[1],&quot;-install&quot;)==0)
{
installfilter();
return 0;
}
else if(strcmp(argv[1],&quot;-remove&quot;)==0)
{
removefilter();
return 0;
}
}
usage();
return 0;
}

BOOL getfilter()
{
int errorcode;

protoinfo=NULL;
totalprotos=0;
protoinfosize=0;

if(WSCEnumProtocols(NULL,protoinfo,&protoinfosize,&errorcode)==SOCKET_ERROR)
{
if(errorcode!=WSAENOBUFS)
{
_tprintf(_T(&quot;First WSCEnumProtocols Error: %d/n&quot;),errorcode);
return FALSE;
}
}

if((protoinfo=(LPWSAPROTOCOL_INFOW)GlobalAlloc(GPTR,protoinfosize))==NULL)
{
_tprintf(_T(&quot;GlobalAlloc in getfilter Error: %d/n&quot;),GetLastError());
return FALSE;
}

if((totalprotos=WSCEnumProtocols(NULL,protoinfo,&protoinfosize,&errorcode))==SOCKET_ERROR)
{
_tprintf(_T(&quot;Second WSCEnumProtocols Error: %d/n&quot;),GetLastError());
return FALSE;
}

_tprintf(_T(&quot;Found %d protocols!/n&quot;),totalprotos);
return TRUE;
}

void freefilter()
{
GlobalFree(protoinfo);
}

void installfilter()
{
int i;
int provcnt;
int cataindex;
int errorcode;
BOOL rawip=FALSE;
BOOL udpip=FALSE;
DWORD iplayercataid=0,udporigcataid=0;
TCHAR filter_path[MAX_PATH];
TCHAR filter_name[MAX_PATH];
TCHAR chainname[WSAPROTOCOL_LEN+1];
LPDWORD cataentries;
WSAPROTOCOL_INFOW iplayerinfo,udpchaininfo,chainarray[1];

getfilter();

for(i=0;i<totalprotos;i++)
{
if(!rawip
&& protoinfo.iAddressFamily==AF_INET
&& protoinfo.iProtocol==IPPROTO_IP)
{
rawip=TRUE;
memcpy(&iplayerinfo,&protoinfo,sizeof(WSAPROTOCOL_INFOW));
iplayerinfo.dwServiceFlags1=protoinfo.dwServiceFlags1 & (~XP1_IFS_HANDLES);
}

if(!udpip
&& protoinfo.iAddressFamily==AF_INET
&& protoinfo.iProtocol==IPPROTO_UDP)
{
udpip=TRUE;
udporigcataid=protoinfo.dwCatalogEntryId;
memcpy(&udpchaininfo,&protoinfo,sizeof(WSAPROTOCOL_INFOW));
udpchaininfo.dwServiceFlags1=protoinfo.dwServiceFlags1 & (~XP1_IFS_HANDLES);
}
}

_tcscpy(iplayerinfo.szProtocol,_T(&quot;T-IpFilter&quot;));
iplayerinfo.ProtocolChain.ChainLen=LAYERED_PROTOCOL;

if(GetCurrentDirectory(MAX_PATH,filter_path)==0)
{
_tprintf(_T(&quot;GetCurrentDirectory Error: %d/n&quot;),GetLastError());
return ;
}
_tcscpy(filter_name,_T(&quot;//ipfilter.dll&quot;));
_tcscat(filter_path,filter_name);

if(WSCInstallProvider(&filterguid,filter_path,&iplayerinfo,1,&errorcode)==SOCKET_ERROR)
{
_tprintf(_T(&quot;WSCInstallProvider Error: %d/n&quot;),errorcode);
return ;
}

freefilter();

getfilter();

for(i=0;i<totalprotos;i++)
{
if(memcmp(&protoinfo.ProviderId,&filterguid,sizeof(GUID))==0)
{
iplayercataid=protoinfo.dwCatalogEntryId;
break;
}
}

provcnt=0;
if(udpip)
{
_tcscpy(chainname,_T(&quot;T-UdpFilter&quot;));
_tcscpy(udpchaininfo.szProtocol,chainname);

if(udpchaininfo.ProtocolChain.ChainLen==BASE_PROTOCOL)
{
udpchaininfo.ProtocolChain.ChainEntries[1]=udporigcataid;
}
else
{
for(i=udpchaininfo.ProtocolChain.ChainLen;i>0;i--)
{
udpchaininfo.ProtocolChain.ChainEntries[i+1]=udpchaininfo.ProtocolChain.ChainEntries;
}
}

udpchaininfo.ProtocolChain.ChainLen++;
udpchaininfo.ProtocolChain.ChainEntries[0]=iplayercataid;

memcpy(&chainarray[provcnt++],&udpchaininfo,sizeof(WSAPROTOCOL_INFOW));
}

if(WSCInstallProvider(&filterchainguid,filter_path,chainarray,provcnt,&errorcode)==SOCKET_ERROR)
{
_tprintf(_T(&quot;WSCInstallProvider for chain Error: %d/n&quot;),errorcode);
return ;
}

freefilter();

getfilter();

if((cataentries=(LPDWORD)GlobalAlloc(GPTR,totalprotos*sizeof(WSAPROTOCOL_INFOW)))==NULL)
{
_tprintf(_T(&quot;GlobalAlloc int installfilter Error: %d/n&quot;),errorcode);
return ;
}

cataindex=0;
for(i=0;i<totalprotos;i++)
{
if(memcmp(&protoinfo.ProviderId,&filterguid,sizeof(GUID))==0 || memcmp(&protoinfo.ProviderId,&filterchainguid,sizeof(GUID))==0)
{
cataentries[cataindex++]=protoinfo.dwCatalogEntryId;
}
}

for(i=0;i<totalprotos;i++)
{
if(memcmp(&protoinfo.ProviderId,&filterguid,sizeof(GUID))!=0 && memcmp(&protoinfo.ProviderId,&filterchainguid,sizeof(GUID))!=0)
{
cataentries[cataindex++]=protoinfo.dwCatalogEntryId;
}
}

if((errorcode==WSCWriteProviderOrder(cataentries,totalprotos))!=ERROR_SUCCESS)
{
_tprintf(_T(&quot;WSCWriteProviderOrder Error: %d/n&quot;),GetLastError());
return ;
}

freefilter();

_tprintf(_T(&quot;/nInstall IP Filter Successfully&quot;));
return ;
}

void removefilter()
{
int errorcode;
BOOL signal=TRUE;

if(WSCDeinstallProvider(&filterguid,&errorcode)==SOCKET_ERROR)
{
_tprintf(_T(&quot;WSCDeinstall filterguid Error: %d/n&quot;),errorcode);
signal=FALSE;
}

if(WSCDeinstallProvider(&filterchainguid,&errorcode)==SOCKET_ERROR)
{
_tprintf(_T(&quot;WSCDeinstall filterchainguid Error: %d/n&quot;),errorcode);
signal=FALSE;
}

if(signal)
{
_tprintf(_T(&quot;Deinstall IP Filter Successfully&quot;));
}
return ;
}

void start()
{
_tprintf(_T(&quot;Install IP Filter, by TOo2y/n&quot;));
_tprintf(_T(&quot;E-Mail: TOo2y@safechina.net/n&quot;));
_tprintf(_T(&quot;HomePage: fz5fz.yeah.net/n&quot;));
_tprintf(_T(&quot;Date: 10-29-2002/n/n&quot;));
return ;
}
void usage()
{
_tprintf(_T(&quot;Usage: instif [ -install | -remove ]/n&quot;));
return ;
}

2.ipfilter.dll

#define UNICODE
#define _UNICODE

#include <ws2spi.h>
#include <tchar.h>

GUID filterguid={0x4d1e91fd,0x116a,0x44aa,{0x8f,0xd4,0x1d,0x2c,0xf2,0x7b,0xd9,0xa9}};

LPWSAPROTOCOL_INFOW protoinfo=NULL;
WSPPROC_TABLE nextproctable;
DWORD protoinfosize=0;
int totalprotos=0;

BOOL getfilter()
{
int errorcode;

protoinfo=NULL;
protoinfosize=0;
totalprotos=0;

if(WSCEnumProtocols(NULL,protoinfo,&protoinfosize,&errorcode)==SOCKET_ERROR)
{
if(errorcode!=WSAENOBUFS)
{
OutputDebugString(_T(&quot;First WSCEnumProtocols Error!&quot;));
return FALSE;
}
}

if((protoinfo=(LPWSAPROTOCOL_INFOW)GlobalAlloc(GPTR,protoinfosize))==NULL)
{
OutputDebugString(_T(&quot;GlobalAlloc Error!&quot;));
return FALSE;
}

if((totalprotos=WSCEnumProtocols(NULL,protoinfo,&protoinfosize,&errorcode))==SOCKET_ERROR)
{
OutputDebugString(_T(&quot;Second WSCEnumProtocols Error!&quot;));
return FALSE;
}

return TRUE;
}

void freefilter()
{
GlobalFree(protoinfo);
}

BOOL WINAPI DllMain(HINSTANCE hmodule,
DWORD reason,
LPVOID lpreserved)
{
TCHAR processname[MAX_PATH];
TCHAR showmessage[MAX_PATH+25];


if(reason==DLL_PROCESS_ATTACH)
{
GetModuleFileName(NULL,processname,MAX_PATH);
_tcscpy(showmessage,processname);
_tcscat(showmessage,_T(&quot; Loading IPFilter ...&quot;));
OutputDebugString(showmessage);
}
return TRUE;
}

int WSPAPI WSPSendTo(SOCKET s,
LPWSABUF lpbuffer,
DWORD dwbuffercount,
LPDWORD lpnumberofbytessent,
DWORD dwflags,
const struct sockaddr FAR *lpto,
int itolen,
LPWSAOVERLAPPED lpoverlapped,
LPWSAOVERLAPPED_COMPLETION_ROUTINE lpcompletionroutine,
LPWSATHREADID lpthreadid,
LPINT lperrno)
{

struct sockaddr_in sin;

sin=*(const struct sockaddr_in *)lpto;
if(sin.sin_port==htons(8000))
{
OutputDebugString(_T(&quot;WSPSendTo Tencent Filtered&quot;));
return 0;
}
else
{
return nextproctable.lpWSPSendTo(s,lpbuffer,dwbuffercount,lpnumberofbytessent,dwflags,lpto,itolen,lpoverlapped,lpcompletionroutine,lpthreadid,lperrno);
}
}

int WSPAPI WSPStartup(
WORD wversionrequested,
LPWSPDATA lpwspdata,
LPWSAPROTOCOL_INFOW lpprotoinfo,
WSPUPCALLTABLE upcalltable,
LPWSPPROC_TABLE lpproctable
)
{
OutputDebugString(_T(&quot;IPFilter WSPStartup ...&quot;));

int i;
int errorcode;
int filterpathlen;
DWORD layerid=0;
DWORD nextlayerid=0;
TCHAR *filterpath;
HINSTANCE hfilter;
LPWSPSTARTUP wspstartupfunc=NULL;

if(lpprotoinfo->ProtocolChain.ChainLen<=1)
{
OutputDebugString(_T(&quot;ChainLen<=1&quot;));
return FALSE;
}

getfilter();

for(i=0;i<totalprotos;i++)
{
if(memcmp(&protoinfo.ProviderId,&filterguid,sizeof(GUID))==0)
{
layerid=protoinfo.dwCatalogEntryId;
break;
}
}

for(i=0;i<lpprotoinfo->ProtocolChain.ChainLen;i++)
{
if(lpprotoinfo->ProtocolChain.ChainEntries==layerid)
{
nextlayerid=lpprotoinfo->ProtocolChain.ChainEntries[i+1];
break;
}
}

filterpathlen=MAX_PATH;
filterpath=(TCHAR*)GlobalAlloc(GPTR,filterpathlen);
for(i=0;i<totalprotos;i++)
{
if(nextlayerid==protoinfo.dwCatalogEntryId)
{
if(WSCGetProviderPath(&protoinfo.ProviderId,filterpath,&filterpathlen,&errorcode)==SOCKET_ERROR)
{
OutputDebugString(_T(&quot;WSCGetProviderPath Error!&quot;));
return WSAEPROVIDERFAILEDINIT;
}
break;
}
}

if(!ExpandEnvironmentStrings(filterpath,filterpath,MAX_PATH))
{
OutputDebugString(_T(&quot;ExpandEnvironmentStrings Error!&quot;));
return WSAEPROVIDERFAILEDINIT;
}

if((hfilter=LoadLibrary(filterpath))==NULL)
{
OutputDebugString(_T(&quot;LoadLibrary Error!&quot;));
return WSAEPROVIDERFAILEDINIT;
}

if((wspstartupfunc=(LPWSPSTARTUP)GetProcAddress(hfilter,&quot;WSPStartup&quot;))==NULL)
{
OutputDebugString(_T(&quot;GetProcessAddress Error!&quot;));
return WSAEPROVIDERFAILEDINIT;
}

if((errorcode=wspstartupfunc(wversionrequested,lpwspdata,lpprotoinfo,upcalltable,lpproctable))!=ERROR_SUCCESS)
{
OutputDebugString(_T(&quot;wspstartupfunc Error!&quot;));
return errorcode;
}

nextproctable=*lpproctable;
lpproctable->lpWSPSendTo=WSPSendTo;

freefilter();
return 0;
}
 
补:NDIS的PASSTHRU层的驱动程序
==========================================
NDIS的PASSTHRU层的驱动程序,MySource应用层的程序,负责向驱动程序发指令,本来是想做防火墙的
==========================================

下载地点:

http://210.21.115.122/datanew/2004081010591630895.zip
 
书写NDIS过滤钩子驱动实现ip包过滤
作者: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 &quot;ntddk.h&quot;
#include &quot;ntddndis.h&quot;
#include &quot;pfhook.h&quot;
#ifndef __NTHANDLE_H
#define __NTHANDLE_H

#define NT_DEVICE_NAME L&quot;//Device//Fxfilthook&quot;
#define DOS_DEVICE_NAME L&quot;//DosDevices//Fxfilthook&quot;

#define PROT_TCP 6

#include &quot;ntddk.h&quot;
#include &quot;xfilthook.h&quot;

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 &quot;ntddk.h&quot;
#include &quot;ntddndis.h&quot;
#include &quot;pfhook.h&quot;
#include &quot;fxfilthook.h&quot;

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( &quot;Leave DriverEntry failed/n&quot; );
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&quot;//Device//IPFILTERDRIVER&quot;);
//将钩子挂接函数放入结构中
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&quot;//Device//IPFILTERDRIVER&quot;);
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,&quot;System//CurrentControlSet//Services//%s&quot;,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,&quot;Start&quot;,0,4,(const unsigned char *)Data,4);
Data[0]=1;
isok=RegSetValueEx(hkResult,&quot;Type&quot;,0,4,(const unsigned char *)Data,4);
isok=RegSetValueEx(hkResult,&quot;ErrorControl&quot;,0,4,(const unsigned char *)Data,4);
GetSystemDirectory(sysdir,256);
buflen = sprintf(drivcedir,&quot;%s//Drivers//FxFiltHook.sys&quot;,sysdir);
buflen = sprintf(subkey,&quot;//??//%s&quot;,drivcedir);
subkey[buflen]=0;
isok=RegSetValueEx(hkResult,&quot;ImagePath&quot;,0,1,(const unsigned char *)subkey,buflen);
RegCloseKey(hkResult);
buflen = sprintf(subkey,&quot;//Registry//Machine//System//CurrentControlSet//Services//%s&quot;,exename);
subkey[buflen]=0;
return TRUE;
}

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

Similar threads

D
回复
0
查看
834
DelphiTeacher的专栏
D
D
回复
0
查看
2K
DelphiTeacher的专栏
D
D
回复
0
查看
1K
DelphiTeacher的专栏
D
D
回复
0
查看
1K
DelphiTeacher的专栏
D
D
回复
0
查看
2K
DelphiTeacher的专栏
D
后退
顶部