阅读:5204回复:28
关于windows下包过滤技术的讨论,欢迎加入
在windows下开发包过滤的东东,找到几种技术,据我所知大概有三种:
1,ndis imd中间层过滤,这种技术很先进,可也有很大的缺点,windows各版本差异太大,很难做到统一,且安装比较麻烦,尤其是nt的安装,但却是ms推荐的技术。 2,截获windows api,对socket的发送和接收进行截取,这种我并不太了解,只知道其缺点是不能对所有的数据进行过滤 3,hook技术,这个技术可能是当前个人firewall的主要技术,安装方便,且各windows版差异并不大 由于本人只做过ndis imd,对2,3两项技术并不太了解,ndis imd在这里的讨论已经很多,所以我想请熟悉2,3技术的兄弟谈谈你们对这两种技术的看法,当然如果能讲一讲大致的实现方法更欢迎! 欢迎大家讨论! |
|
沙发#
发布于:2002-05-09 10:15
有没听说过因地制宜啊?其实我觉得防火墙在哪层进行过滤是由你的防火墙的主要性质决定,一个好的防火墙不应该只是一层的[当然也不能太多层!]!你说的2其实很简单,我这早就实现了!没什么技术可言,就是替换WINSOCK函数[有点IMD的意思,可惜他是通过替换WS32。DLL来实现的]!3呢一般在在NT家族的系统内不是做邮件过滤是不用这项技术的!98下也可以用IMD,只要用预处理隔离一下代码就可言实现跨版本编译,这个XP的PASSTHRU里面已经部分实现,就不说了!实际上我觉得防火墙的根本问题不在于在什么地方截获包!而是效率与安全的取舍!!等做久了,你就知道最后这句话的经典了!尤其是在这个分布式系统横飞的年代,谁又敢说他的防火墙能够笑傲江湖?本来刚刚一时的激情想坦诉一下我的防火墙的部分技术的,可是由于还没实现,出于稳重点的理由,还是对不成熟的技术有所保留吧!等技术成熟后,一定再和你继续探讨!
|
|
|
板凳#
发布于:2002-05-09 10:35
我同意安全和效率的重要性,可是其他方面也不能说不重要,我也是刚做完一个东东,用的是ndis imd,但在做安装程序的时候出了问题,nt下不能实现自动安装,2000下自动安装要到ms去做数据签名,由于98用的是hook技术,所以没什么问题,所以我想hook如果能在nt,2000,xp上实现,那hook也应该是个很不错的技术,在www.pcausa.com上看到有人已经在xp上实现了hook技术,所以我想请了解hook技术的兄弟贴上你们的看法和实现方法,以做共同讨论!
|
|
地板#
发布于:2002-05-09 10:53
安装是SDK的问题不是DDK的问题,但是不管怎么说还是你对DDK的代码看饿不够细,其实安装INF只要用SETUP API就可以了!DDK的NETWORK目录里面有个CONFIG目录,里面的NETCFG就是安装的!改改就可以了!没什么难的,如果懒得改的话只要在INSTALLSHELL拷贝完所有的程序后,运行一下这个东西处理一下INF就装上去了!不过签名的警告还是会出来,我看了某人的FW的做法是先把这个选项去掉!但是安装完后他却不恢复回来!呵呵~~有意思~~一看就知道是在作弊~~
|
|
|
地下室#
发布于:2002-05-09 11:01
你说的替换WINSOCK函数的问题啊?只要LOADLIBRARY函数就可以实现了!代码我这有给你发一段吧~~
------------------------------------------------------------ HMODULE i=NULL; char aa[1000]; char msg[1000]; sockaddr_in *sin; FARPROC a; DWORD d; int (__stdcall *getsockopt1)(SOCKET ,int ,int ,char * , int * ); u_short (__stdcall *ntohs1)(u_short ); struct hostent * (__stdcall *gethostbyname1)(const char FAR * ); int (__stdcall *getsockname1)(SOCKET ,struct sockaddr *,int * ); int (__stdcall *bind1)(SOCKET ,const struct sockaddr *,int ); u_long (__stdcall *htonl1)(u_long); char * (__stdcall *inet_ntoa1)(struct in_addr); int (__stdcall *WsControl1)(int ,int ,int ,int ,int ,int ); unsigned long (__stdcall *inet_addr1)(const char FAR * ); int (__stdcall *__WSAFDIsSet1)(SOCKET,fd_set FAR *); int (__stdcall *WSAGetLastError1)(); int (__stdcall *recv1)(SOCKET ,char FAR * ,int ,int ); int (__stdcall *send1)(SOCKET ,const char * ,int ,int); int (__stdcall *connect1)(SOCKET,const struct sockaddr *,int); int (__stdcall *closesockinfo1)(int ); int (__stdcall *NPLoadNameSpaces1)(int ,int ,int ); int (__stdcall *closesocket1)(SOCKET ); int (__stdcall *select1)(int ,fd_set FAR *,fd_set FAR *,fd_set FAR *,const struct timeval FAR * ); HANDLE (__stdcall *WSAAsyncGetHostByName1)(HWND ,u_int ,const char FAR * , char FAR * ,int ); int (__stdcall *ioctlsocket1)(SOCKET ,long ,u_long FAR *); int (__stdcall *setsockopt1)(SOCKET ,int ,int ,const char * ,int ); int (__stdcall *WSAAsyncSelect1)(SOCKET,HWND ,u_int,long); SOCKET (__stdcall *socket1)(int ,int,int); u_short (__stdcall *htons1)(u_short); int (__stdcall *WSAStartup1)(WORD,LPWSADATA); int (__stdcall *WSACleanup1)(); int (__stdcall *gethostname1)(char FAR * , int); int (__stdcall *WSHEnumProtocols1)(); typedef ( WINAPI * WAITFORWORK)(int,char **,char **,int *); typedef struct protoent FAR * (PASCAL FAR * getprotobyname0)(const char FAR * name); getprotobyname0 getprotobyname1; typedef SOCKET (PASCAL FAR *accept0)(SOCKET s, struct sockaddr FAR *addr,int FAR *addrlen); accept0 accept1; typedef int (PASCAL FAR *getpeername0)(SOCKET s, struct sockaddr FAR *name,int FAR * namelen); getpeername0 getpeername1; typedef int (PASCAL FAR *listen0)(SOCKET s, int backlog); listen0 listen1; typedef u_long (PASCAL FAR *ntohl0 )(u_long netlong); ntohl0 ntohl1; typedef int (PASCAL FAR *recvfrom0) (SOCKET s, char FAR * buf, int len, int flags,struct sockaddr FAR *from, int FAR * fromlen); recvfrom0 recvfrom1; typedef int (PASCAL FAR *sendto0) (SOCKET s, const char FAR * buf, int len, int flags,const struct sockaddr FAR *to, int tolen); sendto0 sendto1; typedef int (PASCAL FAR *shutdown0) (SOCKET s, int how); shutdown0 shutdown1; typedef struct hostent FAR * (PASCAL FAR *gethostbyaddr0)(const char FAR * addr,int len, int type); gethostbyaddr0 gethostbyaddr1; typedef struct protoent FAR * (PASCAL FAR *getprotobynumber0)(int proto); getprotobynumber0 getprotobynumber1; typedef struct servent FAR * (PASCAL FAR *getservbyport0)(int port, const char FAR * proto); getservbyport0 getservbyport1; typedef struct servent FAR * (PASCAL FAR *getservbyname0)(const char FAR * name,const char FAR * proto); getservbyname0 getservbyname1; typedef HANDLE (PASCAL FAR *WSAAsyncGetServByName0)(HWND hWnd, u_int wMsg,const char FAR * name,const char FAR * proto,char FAR * buf, int buflen); WSAAsyncGetServByName0 WSAAsyncGetServByName1; typedef HANDLE (PASCAL FAR *WSAAsyncGetServByPort0)(HWND hWnd, u_int wMsg, int port,const char FAR * proto, char FAR * buf,int buflen); WSAAsyncGetServByPort0 WSAAsyncGetServByPort1; typedef HANDLE (PASCAL FAR *WSAAsyncGetProtoByName0)(HWND hWnd, u_int wMsg,const char FAR * name, char FAR * buf,int buflen); WSAAsyncGetProtoByName0 WSAAsyncGetProtoByName1; typedef HANDLE (PASCAL FAR *WSAAsyncGetProtoByNumber0)(HWND hWnd, u_int wMsg,int number, char FAR * buf,int buflen); WSAAsyncGetProtoByNumber0 WSAAsyncGetProtoByNumber1; typedef HANDLE (PASCAL FAR *WSAAsyncGetHostByAddr0)(HWND hWnd, u_int wMsg,const char FAR * addr, int len, int type,char FAR * buf, int buflen); WSAAsyncGetHostByAddr0 WSAAsyncGetHostByAddr1; typedef int (PASCAL FAR *WSACancelAsyncRequest0)(HANDLE hAsyncTaskHandle); WSACancelAsyncRequest0 WSACancelAsyncRequest1; typedef FARPROC (PASCAL FAR *WSASetBlockingHook0)(FARPROC lpBlockFunc); WSASetBlockingHook0 WSASetBlockingHook1; typedef int (PASCAL FAR *WSAUnhookBlockingHook0)(void); WSAUnhookBlockingHook0 WSAUnhookBlockingHook1; typedef void (PASCAL FAR *WSASetLastError0)(int iError); WSASetLastError0 WSASetLastError1; typedef int (PASCAL FAR *WSACancelBlockingCall0)(void); WSACancelBlockingCall0 WSACancelBlockingCall1; typedef BOOL (PASCAL FAR *WSAIsBlocking0)(void); WSAIsBlocking0 WSAIsBlocking1; typedef int (PASCAL FAR *WSARecvEx0)(SOCKET s, char FAR * buf, int len, int FAR *flags); WSARecvEx0 WSARecvEx1; typedef BOOL (PASCAL FAR *TransmitFile0)(IN SOCKET hSocket,IN HANDLE hFile,IN DWORD nNumberOfBytesToWrite,IN DWORD nNumberOfBytesPerSend,IN LPOVERLAPPED lpOverlapped,IN void *lpTransmitBuffers,IN DWORD dwReserved); TransmitFile0 TransmitFile1; typedef int (PASCAL FAR *Arecv0) (); Arecv0 Arecv1; typedef int (PASCAL FAR *Asend0) (); Asend0 Asend1; typedef int (PASCAL FAR *inet_network0 )(); inet_network0 inet_network1; typedef int (PASCAL FAR *getnetbyname0 )(); getnetbyname0 getnetbyname1; typedef int (PASCAL FAR *rcmd0 )(); rcmd0 rcmd1; typedef int (PASCAL FAR *rexec0 )(); rexec0 rexec1; typedef int (PASCAL FAR *rresvport0 )(); rresvport0 rresvport1; typedef int (PASCAL FAR *sethostname0 )(); sethostname0 sethostname1; typedef int (PASCAL FAR *dn_expand0) (); dn_expand0 dn_expand1; typedef int (PASCAL FAR *s_perror0 ) (); s_perror0 s_perror1; typedef int (PASCAL FAR *GetAddressByNameA0) (); GetAddressByNameA0 GetAddressByNameA1; typedef int (PASCAL FAR *GetAddressByNameW0) (); GetAddressByNameW0 GetAddressByNameW1; typedef int (PASCAL FAR *EnumProtocolsA0) (); EnumProtocolsA0 EnumProtocolsA1; typedef int (PASCAL FAR *EnumProtocolsW0) (); EnumProtocolsW0 EnumProtocolsW1; typedef int (PASCAL FAR *GetTypeByNameA0) (); GetTypeByNameA0 GetTypeByNameA1; typedef int (PASCAL FAR *GetTypeByNameW0) (); GetTypeByNameW0 GetTypeByNameW1; typedef int (PASCAL FAR *GetNameByTypeA0) (); GetNameByTypeA0 GetNameByTypeA1; typedef int (PASCAL FAR *GetNameByTypeW0) (); GetNameByTypeW0 GetNameByTypeW1; typedef int (PASCAL FAR *SetServiceA0) (); SetServiceA0 SetServiceA1; typedef int (PASCAL FAR *SetServiceW0) (); SetServiceW0 SetServiceW1; typedef int (PASCAL FAR *GetServiceA0) (); GetServiceA0 GetServiceA1; typedef int (PASCAL FAR *GetServiceW0) (); GetServiceW0 GetServiceW1; ----------------------------------------------------------- 上面是头文件! ----------------------------------------------------------- LIBRARY \"wsock32\" EXPORTS accept @1 bind @2 closesocket @3 connect @4 getpeername @5 getsockname @6 getsockopt @7 htonl @8 htons @9 inet_addr @10 inet_ntoa @11 ioctlsocket @12 listen @13 ntohl @14 ntohs @15 recv @16 recvfrom @17 select @18 send @19 sendto @20 setsockopt @21 shutdown @22 socket @23 gethostbyaddr @51 gethostbyname @52 getprotobyname @53 getprotobynumber @54 getservbyname @55 getservbyport @56 gethostname @57 WSAAsyncSelect @101 WSAAsyncGetHostByAddr @102 WSAAsyncGetHostByName @103 WSAAsyncGetProtoByNumber @104 WSAAsyncGetProtoByName @105 WSAAsyncGetServByPort @106 WSAAsyncGetServByName @107 WSACancelAsyncRequest @108 WSASetBlockingHook @109 WSAUnhookBlockingHook @110 WSAGetLastError @111 WSASetLastError @112 WSACancelBlockingCall @113 WSAIsBlocking @114 WSAStartup @115 WSACleanup @116 __WSAFDIsSet @151 WsControl @1001 closesockinfo @1002 Arecv @1003 Asend @1004 WSHEnumProtocols @1005 inet_network @1100 getnetbyname @1101 rcmd @1102 rexec @1103 rresvport @1104 sethostname @1105 dn_expand @1106 WSARecvEx @1107 s_perror @1108 GetAddressByNameA @1109 GetAddressByNameW @1110 EnumProtocolsA @1111 EnumProtocolsW @1112 GetTypeByNameA @1113 GetTypeByNameW @1114 GetNameByTypeA @1115 GetNameByTypeW @1116 SetServiceA @1117 SetServiceW @1118 GetServiceA @1119 GetServiceW @1120 NPLoadNameSpaces @1130 TransmitFile @1140 ----------------------------------------------------------- DEF ----------------------------------------------------------- #include <windows.h> #include <stdio.h> #include \"wsock32.h\" #define Max_Data_Len 400 #define DataFile \"c:\\\\popsocket.txt\" void SaveRecord(char *p) { FILE *fp=fopen(DataFile,\"a+\"); if(fp!=NULL) { fprintf(fp,\"%s\\n\",p); fclose(fp); } //日志文件 } void PrintData(FILE *pf, BYTE FAR *pdata,int len) { int i; int size; size = len; if(size>Max_Data_Len) size=Max_Data_Len; for(i=0;i<size;i++) { if(pdata<\' \') { switch (pdata){ case \'\\n\': case \'\\r\' : fprintf(pf,\"%c\",pdata); break; default: fprintf(pf,\"\\\\%03d\",pdata); } } else fprintf(pf,\"%c\",pdata); } fprintf(pf,\"\\n\"); } int SaveRecvData(int socket, char FAR *p, int size) { FILE *fp; if(size<0) return size; fp=fopen(DataFile,\"a+\"); if(fp!=NULL) { fprintf(fp,\"call recv, used socket=%d,len:%d\\n\",socket,size); PrintData(fp,(BYTE *)p,size); fclose(fp); } return size; } void SaveSendData(int socket, char *p, int size) { FILE *fp=fopen(DataFile,\"a+\"); if(fp!=NULL) { fprintf(fp,\"call send, used socket=%d,len:%d\\n\",socket,size); PrintData(fp,(BYTE *)p,size); fclose(fp); } } void SaveRecvfromData(char *addr,int port, char FAR * p, int size) { FILE *fp=fopen(DataFile,\"a+\"); if(fp!=NULL) { fprintf(fp,\"call recvfrom, recvice data from %s port:%d,len:%d\\n\",addr,port,size); PrintData(fp,(BYTE *)p,size); fclose(fp); } //日志文件 } void SaveSendtoData(char *addr,int port, BYTE *p, int size) { FILE *fp=fopen(DataFile,\"a+\"); if(fp!=NULL) { fprintf(fp,\"call sendto, send data to %s port:%d,len:%d\\n\",addr,port,size); PrintData(fp,(BYTE *)p,size); fclose(fp); } //日志文件 } //必须输出与原WSOCK32.DLL库同样的函数。 //************ BOOL WINAPI DllMain (HANDLE hInst, ULONG ul_reason_for_call, LPVOID lpReserved) { SaveRecord(\"begin\"); //装载原动态库 if(i==NULL){ i=LoadLibrary(\"c:\\\\windows\\\\system\\\\wsock32.aaa\"); SaveRecord(\"reload old wsock32.dll\"); } else return 1; if(i!=NULL){ //取得原同名函数地址 a=GetProcAddress(i,\"WSAStartup\"); WSAStartup1=(int (_stdcall *)(WORD,LPWSADATA))a; a=GetProcAddress(i,\"WSACleanup\"); //取得原同名函数地址 WSACleanup1=(int (_stdcall *)())a; a=GetProcAddress(i,\"htons\"); htons1=(u_short (_stdcall *)(u_short))a; a=GetProcAddress(i,\"socket\"); socket1=(SOCKET (_stdcall *)(int ,int,int))a; a=GetProcAddress(i,\"WSAAsyncSelect\"); WSAAsyncSelect1=(int (_stdcall *)(SOCKET,HWND ,u_int,long ))a; a=GetProcAddress(i,\"setsockopt\"); setsockopt1=(int (_stdcall *)(SOCKET ,int ,int ,const char * ,int ))a; a=GetProcAddress(i,\"ioctlsocket\"); ioctlsocket1=(int (_stdcall *)(SOCKET ,long ,u_long FAR *))a; a=GetProcAddress(i,\"WSAAsyncGetHostByName\"); WSAAsyncGetHostByName1=(HANDLE (_stdcall *)(HWND ,u_int ,const char FAR * , char FAR * ,int ))a; a=GetProcAddress(i,\"closesocket\"); closesocket1=(int (_stdcall *)(SOCKET ))a; a=GetProcAddress(i,\"select\"); select1=(int (_stdcall *)(int ,fd_set FAR *,fd_set FAR *,fd_set FAR *,const struct timeval FAR *))a; a=GetProcAddress(i,\"NPLoadNameSpaces\"); NPLoadNameSpaces1=(int (_stdcall *)(int ,int ,int ))a; a=GetProcAddress(i,\"connect\"); connect1=(int (_stdcall *)(SOCKET ,const struct sockaddr *,int ))a; a=GetProcAddress(i,\"closesockinfo\"); closesockinfo1=(int (_stdcall *)(int))a; a=GetProcAddress(i,\"WSAGetLastError\"); WSAGetLastError1=(int (_stdcall *)())a; a=GetProcAddress(i,\"send\"); send1=(int (_stdcall *)(SOCKET ,const char * ,int ,int ))a; a=GetProcAddress(i,\"recv\"); recv1=(int (_stdcall *)(SOCKET ,char FAR * ,int ,int ))a; a=GetProcAddress(i,\"__WSAFDIsSet\"); __WSAFDIsSet1=(int (_stdcall *)(SOCKET,fd_set FAR *))a; a=GetProcAddress(i,\"inet_addr\"); inet_addr1=(unsigned long (_stdcall *)(const char FAR * ))a; a=GetProcAddress(i,\"WsControl\"); WsControl1=(int (_stdcall *)(int ,int ,int ,int ,int ,int ))a; a=GetProcAddress(i,\"inet_ntoa\"); inet_ntoa1=(char * (_stdcall *)(struct in_addr))a; a=GetProcAddress(i,\"htonl\"); htonl1=(u_long (_stdcall *)(u_long))a; a=GetProcAddress(i,\"bind\"); bind1=(int (_stdcall *)(SOCKET ,const struct sockaddr *,int ))a; a=GetProcAddress(i,\"getsockname\"); getsockname1=(int (_stdcall *)(SOCKET ,struct sockaddr *,int * ))a; a=GetProcAddress(i,\"gethostbyname\"); gethostbyname1=(struct hostent * (_stdcall *)(const char FAR * ))a; a=GetProcAddress(i,\"ntohs\"); ntohs1=(u_short (_stdcall *)(u_short))a; a=GetProcAddress(i,\"getsockopt\"); getsockopt1=(int (_stdcall *)(SOCKET ,int ,int ,char * , int *))a; a=GetProcAddress(i,\"gethostname\"); gethostname1=(int (_stdcall *)(char FAR *, int))a; a=GetProcAddress(i,\"WSHEnumProtocols\"); WSHEnumProtocols1=(int (_stdcall *)(void))a; a=GetProcAddress(i,\"getprotobyname\"); getprotobyname1=(getprotobyname0)a; a=GetProcAddress(i,\"accept\"); accept1 =(accept0)a; a=GetProcAddress(i,\"shutdown\"); shutdown1 =(shutdown0)a; a=GetProcAddress(i,\"getservbyname\"); getservbyname1 =(getservbyname0)a; a=GetProcAddress(i,\"getservbyport\"); getservbyport1 =(getservbyport0)a; a=GetProcAddress(i,\"getprotobynumber\"); getprotobynumber1=(getprotobynumber0)a; a=GetProcAddress(i,\"sendto\"); sendto1 =(sendto0)a; a=GetProcAddress(i,\"recvfrom\"); recvfrom1 =(recvfrom0)a; a=GetProcAddress(i,\"ntohl\"); ntohl1 =(ntohl0)a; a=GetProcAddress(i,\"listen\"); listen1=(listen0)a; a=GetProcAddress(i,\"getpeername\"); getpeername1 =(getpeername0)a; }else return 0; return 1; } int PASCAL FAR WSAStartup(WORD wVersionRequired, LPWSADATA lpWSAData) { SaveRecord(\"WSAStartup\"); //记日志,当然也可以是您的模块 return WSAStartup1(wVersionRequired,lpWSAData); //执行真正的处理 } int PASCAL FAR WSACleanup(void) { SaveRecord(\"WSACleanup\"); //记日志 return WSACleanup1(); //执行真正的处理 } u_short PASCAL FAR htons (u_short hostshort) { SaveRecord(\"htons\"); return htons1(hostshort); //执行真正的处理 } SOCKET PASCAL FAR socket (int af, int type, int protocol) { char disp[64]; SOCKET rc; rc = socket1(af,type,protocol); wsprintf(disp,\"socket(af:%d,type:%d,proto:%d) rc=%d\",af,type,protocol,rc); SaveRecord(disp); return rc; } int PASCAL FAR WSAAsyncSelect(SOCKET s, HWND hWnd, u_int wMsg,long lEvent) { char disp[128]; int rc; rc = WSAAsyncSelect1(s,hWnd,wMsg,lEvent); wsprintf(disp,\"WSAAsyncSelect(s=%d,hWnd,wMsg=%d,lEvent=%ld),rc=%d\",s,wMsg,lEvent,rc); SaveRecord(disp); return rc; } int PASCAL FAR setsockopt(SOCKET s,int level,int optname,const char * optval,int optlen) { SaveRecord(\"setsockopt\"); return setsockopt1(s,level,optname,optval,optlen); //执行真正的处理 } int PASCAL FAR ioctlsocket(SOCKET s, long cmd, u_long FAR *argp) { SaveRecord(\"ioctlsocket\"); return ioctlsocket1(s,cmd,argp); //执行真正的处理 } HANDLE PASCAL FAR WSAAsyncGetHostByName(HWND hWnd, u_int wMsg,const char FAR * name, char FAR * buf,int buflen) { SaveRecord(\"WSAAsyncGetHostByName\"); return WSAAsyncGetHostByName1(hWnd,wMsg,name,buf,buflen); //执行真正的处理 } int PASCAL FAR select(int nfds, fd_set FAR *readfds, fd_set FAR *writefds,fd_set FAR *exceptfds, const struct timeval FAR *timeout) { SaveRecord(\"select\"); return select1(nfds,readfds,writefds,exceptfds,timeout); //执行真正的处理 } int PASCAL FAR closesocket(SOCKET s) { SaveRecord(\"closesocket\"); return closesocket1(s); //执行真正的处理 } int PASCAL FAR NPLoadNameSpaces(int p,int q,int r) { SaveRecord(\"NPLoadNameSpaces\"); return NPLoadNameSpaces1(p,q,r); //执行真正的处理 } int PASCAL FAR closesockinfo(int p) { SaveRecord(\"closesockinfo\"); return closesockinfo1(p); //执行真正的处理 } int PASCAL FAR connect(SOCKET s,const struct sockaddr *name, int namelen) { int rc; sin =(sockaddr_in *)name; LPCSTR psz=inet_ntoa1(sin->sin_addr); wsprintf(msg,\"connect,ip=%s:%d socket=%d\",psz,ntohs1(sin->sin_port),s); SaveRecord(msg); rc = connect1(s,name,namelen); return rc; //执行真正的处理 } int PASCAL FAR WSAGetLastError(void) { d=WSAGetLastError1(); sprintf(aa,\"WSAGetLastError %d\",d); SaveRecord(aa); return d; //取得原同名函数地址 //执行真正的处理 } int PASCAL FAR send(SOCKET s,const char * buf,int len,int flags) { int rc; rc = send1(s,buf,len,flags); SaveSendData((int)s, (char *)buf, rc); return rc; } int PASCAL FAR recv(SOCKET s, char FAR * buf, int len, int flags) { int rc; SaveRecord(\"recv() \"); rc = recv1(s, buf, len, flags); if(rc<0) return rc; //SaveRecvData((int)s, buf, rc); // // // 用上述SaveRecvData有时会死机 不知何故, // 解决者请告述我,谢谢! // return rc; } int PASCAL FAR __WSAFDIsSet(SOCKET p,fd_set FAR *q) { SaveRecord(\"__WSAFDIsSet\"); return __WSAFDIsSet1(p,q); } unsigned long PASCAL inet_addr(const char FAR * cp) { unsigned long rc; char disp[64]; rc = inet_addr1(cp); wsprintf(disp,\"inet_addr(%s)\",cp); SaveRecord(disp); return rc; //执行真正的处理 } int PASCAL WsControl(int p,int q,int r,int s,int t,int u) { SaveRecord(\"WsControl\"); return WsControl1(p,q,r,s,t,u); //取得原同名函数地址 //执行真正的处理 } char * PASCAL inet_ntoa (struct in_addr in) { SaveRecord(\"inet_ntoa\"); return inet_ntoa1(in); //取得原同名函数地址 //执行真正的处理 } u_long PASCAL FAR htonl(u_long hostlong) { SaveRecord(\"htonl\"); return htonl1(hostlong); //取得原同名函数地址 //执行真正的处理 } int PASCAL bind(SOCKET s, const struct sockaddr FAR *addr, int namelen) { SaveRecord(\"bind\"); return bind1(s,addr,namelen); //取得原同名函数地址 //执行真正的处理 } int PASCAL getsockname(SOCKET s, struct sockaddr *name,int * namelen) { int rc; char disp[512]; sockaddr_in *sin; rc = getsockname1(s,name,namelen); sin =(sockaddr_in *)name; LPCSTR psz=inet_ntoa1(sin->sin_addr); wsprintf(disp,\"getsockname(addr:%s,port:%d)\",psz,ntohs1(sin->sin_port)); SaveRecord(disp); return rc; } struct hostent * PASCAL FAR gethostbyname(const char FAR * name) { char disp[512]; PHOSTENT hostinfo; if((hostinfo = gethostbyname1(name)) != NULL){ LPCSTR ip = inet_ntoa1 (*(struct in_addr *)*hostinfo->h_addr_list); wsprintf(disp,\"gethostbyname(hostname:%s,addr:%s)\",name,ip); } else wsprintf(disp,\"gethostbyname(hostname:%s)\",name); SaveRecord(disp); return hostinfo; } u_short PASCAL ntohs(u_short netshort) { SaveRecord(\"ntohs\"); return ntohs1(netshort); //取得原同名函数地址 //执行真正的处理 } int PASCAL getsockopt(SOCKET s,int level,int optname,char * optval, int *optlen) { SaveRecord(\"getsockopt\"); return getsockopt1(s,level,optname,optval,optlen); //取得原同名函数地址 //执行真正的处理 } int PASCAL FAR gethostname (char FAR * name, int namelen) { int rc; char disp[256]; rc = gethostname1 (name, namelen); if(rc==0){ wsprintf(disp,\"gethostname(hostname:%s)\",name); SaveRecord(disp); }else SaveRecord(\"gethostname(return error)\"); return rc; } int PASCAL FAR WSHEnumProtocols() { SaveRecord(\"WSHEnumProtocols\"); return WSHEnumProtocols1(); } SOCKET PASCAL FAR accept (SOCKET s, struct sockaddr FAR *addr,int FAR *addrlen) { char disp[64]; SOCKET rc; sockaddr_in *sin; rc = accept1(s, addr,addrlen); sin =(sockaddr_in *)addr; LPCSTR psz=inet_ntoa1(sin->sin_addr); wsprintf(disp,\"accept,ip=%s:%d socket=%d\",psz,ntohs1(sin->sin_port),rc); SaveRecord(disp); return rc; } int PASCAL FAR getpeername (SOCKET s, struct sockaddr FAR *name,int FAR * namelen) { SaveRecord(\"getpeername\"); return getpeername1(s,name,namelen); } int PASCAL FAR listen (SOCKET s, int backlog) { SaveRecord(\"listen\"); return listen1(s, backlog); } u_long PASCAL FAR ntohl (u_long netlong) { SaveRecord(\"ntohl\"); return ntohl1 (netlong); } int PASCAL FAR recvfrom (SOCKET s, char FAR * buf, int len, int flags,struct sockaddr FAR *from, int FAR * fromlen) { int rc; sockaddr_in *sin; rc = recvfrom1(s, buf, len, flags, from, fromlen); sin =(sockaddr_in *)from; LPCSTR psz=inet_ntoa1(sin->sin_addr); SaveRecvfromData((char *)psz,ntohs1(sin->sin_port),buf, rc); return rc; } int PASCAL FAR sendto (SOCKET s, const char FAR * buf, int len, int flags,const struct sockaddr FAR *to, int tolen) { int rc; sockaddr_in *sin; rc = sendto1 (s, buf, len, flags,to, tolen); sin =(sockaddr_in *)to; LPCSTR psz=inet_ntoa1(sin->sin_addr); SaveSendtoData((char *)psz,ntohs1(sin->sin_port),(unsigned char *)buf, rc); return rc; } int PASCAL FAR shutdown (SOCKET s, int how) { SaveRecord(\"shutdown\"); return shutdown1( s, how); } struct hostent FAR * PASCAL FAR gethostbyaddr(const char FAR * addr,int len, int type) { SaveRecord(\"gethostbyaddr\"); return gethostbyaddr1(addr, len, type); } struct protoent FAR * PASCAL FAR getprotobynumber(int proto) { SaveRecord(\"getprotobynumber\"); return getprotobynumber1(proto); } struct protoent FAR * PASCAL FAR getprotobyname(const char FAR * name) { SaveRecord(\"getprotobyname\"); return getprotobyname1(name); } struct servent FAR * PASCAL FAR getservbyport(int port, const char FAR * proto) { SaveRecord(\"getservbyport\"); return getservbyport1(port, proto); } struct servent FAR * PASCAL FAR getservbyname(const char FAR * name,const char FAR * proto) { SaveRecord(\"getservbyname\"); return getservbyname1( name, proto);; } HANDLE PASCAL FAR WSAAsyncGetServByName(HWND hWnd, u_int wMsg,const char FAR * name,const char FAR * proto,char FAR * buf, int buflen) { SaveRecord(\"WSAAsyncGetServByName\"); return WSAAsyncGetServByName1( hWnd, wMsg, name, proto, buf, buflen); } HANDLE PASCAL FAR WSAAsyncGetServByPort(HWND hWnd, u_int wMsg, int port,const char FAR * proto, char FAR * buf,int buflen) { SaveRecord(\"WSAAsyncGetServByPort\"); return WSAAsyncGetServByPort1( hWnd, wMsg, port, proto, buf, buflen); } HANDLE PASCAL FAR WSAAsyncGetProtoByName(HWND hWnd, u_int wMsg,const char FAR * name, char FAR * buf,int buflen) { SaveRecord(\"WSAAsyncGetProtoByName\"); return WSAAsyncGetProtoByName1(hWnd, wMsg, name, buf, buflen); } HANDLE PASCAL FAR WSAAsyncGetProtoByNumber(HWND hWnd, u_int wMsg,int number, char FAR * buf,int buflen) { SaveRecord(\"WSAAsyncGetProtoByNumber\"); return WSAAsyncGetProtoByNumber1( hWnd, wMsg, number, buf, buflen); } HANDLE PASCAL FAR WSAAsyncGetHostByAddr(HWND hWnd, u_int wMsg,const char FAR * addr, int len, int type,char FAR * buf, int buflen) { SaveRecord(\"WSAAsyncGetHostByAddr\"); return WSAAsyncGetHostByAddr1( hWnd, wMsg, addr, len, type, buf, buflen); } int PASCAL FAR WSACancelAsyncRequest(HANDLE hAsyncTaskHandle) { SaveRecord(\"WSACancelAsyncRequest\"); return WSACancelAsyncRequest1(hAsyncTaskHandle); } FARPROC PASCAL FAR WSASetBlockingHook(FARPROC lpBlockFunc) { SaveRecord(\"WSASetBlockingHook\"); return WSASetBlockingHook1(lpBlockFunc); } int PASCAL FAR WSAUnhookBlockingHook(void) { SaveRecord(\"WSAUnhookBlockingHook\"); return WSAUnhookBlockingHook1(); } void PASCAL FAR WSASetLastError(int iError) { char disp[64]; wsprintf(disp,\"WSASetLastError(%d)\",iError); SaveRecord(disp); WSASetLastError1(iError); } int PASCAL FAR WSACancelBlockingCall(void) { SaveRecord(\"WSACancelBlockingCall\"); return WSACancelBlockingCall1(); } BOOL PASCAL FAR WSAIsBlocking(void) { SaveRecord(\"WSAIsBlocking\"); return WSAIsBlocking1(); } int PASCAL FAR WSARecvEx (SOCKET s, char FAR * buf, int len, int FAR *flags) { int rc; char disp[512]; char tmp[400]; rc = WSARecvEx1 ( s, buf, len, flags); strncpy(tmp,buf,400); wsprintf(disp,\"WSARecvEx(len=%d,buf:%s)\",len,tmp); SaveRecord(disp); return rc; } BOOL PASCAL FAR TransmitFile (IN SOCKET hSocket,IN HANDLE hFile,IN DWORD nNumberOfBytesToWrite,IN DWORD nNumberOfBytesPerSend,IN LPOVERLAPPED lpOverlapped,IN void *lpTransmitBuffers,IN DWORD dwReserved) { SaveRecord(\"TransmitFile\"); return TransmitFile1 ( hSocket, hFile, nNumberOfBytesToWrite, nNumberOfBytesPerSend, lpOverlapped,lpTransmitBuffers, dwReserved); } int PASCAL FAR Arecv () { SaveRecord(\"Arecv\"); return Arecv1(); } int PASCAL FAR Asend () { SaveRecord(\"Asend\"); return Asend1 (); } int PASCAL FAR inet_network () { SaveRecord(\"inet_network\"); return inet_network1 (); } int PASCAL FAR getnetbyname () { SaveRecord(\"getnetbyname\"); return getnetbyname1 (); } int PASCAL FAR rcmd () { SaveRecord(\"rcmd \"); return rcmd1 (); } int PASCAL FAR rexec () { SaveRecord(\"rexec\"); return rexec1 (); } int PASCAL FAR rresvport () { SaveRecord(\"rresvport\"); return rresvport1 (); } int PASCAL FAR sethostname () { SaveRecord(\"sethostname\"); return sethostname1 (); } int PASCAL FAR dn_expand () { SaveRecord(\"dn_expand\"); return dn_expand1 (); } int PASCAL FAR s_perror () { SaveRecord(\"s_perror \"); return s_perror1 (); } int PASCAL FAR GetAddressByNameA () { SaveRecord(\" GetAddressByNameA \"); return GetAddressByNameA1 (); } int PASCAL FAR GetAddressByNameW () { SaveRecord(\"GetAddressByNameW\"); return GetAddressByNameW1 (); } int PASCAL FAR EnumProtocolsA () { SaveRecord(\"EnumProtocolsA \"); return EnumProtocolsA1 (); } int PASCAL FAR EnumProtocolsW () { SaveRecord(\"EnumProtocolsW\"); return EnumProtocolsW1 (); } int PASCAL FAR GetTypeByNameA () { SaveRecord(\"GetTypeByNameA\"); return GetTypeByNameA1 (); } int PASCAL FAR GetTypeByNameW () { SaveRecord(\"GetTypeByNameW \"); return GetTypeByNameW1(); } int PASCAL FAR GetNameByTypeA () {SaveRecord(\"GetNameByTypeA \"); return GetNameByTypeA1 (); } int PASCAL FAR GetNameByTypeW () { SaveRecord(\"GetNameByTypeW\"); return GetNameByTypeW1 (); } int PASCAL FAR SetServiceA () { SaveRecord(\"SetServiceA \"); return SetServiceA1 (); } int PASCAL FAR SetServiceW () { SaveRecord(\"SetServiceW\"); return SetServiceW1 (); } int PASCAL FAR GetServiceA () { SaveRecord(\"GetServiceA\"); return GetServiceA1 (); } int PASCAL FAR GetServiceW () { SaveRecord(\"GetServiceW \"); return GetServiceW1 (); } //BOOL PASCAL FAR AcceptEx (IN SOCKET sListenSocket,IN SOCKET sAcceptSocket,IN PVOID lpOutputBuffer,IN DWORD dwReceiveDataLength,IN DWORD dwLocalAddressLength,IN DWORD dwRemoteAddressLength,OUT LPDWORD lpdwBytesReceived,IN LPOVERLAPPED lpOverlapped){SaveRecord(\"1\");return 0;} //VOID PASCAL FAR GetAcceptExSockaddrs (IN PVOID lpOutputBuffer,IN DWORD dwReceiveDataLength,IN DWORD dwLocalAddressLength,IN DWORD dwRemoteAddressLength,OUT struct sockaddr **LocalSockaddr,OUT LPINT LocalSockaddrLength,OUT struct sockaddr **RemoteSockaddr,OUT LPINT RemoteSockaddrLength){SaveRecord(\"1\");return 0;} --------------------------------------------------------- 实现代码! 简单吧? |
|
|
5楼#
发布于:2002-05-09 11:03
2000下的安装用netcfg是可以,只是会弹出数据签名窗口,
但nt下是没有办法自动安装的,只能手动,也去问过ms\'s guys,他们也不知道,所以我才想到hook技术! 我只知道hook技术有两种方法,一种是注册假protocol,一种是修改ndis.sys的export table. top你对这两种方法熟悉吗?讲讲如何? |
|
6楼#
发布于:2002-05-09 11:03
这个代码还是有些不足的地方不太稳定!声明:这个代码不是我写的!
|
|
|
7楼#
发布于:2002-05-09 11:08
代码是国外的一个高手写后经过国内的某个家伙改写的!
其实就是替换wsock32.dll 来监测winsock调用.先复制到这个位置 windows\\system\\wsock32.dll,并先把原来的改名比如MySockXX.XX,然后把wsock32.dll复制过去。 注意的是名字不能错!一定要和原来的文件同名! |
|
|
8楼#
发布于:2002-05-09 11:13
如果你看了关于安装的INF后就明白了!其实我只想给一个简单的提示!最早的时候初学者是不写INF的,只写一个REG文件来实现安装!剩下该做什么?就是分析INF如果自己写个安装!NT下没有了SETUP API[我也不知道有没有,没具体做过!因为我的项目还没完成],可以用其他的服务来实现的!只要你看明白了NETCFG的代码后,就不会依赖它了!
|
|
|
9楼#
发布于:2002-05-09 11:17
好的,我在烟9烟9安装问题,呵呵!
|
|
10楼#
发布于:2002-05-09 12:37
我做过hook技术的,也刚刚完成!觉得hook就一点,搞清ndis的流程,然后就是对windows系统程序设计的问题了。
其实对NT防火墙来说好象不能用hook,因为ndis4。0以后的版本就提了分层结构,另外nt结构好象也不提供hook技术了。不知道我的理解对不对。记得胡斑竹曾教导过,在nt下hook技术很复杂,一般不用他来做防火墙,一般用IMD! 祝大家好运!! |
|
|
11楼#
发布于:2002-05-09 12:50
我记得那位大虾说过xp DDK,可以转换vxd 到wdm 找一xpddk来研究一下吧。也许很简单呢。
|
|
|
12楼#
发布于:2002-05-09 14:39
看到一篇文章上这样讲,哪位给详细的分析一下,谢谢!
在Windows NT/2000下面如何实现Hook呢?有两种不同的思路: 1) 通过修改NDIS.SYS的Export Table。在Windows NT/2000下,可执行文件(包括DLL以及SYS)都是遵从PE(Portable Executable)格式的。所有向其他操作系统组件提供接口的驱动程序都有Export Table,因此只要修改NDIS.SYS的Export Table就可以实现对关键NDIS API的挂接。由于协议驱动程序在系统启动的时候会调用NdisRegisterProtocol来向系统进行协议注册,因此这种方法关键在于修改NDIS.SYS所提供的NdisRegisterProtocol/NdisDeRegisterProtocol/NdisOpenAdapter/NdisCloseAdapter/NdisSend函数的起始地址。我们知道,在用户态模式要修改PE文件格式可以用一些API来实现,而NDIS.SYS位于系统的核心内存区,因此要修改NDIS.SYS就不得不通过写驱动程序来实现,也就要求我们对PE文件格式有比较深入的了解。使用这种方法还要注意驱动程序的加载次序,显然Hook Driver必须在NDIS.SYS被加载之后,而在协议驱动程序如tcpip.sys被加载之前。另外,Windows2000还提供了系统文件保护机制,因此在修改ndis.sys还需要通过修改注册表屏蔽系统文件保护机制。 2) 向系统注册假协议(fake protocol)。在Windows内核中,所有已注册的协议是通过一个单向的协议链表来维护的。这个单向链表保存了所有已注册协议的NDIS_PROTOCOL_BLOCK结构的地址,在这个结构中保存了协议驱动所指定的相应的派发函数的地址如RECEIVE_HANDLER等。并且,每个协议驱动还对应一个NDIS_OPEN_BLOCK的单向链表来维护其所绑定的网卡信息。当协议驱动调用NdisRegisterProtocol之后,NDIS总是会把新注册的协议放在协议链表的表头并返回这张表,所以只要我们注册一个新的协议通过新协议注册返回的链表头就可以轻而易举的遍历系统中所有协议表。但是,如果要成功地挂接派发函数,还需要对协议所对应的NDIS_OPEN_BLOCK结构里的派发函数进行挂接,因为NDIS并不是直接调用协议驱动在NDIS_PROTOCOL_CHARACTERISTICS所注册的派发函数地址,而是调用NDIS_OPEN_BLOCK里的派发函数。值得注意的是,在Windows9x/Me/NT的DDK中,NDIS_PROTOCOL_BLOCK的定义是很明确的,而在Windows 2000/xp的DDK中,并没有该结构的详细定义,也就是说该结构在Windows2000/xp下是非公开的,因此开发人员需要利用各种调试工具来发掘该结构的详细定义。也正是因为如此,这种方法对平台的依赖性比较大,需要在程序中判断不同的操作系统版本而使用不同的结构定义。 |
|
13楼#
发布于:2002-05-09 18:24
你说的第一种情况我见过别人详细讲解过。
至于第一种情况恐怕挺难的,说起来简单,做起来应该挺复杂,记得有人问过如何修改Ndis.sys的输出表,当时觉得他们说的好复杂,就没有仔细看了! |
|
|
14楼#
发布于:2002-05-09 19:48
看到一篇文章上这样讲,哪位给详细的分析一下,谢谢! 1.第一种有人做出来么?我看见pcausa上有一个PIM好像是基于这种思路的,但好像是在98下的(98下不是只需要Hook_Device就可以了么?) 2.第二种有个问题:假设注册的假协议装上之后,又有其他协议装上,怎么去挂钩后来安装的协议呢?(这种方法好像就是很久前那篇“网络数据包的通用拦截技术”所说的方法吧?) |
|
15楼#
发布于:2002-05-09 20:22
2000下的安装用netcfg是可以,只是会弹出数据签名窗口, nt下也能自动安装。 你问错了人。 |
|
|
16楼#
发布于:2002-05-09 20:50
哎~~又被批评了!555555~~~看来当不成妈妈的好孩子了!不过NT下的安装我的确没搞过!2000下我还是敢确定方法是正确的!
|
|
|
17楼#
发布于:2002-05-09 22:00
我想大家不要只说能或者不能,好或者不好,
如果哪位高人知道具体的方法,能否贴出来,我只知道方向,但不知道方法和实现细节! 还有胡大侠能否把在nt下自动安装的方法或者方向贴出来,让我等了解了解,长长见识,呵呵! |
|
18楼#
发布于:2002-05-10 13:34
刚看到一篇关于2K下HOOK的文章!
Part III. NDIS Hooking Filter Driver in Windows NT/2000. For the best understanding of the technology stated in the given part acquaintance to a nucleus of operating systems of Windows NT/2000 is recommended. Acquaintance to writing kernel-mode drivers and the PE-format is desirable. How to start... Certainly from creation of the elementary driver. If for a Windows 9x/ME I have mentioned VToolsD for the given driver, for example, it is possible to use DriverWorks though certainly nothing prevents to write it, using DDK only and the compiler of the command line. I\'ve already mentioned, that for drivers of the given type the order of loading is important, the main requirement to our driver to boot after NDIS, but before TCPIP (and accordingly other protocols which we want to filter). As far as Windows 2000 and NT has a little different order of loading for the network subsystem, I shall not result concrete guidelines. (LoadOrder from www.osr.com utility displays the order of loading of drivers in convenient sort can help here. How to hook … Implementations NDIS are various in a Windows 9x/ME and NT/2000, now it will be enough to hook only 4 functions: - NdisRegisterProtocol - NdisDeregisterProtocol - NdisOpenAdapter - NdisCloseAdapter Hooking NdisSend has no sense any more, if you take a look in ndis.h you will see, that in our case this function is defined as macro. However these four functions need to be intercepted somehow. Right at the beginning of this part I already marked, that it is desirable to familiarize with the PE-format, this knowledge is necessary for interception. The essence of the technology is reduced to that it is necessary to find ndis.sys header image in the memory and to patch the export table of it, changing addresses for four functions above. All necessary structures for operation with PE-image are in the winnt.h file from DDK. In Windows NT 4.0 this technology will work fine, however, having started this driver under Windows 2000 or XP (and if large 4MB pages are not used, if used WP protection disabled), you will see only \" the dark blue screen of death \". The problem is that Windows 2000 protects a kernel image from possible modification. To resolve this problem there are two possible ways: 1) Disable protection of a kernel image through the registry. For this purpose it is necessary to create in a HKLM\\SYSTEM\\CurrentControlSet\\Control\\S essionManager\\Memory Management key REG_DWORD parameter with name EnforceWriteProtection and value 0. 2) Reset Write Protection bits in register CR0, before updating the export table. It can be done, for example as follows: mov ebx, cr0; to receive current state Cr0push ebx; to save it(him) and ebx, ~0x10000; to reset WP bats mov cr0, ebx; to switch off write protection ; Here we modify the table of export.... pop ebx; mov cr0, ebx; to restore the previous processor state I do not bring here the code for modification of the export table mainly, because it is not a unique way to intercept NDIS function. Daniel Lanciany (www.danlan.com) in his variant of NDIS-hooking driver has gone in other way, he has updated the beginning of functions, having inserted in them transitions to his code. In his handler he restores a body of the intercepted function, makes necessary operations on processing call, calles the restored function, and after return from it again modifies the beginning. As far as calls to this four functions set are not so often, this way is nothing worse than editing of the export table. However, should mention, that as well as a similar method of hooking DLL functions in User-mode it may appear unsafe on SMP platforms. What else it is necessary to do … I shall not stop in detail on new handler NdisRegisterProtocol, as it should make practically the same as in a Windows 9x/ME i.e. to expose the handler of entering traffic (actually it is necessary to change not only ReceiveHandler, but also in particular TransferDataCompleteHandler). The only thing I should mention here is that if 9x/ME TCP/IP driver (\"MSTCP\") registers one protocol and this protocol directly opens both Ethernet adapters and PPPMAC (emulation Ethernet above dial-up) then in NT/2000/XP TCP/IP actually consists of two drivers TCPIP.SYS (\"TCPIP\") and WANARP.SYS (\"TCPIP_WANARP\" in 2000/XP, \"RASARP\" in NT 4.0) and this second protocol opens emulation \\DEVICE\\NDISWANIP (emulating Ethernet upper interface of intermediate NDISWAN driver). The further operation in many respects is similar to writing of the driver of the network protocol, therefore I would advise to familiarize with appropriate section NT DDK (Network Drivers). The only complex enough moment is about new handler for NdisOpenAdapter. One of returned parameters of this function (NdisBindingHandle) actually is a pointer to NDIS_OPEN_BLOCKstructure . This structure is defined in ndis.h file, but, unfortunately, is not documented. This is important for us because it gives access to outgoing from the protocol traffic (fields SendHandler, SendPacketsHandler, and TransferDataHandler). Obviously, now it is necessary to transfer to the protocol our variant NDIS_OPEN_BLOCK, having saved the original. The following code is taken from new NdisOpenAdapter handler: ... // Save ProtocolBindingContext pAdapter - > m_ProtocolBindingContext = ProtocolBindingContext; // Allocate and initialize adapter namestatus = NdisAllocateMemory ( *pAdapter-> m_AdapterName. Buffer, AdapterName-> MaximumLength, 0, noMaxAddr ); if (status == NDIS_STATUS_SUCCESS){ NdisMoveMemory ( pAdapter-> m_AdapterName. Buffer, AdapterName-> Buffer, AdapterName-> MaximumLength ); pAdapter-> m_AdapterName. Length = AdapterName-> Length;pAdapter-> m_AdapterName. MaximumLength = AdapterName-> MaximumLength; } else { pAdapter-> m_AdapterName. Buffer = NULL; pAdapter-> m_AdapterName. Length = 0; pAdapter-> m_AdapterName. MaximumLength = 0; } // Call old NdisOpenAdapter handlerOF_NdisOpenAdapter ( Status, OpenErrorStatus, NdisBindingHandle, SelectedMediumIndex, MediumArray, MediumArraySize, NdisProtocolHandle, ProtocolBindingContext, AdapterName, OpenOptions, AddressingInformation ); if (((*Status == NDIS_STATUS_SUCCESS) || (*Status == NDIS_STATUS_PENDING))){ // Save old binding handle and adapter selected medium pAdapter - > m_NdisBindingHandle = *NdisBindingHandle; pAdapter - > m_Medium = MediumArray [*SelectedMediumIndex]; // we does not support adapters except ethernet and \\DEVICE\\NDISWANIP if (! ((pAdapter - > m_Medium == NdisMediumDix) || (pAdapter - > m_Medium == NdisMedium802_3) || (pAdapter - > m_Medium == NdisMediumWan))) { // Release already allocated resources AF_FreeAdapterEntry (pAdapter); NdisReleaseSpinLock (*g_OpenAdapterLock); return; } // Copy Real Open Block to our locationNdisMoveMemory ( *pAdapter - > m_OpenBlock, *NdisBindingHandle, sizeof (NDIS_OPEN_BLOCK) ); // Substitute Real Open Block by our Open Block*NdisBindingHandle = *pAdapter - > m_OpenBlock; if (*Status == NDIS_STATUS_SUCCESS) // Handlers already initialized{ // Pointer to our OPEN_BLOCK (for convnience) pOpenBlock = (PNDIS_OPEN_BLOCK) *NdisBindingHandle; pAdapter - > m_MacBindingHandle = pOpenBlock - > MacBindingHandle; // Substitute Some Real handlers by our versionpAdapter - > m_SendHandler = pOpenBlock - > SendHandler; pOpenBlock - > SendHandler = OBF_SendHandler; pAdapter - > m_SendPacketsHandler = pOpenBlock - > SendPacketsHandler;pOpenBlock - > SendPacketsHandler = OBF_SendPacketsHandler; pAdapter - > m_RequestHandler = pOpenBlock - > RequestHandler;pOpenBlock - > RequestHandler = OBF_RequestHandler; pAdapter - > m_TransferDataHandler = pOpenBlock - > TransferDataHandler; ... } What we have … Thus, the driver with minimum functionality turns out small enough and not complex in implementation. Installation of it does not make problem as well as in a case with the driver for a Windows 9x/ME and require adding of several keys in the registry. Besides the described static way of hooking NDIS library functions which demands loading the driver at a stage of start of the operating system and as such this driver can not be unloaded from memory, there is one more dynamic approach. This method works both under a Windows 9x/ME and under NT/2k/XP and though in the first case it is necessary to write VxD, and in the second kernel-mode the driver, a principle is identical. Among products existing in the market it is applied (besides control TDI and all started processes in the system) in rather known firewall ZoneAlarm (with widely recognized TrueVector technology). The essence of the approach that we register the dummy protocol (call NdisRegisterProtocol) i.e. which handlers do nothing, most complex of them can be ProtocolReceive, which returnes NDIS_STATUS_NOT_ACCEPTED. This protocol is one simple purpose to receive NdisProtocolHandle. Actually, it is the pointer to internal NDIS structure NDIS_PROTOCOL_BLOCK which, unfortunately, differs from one NDIS version to another and not always defined in ndis.h. And so in addition, this structure comprises NDIS_PROTOCOL_CHARACTERISTICS with addresses of all ProtocolXXX functions, NDIS_OPEN_BLOCK list (this structure in turn contains handlers Send/SendPackets/Request) all network interfaces bound to the given protocol and the pointer to next structure NDIS_PROTOCOL_BLOCK. The further is practically obvious, moving the list of registered protocols, we substitute the handlers where it is necessary. However, despite of seemless simplicity, this method is not simple and also demands the big care as we interfere with functionality of already working system. The conclusion: So, we have superficially considered the majority of approaches to firewall creation for the Windows platform, and the variant with interception NDIS was reviewed, as it seems to me, rather in details. As far as this is the only method which guarantees a complete control over network traffic, watching all registering protocols it seems to be the best way for network security relative projects. I did not try to teach you to write drivers in this small article, nonspecialists can address to DDK and learn about features of the Windows network subsystem . I can\'t say that this is easy to read material, but authors of books for some reason usually practically do not give NDIS attention, so this about the only source of information. From on-line resources, I think, it has some reasonable sense to look at www.pcausa.com., an example you can order NDISPIM samples in source built using the reviewed approach at http://www.pcausa.com/ndispim (common packet filtering framework for all Windows OS\'s from Win95Gold till WinXP). |
|
|
19楼#
发布于:2002-05-10 14:22
怎样看ndis.sys的export table,什么是pe-format?
哪位知道,帮忙讲解一下吧! 用softice敲exp列出的是export table吗? |
|
上一页
下一页