daviswjk
驱动牛犊
驱动牛犊
  • 注册日期2003-03-26
  • 最后登录2009-06-12
  • 粉丝0
  • 关注0
  • 积分334分
  • 威望64点
  • 贡献值0点
  • 好评度33点
  • 原创分0分
  • 专家分0分
阅读:3110回复:10

网络底层驱动开发(防火墙等)技术小文章

楼主#
更多 发布于:2003-03-27 02:09
我觉得挺好,推荐给我这样的初学者
觉得好的给点分吧?? :) ,谢谢

http://hantech.cheju.ac.kr/company/tech/technical.htm

http://www.zjinfosec.net/anquan_1.php?474

http://www.ntndis.com/articles/firewall.htm

最新喜欢:

cyliucyliu baoyibao99baoyib...
一切随风!
SharpShooter
驱动小牛
驱动小牛
  • 注册日期2002-04-07
  • 最后登录2013-07-05
  • 粉丝0
  • 关注0
  • 积分5分
  • 威望40点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
沙发#
发布于:2003-03-27 15:38
发帖子要分的还是第一次见,就不知道别人怎么给你分?
写驱动不如买足彩!!
Unique
驱动牛犊
驱动牛犊
  • 注册日期2003-04-16
  • 最后登录2003-05-21
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
板凳#
发布于:2003-04-17 11:40
一个简体中文,
一个韩文,
一个乱码。
看来只能给你加3.3分。
bxiao
驱动牛犊
驱动牛犊
  • 注册日期2003-04-10
  • 最后登录2003-07-31
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
地板#
发布于:2003-04-17 17:43
一个简体中文,
一个韩文,
一个乱码。
看来只能给你加3.3分。


一篇中文的看过了
乱码可能是我的ie编码没有装全
呵呵……

别人怎么给分呀?
我是菜鸟
chacker
驱动小牛
驱动小牛
  • 注册日期2002-11-22
  • 最后登录2007-11-15
  • 粉丝0
  • 关注0
  • 积分193分
  • 威望20点
  • 贡献值0点
  • 好评度17点
  • 原创分0分
  • 专家分0分
地下室#
发布于:2003-04-17 20:21
只有一个能看,叫我怎么给分你?虽然我的分多得是!
zydcat
驱动老牛
驱动老牛
  • 注册日期2001-12-06
  • 最后登录2006-04-12
  • 粉丝0
  • 关注0
  • 积分9分
  • 威望2点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
5楼#
发布于:2003-04-17 20:35
贴出来啊
连不上,需要代理 :mad:
[color=red]肥虫虫[/color] [img]http://www.driverdevelop.com/forum/upload/bradley/2002-11-15_ig01.gif[/img]
daviswjk
驱动牛犊
驱动牛犊
  • 注册日期2003-03-26
  • 最后登录2009-06-12
  • 粉丝0
  • 关注0
  • 积分334分
  • 威望64点
  • 贡献值0点
  • 好评度33点
  • 原创分0分
  • 专家分0分
6楼#
发布于:2003-04-19 18:36
第三篇:
Firewall for Windows 9x/ME/NT/2000/XP  
 


Copyright(c) Vadim V.Smirnov 2000-2003
Switch to Russian Language


--------------------------------------------------------------------------------

Introduction:
I suppose any experienced Internet user knows what is firewall and when it is required. Those of you who interest in exact definition of this term I address to well-known on-line technical terms encyclopedia on www.whatis.com . If you are not lazy to do this you will even find two relative definitions (firewall and personal firewall). I’m not going to provide here exact classification and just enumerate some typical representatives. As far as this article is Windows systems relative the following does not pretend to cover all. Among server-oriented products I could mention WinGate, WinRoute, Vicomsoft Internet Gateway, WinProxy and etc… All these products differ in their functionality and price, and in addition to internal network intrusion protection usually realize single Internet connection sharing. From personal firewall group I can mention AtGuard, Outpost Firewall, ZoneAlarm, Tiny Personal Firewall, Sygate Personal Firewall and etc. I’m not going to discuss these solutions here; end users are responsible for this. We will concentrate on the technical part of question, in particular how to organize traffic filtering in operating systems from Windows family. I should mention, that I’m not going to describe each approach in detail; this would take pretty much amount of time. I’ll try to point different approaches advantages and disadvantages and additional information sources. Only one variant, so-called NDIS-hooking approach will be reviewed in detail. At this time its realized at least by one third-party company www.pcausa.com, which offers some source code resources for developers. Please, note that if Part I of this paper is suitable for the majority of Windows developers then Part II and Part III require deep knowledge of Windows internals and strong driver development skills. For those people who would like to experiment with network packet filtering or need to develop custom solution (network security, internet connection sharing, VPN and etc.) and have no desire or no opportunity to learn driver development we offer WinpkFilter? development framework. Those of readers who interested in development of pure kernel-mode solution also can use WinpkFilter? framework (pure IOCTL interface is well documented) or alternatively can order PCAUSA NDIS-hooking samples. The Part II and Part III of this paper covers the approach to cross-platform NDIS-hooking driver development, but the great amount of details is not mentioned here. The raw time esteem for the development stable set of drivers is 6-12(or even more) months depending of your experience, so think twice before starting your project from scratch.

Part I. Network traffic filtering technologies for Windows.
In spite of the fact that Windows 9x/ME and Windows NT/XP provides similar socket interface and NDIS architecture even allows binary compatible miniport drivers for network interfaces their network subsystem internals differ a lot. Regretfully, the size of this article does not allow us to review each of them in details, some interesting NT relative information can be found in chapter13 “Inside Microsoft Windows 2000 Third Edition” (David A. Solomon, Mark E. Russinovich MS Press 2000). As for Windows 9x/ME I can hardly recommend something. Actually, NT/2000/XP network subsystem is more complicated then 9x/ME, but we can subdivide both on some common parts:

NDIS. In 1989 Microsoft and 3Com jointly developed Network Driver Interface Specification (NDIS), which allows network protocol drivers use of network interface services hiding details of their realization. Network interface driver developed in conformance with this specification is commonly called NDIS-miniport. One of the Microsoft goals was to make network hardware vendors life easier, once developed NDIS-miniport is portable between Windows versions. Details subject description can be found in DDK documentation (Network Drivers section), in two words NDIS describes rules (types and interfaces) to follow in network driver development and provides functions library to call instead kernel-exported services.
Network Protocol Drivers. Detailed description of this driver class is out of this article subject, however for better understanding of network filtering technologies I would advise to look into DDK documentation (Network Drivers section). In two words, network protocol driver (like TCPIP an example) on it’s lower edge uses NDIS library function for network access and may provide Transport Data Interface (TDI) on the upper edge. Exported TDI interface can be used by various TDI-clients, like an example part of socket implementation afd.sys (NT/2000/XP). The usage of TDI has much common with socket interface, an example the next sequence of requests establishes connection to remote system (NT specific):
1. Client allocates and initializes address open TDI IRP. On this request TDI returns file object known as address object and representing network address. This step is equivalent to bind call from Windows Sockets interface.
2. Client allocates and initializes connection open TDI IRP, for what TDI return file object known as connection object and representing connection. This step is equivalent to socket function call from Windows Sockets interface.
3. Client associates connection object with address object, through associate address TDI IRP.
4. TDI client who wishes to accept connection issue listen TDI IRP, specifying number of connections for this connection object, and then sending accept TDI IRP for each remote client connection. This step is equal to listen and accept functions from Windows Sockets. TDI client who wishes to establish connection to remote system allocates connect TDI IRP, specifying connection object. This IRP complete when connection will be established (or error occur). This step is equivalent to connect function from Windows Sockets.
User-Mode DLLs that forms Windows Sockets interface. These are well-known ws2_32.dll, msafd.dll, wshtcpip.dll and etc.
Let us review possible ways for network traffic filtering. May be this will be new for some readers but about whole traffic can be filtered from User-mode, with no need in writing any drivers. No doubt, these methods has many limitations, an example does not provide any real network protection (Trojan application can skip Windows Sockets interface and use TDI directly), however can be used for such purposes like QOS(Quality Of Service).

User-mode traffic filtering.

1) Winsock Layered Service Provider (LSP). This approach is well documented in MSDN and has a good example (SPI.CPP). As method advantage I would mention the possibility to determine process that called Windows Sockets. This can be used for such tasks like QOS (Quality Of Service), encryption of data streams and etc. However, don’t forget that TCPIP can be called directly via TDI; therefore this method is in no use for Trojan/virus protection and etc. Additionally, this approach can’t be used on router, because packets are routed on the TCPIP level (or even on MAC level, for details search in DDK for FFP).
2) Windows 2000 Packet Filtering Interface. Windows 2000 provides API using which user-mode application can install a set of “filter descriptors”, which will be used by TCPIP for packet filtering (PASS/DROP). However, rules for filtering are rather limited (pass/drop based on IP address and port information), and this approach can be used only starting from Windows 2000 and higher, what is rather serious limitation.
3) Substitution of Winsock DLL. This approach mentioned only for security reasons. I would not recommend it using nowadays because of well-known reasons.
4) Global hook of all “dangerous” functions (starting from Windows sockets, DeviceIoControl and etc). If you ask me if this can be done I answer yes, but this approach is rather difficult to realize and developer must be very careful, because it have possible impact on overall system stability and security.
Kernel-mode traffic filtering:

1) Kernel-mode sockets filter. This technology is applicable for Windows NT/2000. It is based on interception of all calls from msafd.dll (the lowest level user-mode Windows Sockets DLL) to the kernel-mode module afd.sys (the TDI-client, kernel-mode a part of Windows Sockets). This method is interesting, but its possibilities are no much wider, than LSP\'s. In addition I would like to add that AFD interface is extended from version to version of Windows NT family what limits it portability.
2) TDI-filter driver. This technology applied for both Windows 9x/ME and Windows NT/2000 though concrete implementations strongly differ. The example of the code for a Windows 9x can be found in the examples to Vireo/Numega VtoolsD, therefore I will not observe it here. As for Windows NT/2000, in case of TCP/IP filtering it is necessary to intercept (using IoAttachDevice or patching dispatch table in driver object) all calls, directed to devices created by tcpip.sys driver (\\Device\\RawIp, \\Device\\Udp, \\Device\\Tcp, \\Device\\Ip, \\Device\\MULTICAST). I would recommend you to make simple experiment, download and install Device Filter utility from this site. Then attach to devices created by TCPIP and try any network activite (even \"ping 127.0.0.1\" is OK). Utility will show you all requests to the transport. This technology is well known and also it\'s used in a number of commercial products (for example, Outpost Firewall). However, as well as methods above, this approach can be used only for creation of personal firewall class products, and it can\'t protect you TCPIP stack from hackers attacks.
3) NDIS Intermediate Driver. Microsoft has provided this class of drivers just for needs similar to ours, however implementation of this drivers for Windows 98/ME/NT leaves to wish the best, and in a Windows 95 is absent at all. In particular they are very inconvenient in installation and for end user. Actually, support of IM drivers was improved in Windows 2000/XP, but there is another problem, you will have to digitally sign your driver at Microsoft, elsewhere user will have a horrible nag-message. Interested persons can look at NDIS IM FAQ, and documentation in DDK. I shall not examine this variant in detail here, instead of it we shall consider worthy alternative.
4) Windows 2000 Filter-Hook Driver. The method is described in DDK documentation and applicable only in Windows 2000 and higher, therefore I not shall stop on this variant.
5) NDIS Hooking Filter Driver. This approach we will review in more detail here. Briefly the technique based on interception of some subset of NDIS functions which in the further allow to trace registration of all protocols installed in the operating system and opening of network interfaces by them. Among advantages of the given approach it is necessary to mention ease of installation and transparent support of Dial-Up interfaces what require additional work in case of IM drivers.
Part II. NDIS Hooking Filter Driver in a Windows 9x/ME.

Before continue reading I recommend you to open MSDN and read documentation for the following NDIS functions:

- NdisRegisterProtocol
- NdisDeregisterProtocol
- NdisOpenAdapter
- NdisCloseAdapter
- NdisSend
As acquaintance to writing drivers of virtual devices (VxD) for the platform of a Windows 9x/ME is desirable. In the further examples of the code we will use functions and data structures defined in Vireo/Numega VToolsD. Certainly, all code can be modified for compilation with DDK, however VtoolsD allows writing much more compact code and hides VxD implementation details.


The beginning of the beginnings …

As it was already mentioned above, in the Windows 9x/ME NDIS library is realized as the virtual device driver ndis.vxd. As far as we need to intercept part of NDIS functions, we should write our own virtual device driver (VxD). I am not going to teach you here to write virtual device drivers, therefore for understanding underwritten I recommend you to familiarize with a subject. In the further it is supposed, that the reader has some knowledge Windows 9x/ME internals and can create VxD, even with the help of such tools as Numega VtoolsD.

If you have followed to my advice and have viewed descriptions of five mentioned above NDIS functions, it must be clear for you, that interception of five listed functions should be made before initialization of protocols (calling NdisRegisterProtocol by them). For an examined example as the order of initialization was selected VNETBIOS_Init_Order. I leave other parameters of the VxD on your discretion as they entirely depend on that functionality what you want to receive.

Hooking of VxD services …

The technique of hooking VxD services is well documented; therefore I shall not waste time on retelling already written. I\'ll bring a short code snippet instead. I do not bring the code for each concrete function, that is done below for NdisRegisterProtocol, it is necessary to do and for four other functions.

...
   // Function Prototype For Hooking NdisRegisterProtocol
   typedef VOID NDIS_API OS_NDIS_REGISTER_PROTOCOL (
   PNDIS_STATUS Status,
   PNDIS_HANDLE NdisProtocolHandle,
   PNDIS_PROTOCOL_CHARACTERISTICS ProtocolCharacteristics,
   UINT CharacteristicsLength
   );
  
   typedef OS_NDIS_REGISTER_PROTOCOL *POS_NDIS_REGISTER_PROTOCOL;...
   // Thunks for NDIS services hooking
   HDSC_Thunk thunkNdisRegisterProtocolHook;
   ...
   // Old handlers
   POS_NDIS_REGISTER_PROTOCOL OldNdisRegisterProtocol = NULL;
   ...
   // New NdisRegisterProtocol handler
   VOID NDIS_API NH_NdisRegisterProtocol (
PNDIS_STATUS Status,
PNDIS_HANDLE NdisProtocolHandle,
PNDIS_PROTOCOL_CHARACTERISTICS ProtocolCharacteristics,
UINT CharacteristicsLength
)
   {
   ...
   }
   ...
   // Hooking VxD services of NDIS.VXD
   NDIS_STATUS HookNdisVxdServices ()
   {
   OldNdisRegisterProtocol =
  (POS_NDIS_REGISTER_PROTOCOL) Hook_Device_Service_C (
GetVxDServiceOrdinal (NdisRegisterProtocol),
NH_NdisRegisterProtocol,
*thunkNdisRegisterProtocolHook
);

   if (! OldNdisRegisterProtocol)
   return NDIS_STATUS_FAILURE;
   ...
  
   return NDIS_STATUS_SUCCESS;
}
HookNdisVxdServices function should be called in the initialization handler of for the virtual device.

What is next?

Before answering this question, let\'s take a look, what we already have. Actually we already can view all outgoing network traffic. We are not limited only to view, but also to modify, or, for example, to transfer packets to the application working in Ring3. Anyway, we have all necessary to move further. There is a question on how to get access to the incoming traffic. Actually it not as difficult as it seems, for this purpose we have intercepted NdisRegisterProtocol. As one of arguments of this function the protocol transfers the pointer to structure NDIS_PROTOCOL_CHARACTERISTICS. This structure in details is described in documentation DDK. In new handler NdisRegisterProtocol we can modify this structure, in particular we are interested with ReceiveHandler field, this function called in reply to call by the driver of the network interface of NdisIndicateReceive function. How to process this call and to receive whole packet (the network adapter can transfer only a part of the package) documented in DDK, and I shall omit these details. Thus, actually we can process not only outgoing, but also incoming traffic. For what we intercepted three more functions? I believe, any well-designed firewall should watch the protocols, which have registered in the system, and the network adapters open them, namely the staying functions allow us to watch it.

Windows ME …

Let\'s put, you followed the above-stated guidelines and as a result of persistent work have created the network-filtering driver. Unfortunately, this driver will work normally only under Windows 95/98. If you install your VxD on Windows ME (I\'m not going to review variants of VxD installation here, the most universal for the given class of drivers is installation through the registry) your driver will not intercept any registered protocol. The problem occurs because, TCP/IP protocol has moved from the virtual device driver (VxD) into tcpip.sys that does not know anything about VxD services. To support new implementation of the TCP/IP stack ndis.vxd exports library functions not only as VxD-services (as it did before for NDIS-miniports support, which are binary compatible with Windows NT (if built with this option) though for protocols it was not used). It is done using well-known PELDR_AddExportTable function (service of vxdldr.vxd). The problem can be resolved by simple hooking of this service, in the new handler we should check, that these are NDIS exports and change five pointers in the table (for previously mentioned functions). I shall not stop on concrete implementation, as it does not represent anything complex. Another moment with NdisRegisterProtocol function, more exactly with structure NDIS_PROTOCOL_CHARACTERISTICS is much more interesting. This structure differently defined in a Windows 9x and Windows NT DDK. You can find exact definitions in the proprietary DDK\'s header file ndis.h, The most important moment here is that tcpip.sys calls NdisRegisterProtocol, transferring it NDIS_PROTOCOL_CHARACTERISTICS as it is defined in NT DDK, therefore ndis.vxd does not export the same function as VxD-service and through the PELDR-interface. The function exported through the PELDR-interface should convert NDIS_PROTOCOL_CHARACTERISTICS from the format accepted in NT in the format understandable to VxD-service, then call the last. And it is necessary to mark, that in Windows ME VxD-service NdisRegisterProtocol has another structure as a parameter then one defined in a Windows 9x DDK structure, its extended and not documented variant (which allows tcpip.sys to use NDIS version up to 5.0 though in practice it uses version 4.0).

Definition of this structure should look approximately so:

typedef
struct _ME_NDIS_PROTOCOL_CHARACTERISTICS
{
   UCHAR MajorNdisVersion;
   UCHAR MinorNdisVersion;
   ULONG Reserved;
   OPEN_ADAPTER_COMPLETE_HANDLER OpenAdapterCompleteHandler;
   CLOSE_ADAPTER_COMPLETE_HANDLER CloseAdapterCompleteHandler;
   SEND_COMPLETE_HANDLER SendCompleteHandler;
   TRANSFER_DATA_COMPLETE_HANDLER TransferDataCompleteHandler;
   RESET_COMPLETE_HANDLER ResetCompleteHandler;
   REQUEST_COMPLETE_HANDLER RequestCompleteHandler;
   RECEIVE_HANDLER ReceiveHandler;
   RECEIVE_COMPLETE_HANDLER ReceiveCompleteHandler;
   STATUS_HANDLER StatusHandler;
   STATUS_COMPLETE_HANDLER StatusCompleteHandler;
   BIND_ADAPTER_HANDLER BindAdapterHandler;
   UNBIND_ADAPTER_HANDLER UnbindAdapterHandler;
   UNLOAD_PROTOCOL_HANDLER UnloadProtocolHandler;
   NDIS_STRING Name;
   RECEIVE_PACKET_HANDLER ReceivePacketHandler;
   PNP_EVENT_HANDLER PnPEventHandler;
   PVOID ReservedHandlers [4];
   PVOID CoSendCompleteHandler;
   PVOID CoStatusHandler;
   PVOID CoReceivePacketHandler;
   PVOID CoAfRegisterNotifyHandler;
} ME_NDIS_PROTOCOL_CHARACTERISTICS;
And pseudocode NdisRegisterProtocol exported through PELDR-tools looks approximately so:

 // New entry for export from NDIS.VXD exported through PELDR_AddExportTable
VOID NDIS_API
   WDM_NdisRegisterProtocol (
   OUT PNDIS_STATUS Status,
   OUT PNDIS_HANDLE NdisProtocolHandle,
   IN PNDIS50_PROTOCOL_CHARACTERISTICS ProtocolCharacteristics,
   IN UINT CharacteristicsLength
   )
{
   unsigned short* pUnicode = NULL;
   unsigned char* pAnsi = NULL;
   unsigned int Counter = 0;
   unsigned char* pProto = NULL;
  
   ME_NDIS_PROTOCOL_CHARACTERISTICS MilleniumCharacteristics;
   NdisZeroMemory (
*MilleniumCharacteristics,  
sizeof (MilleniumCharacteristics)
);
  
   MilleniumCharacteristics.MajorNdisVersion =
    ProtocolCharacteristics->MajorNdisVersion;
   MilleniumCharacteristics.MinorNdisVersion  =
    ProtocolCharacteristics->MinorNdisVersion;
   MilleniumCharacteristics.Reserved =
    ProtocolCharacteristics->Reserved;
  
   MilleniumCharacteristics.OpenAdapterCompleteHandler =
    ProtocolCharacteristics->OpenAdapterCompleteHandler;
   MilleniumCharacteristics.CloseAdapterCompleteHandler =
    ProtocolCharacteristics->CloseAdapterCompleteHandler;
   MilleniumCharacteristics.SendCompleteHandler =
    ProtocolCharacteristics->SendCompleteHandler;
   MilleniumCharacteristics.TransferDataCompleteHandler =
    ProtocolCharacteristics->TransferDataCompleteHandler;
   MilleniumCharacteristics.ResetCompleteHandler =
    ProtocolCharacteristics->ResetCompleteHandler;
   MilleniumCharacteristics.RequestCompleteHandler =
    ProtocolCharacteristics->RequestCompleteHandler;
   MilleniumCharacteristics.ReceiveHandler =
    ProtocolCharacteristics->ReceiveHandler;
   MilleniumCharacteristics.ReceiveCompleteHandler =
    ProtocolCharacteristics->ReceiveCompleteHandler;
   MilleniumCharacteristics.StatusHandler =
    ProtocolCharacteristics->StatusHandler;
   MilleniumCharacteristics.StatusCompleteHandler =
    ProtocolCharacteristics->StatusCompleteHandler;
  
   if (ProtocolCharacteristics->Ndis40Chars.Ndis30Chars.MajorNdisVersion > 3)
   {
   MilleniumCharacteristics.BindAdapterHandler =
ProtocolCharacteristics->BindAdapterHandler;
MilleniumCharacteristics.UnbindAdapterHandler =
ProtocolCharacteristics->UnbindAdapterHandler;
   MilleniumCharacteristics.UnloadProtocolHandler =
ProtocolCharacteristics->UnloadHandler;
   MilleniumCharacteristics.PnPEventHandler =
ProtocolCharacteristics->PnPEventHandler;
   MilleniumCharacteristics.ReceivePacketHandler =
ProtocolCharacteristics->ReceivePacketHandler;
   }
  
   if (ProtocolCharacteristics->MajorNdisVersion > 4)
   {
   MilleniumCharacteristics.CoReceivePacketHandler =
  ProtocolCharacteristics->CoReceivePacketHandler;
   MilleniumCharacteristics.CoSendCompleteHandler =
ProtocolCharacteristics->CoSendCompleteHandler;
   MilleniumCharacteristics.CoStatusHandler =
ProtocolCharacteristics->CoStatusHandler;
   MilleniumCharacteristics.CoAfRegisterNotifyHandler =
ProtocolCharacteristics->CoAfRegisterNotifyHandler;
   MilleniumCharacteristics.ReservedHandlers [0] =
ProtocolCharacteristics->ReservedHandlers [0];
   MilleniumCharacteristics.ReservedHandlers [1] =
ProtocolCharacteristics->ReservedHandlers [1];
   MilleniumCharacteristics.ReservedHandlers [2] =
ProtocolCharacteristics->ReservedHandlers [2];
   MilleniumCharacteristics.ReservedHandlers [3] =
ProtocolCharacteristics->ReservedHandlers [3];
   }
  
   MilleniumCharacteristics.Name.Length =
      ProtocolCharacteristics->Name.Length/2;
   MilleniumCharacteristics.Name.MaximumLength =  
      ProtocolCharacteristics->Name.MaximumLength/2;
   MilleniumCharacteristics.Name.Buffer =
      (PUCHAR) HeapAllocate (
ProtocolCharacteristics->Name.MaximumLength,
0
);
        
   pAnsi = MilleniumCharacteristics.Name.Buffer;
   pUnicode = (unsigned short *)
      ProtocolCharacteristics->Name.Buffer;
  
    // Copy UNICODE string to ANSI string
   for (
Counter = 0;
Counter < MilleniumCharacteristics.Name.Length;
++Counter
)
   {
   *(pAnsi + Counter) = (UCHAR) *(pUnicode + Counter);
   }

   // finalize ANSI string with zero
   *(pAnsi + MilleniumCharacteristics.Name.Length) = 0;
    
   NH_NdisRegisterProtocol (
     Status,
     NdisProtocolHandle,
     (PNDIS_PROTOCOL_CHARACTERISTICS)*MilleniumCharacteristics,
     sizeof (MilleniumCharacteristics)
     );
 
   if (*Status == NDIS_STATUS_SUCCESS)
   {
      // pProto points to internal NDIS structure    
      // which holds information about protocol
      pProto = (PUCHAR) (*NdisProtocolHandle);

     // Some internal operation
     *(pProto + 0x34) = *(pProto + 0x34) | 1;
   }
  
   HeapFree ((PVOID) MilleniumCharacteristics. Name. Buffer, 0);
}
  
Thus, the problem with Windows Millennium Edition has been successfully resolved.

How to continue …

It seems to me, I\'ve given here enough information to start with implementation of the driver of the described type, certainly, I have omitted a huge set of technical details, but all of them are perfectly stated in DDK\'s documentation. So have a desire, everything else will be applied. In the meantime we shall precede to next subject, let\'s review how the similar approach can be realized in Windows NT/2000.

Part III. NDIS Hooking Filter Driver in Windows NT/2000.
For the better understanding of the technology stated in the given part acquaintance with kernel architecture of Windows NT/2000/XP is recommended. Acquaintance to writing kernel-mode drivers and the PE-format is desirable.

How to start...

Certainly you should start from creation of the elementary NT kernel-mode driver. If for the 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 command line compiler. 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 have a little different order of loading for the network subsystem, I shall not result concrete guidelines. LoadOrder utility from www.osr.com displays the order of loading of drivers in convenient manner and may be helpful to you here.

How to hook …

Implementations of 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 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, calls 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 not much worse than editing of the export table, except one important drawback. As well as the 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 fragment is taken from new NdisOpenAdapter handler:

// after calling original NdisOpenAdapter
NdisAcquireSpinLock ( &g_OpenAdapterLock );

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 location
   NdisMoveMemory (
   &pAdapter -> m_OpenBlock,
   *NdisBindingHandle,
   sizeof(NDIS_OPEN_BLOCK)
   );
  
   // Substitute NDIS_OPEN_BOCK
   *NdisBindingHandle = &pAdapter->m_OpenBlock;
  // Major work for initializing adapter finished
   // Check if complete handler did the remain in case of pending
   if ((*Status == NDIS_STATUS_PENDING)&&
      (pAdapter->m_dwAdapterState == ADAPTER_STATE_COMPLETE_FAILED)
   )
   {
   // Error while opening adapter occured,
// OpenAdapterComplete left us to free resource
   // Release already allocated resources
   AF_FreeAdapterEntry ( pAdapter );
   NdisReleaseSpinLock ( &g_OpenAdapterLock );
   return;
    }
  // Pointer to our OPEN_BLOCK (for convnience)
   pOpenBlock = (PNDIS_OPEN_BLOCK)*NdisBindingHandle;
  pAdapter->m_MacBindingHandle = pOpenBlock->MacBindingHandle;
  // Substitute Some Real handlers by our version
   pAdapter->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 but may appear a bit 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 apparent 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 that 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 with complete source code built using the reviewed approach at PCAUSA Universal NDIS-hooking Samples (common packet filtering framework for all Windows OS\'s from Win95Gold till WinXP). NT Kernel Resources offers it\'s NDIS-hooks based product WinpkFilter?, you can use it for implementing custom network filtering, NAT, VPN solutions completely in user-mode.
一切随风!
daviswjk
驱动牛犊
驱动牛犊
  • 注册日期2003-03-26
  • 最后登录2009-06-12
  • 粉丝0
  • 关注0
  • 积分334分
  • 威望64点
  • 贡献值0点
  • 好评度33点
  • 原创分0分
  • 专家分0分
7楼#
发布于:2003-04-19 18:38
中文这篇:
Windows下的个人防火墙-网络数据包拦截技术概览
 
作者:叶小虎


随着网络安全问题日益严重,网络安全产品也被人们重视起来。防火墙作为最早出现的网络安全产品和使用量最大的安全产品,也受到用户和研发机构的青睐。从防火墙的应用角度来看基本上可以分为两种:网络级的防火墙和个人防火墙。Windows操作系统作为使用最为广泛的PC操作系统,因此在Windows操作系统下开发的个人防火墙产品数不胜数。国外比较著名的有AtGuard,Outpost Firewall,ZoneAlarm,Tiny Personal Firewall,Norton Personal Firewall以及Sygate Personal Firewall等,国内用的比较多的有天网防火墙等产品。
所有基于Windows操作系统的个人防火墙核心技术点在于Windows操作系统下网络数据包拦截技术。本文主要讲述的是Windows操作系统下网络数据包拦截的技术。首先读者应该对Windows网络体系结构有一定了解,并且对开发Windows驱动程序有一定了解。

Windows 网络驱动程序结构
图1显示了Windows 2000下的网络驱动程序结构。





微软和3Com公司在1989年制定了一套开发Windows下网络驱动程序的标准,称为NDIS( Network Driver Interface Specification)。NDIS为网络驱动的开发提供了一套标准的接口,使得网络驱动程序的跨平台性更好。NDIS提供以下几个层次的接口:
?1、NDIS小端口驱动(Miniport driver)。这也就是我们常说的网卡驱动。
?2、NDIS 协议驱动(Protocol driver)。例如TCPIP协议驱动。
?3、NDIS 中间层驱动(Intermediate driver)。这是基于链路层和IP层之间的驱动。
从图1中我们可以很清楚地看到网络驱动的分层结构,这就给我们提供了拦截网络数据包的基本思路。
总的来说,要拦截Windows下的网络数据包可以在两个层面进行:用户态(user-mode)和内核态(kernel-mode)


用户态下的网络数据包拦截
在用户态下进行网络数据包拦截有以下几种方法:
1) Winsock Layered Service Provider (LSP)。这种方法在MSDN里有很详细的文档,并且给出了一个例子(SPI.CPP)。这种方法的好处是可以获得调用Winsock的进程详细信息。这就可以用来实现QoS,数据流加密等目的。但是,如果应用程序直接通过TDI(Transport Driver Inface)调用TCPIP来发送数据包,这种方法就无能为力了。对于一些木马和病毒来说要实现通过TDI直接调用TCPIP是一件很容易的事情。因此,大多数的个人防火墙都不使用这种方法。国内也有使用该方法实现的个人防火墙,例如Xfilter(www.xfilter.com)。
2) Windows 2000 包过滤接口。Windows 2000 IPHLP API提供了安装包过滤器的功能。但是,包过滤的规则有很多限制,对于个人防火墙来说是远远不够的。
3) 替换系统自带的WINSOCK动态连接库。这种方法可以在很多文章里面找到详细的实现细节。
很显然,在用户态下进行数据包拦截最致命的缺点就是只能在Winsock层次上进行,而对于网络协议栈中底层协议的数据包无法进行处理。对于一些木马和病毒来说很容易避开这个层次的防火墙。

利用驱动程序拦截网络数据包
大多数的个人防火墙都是利用网络驱动程序来实现的。从图1中我们马上可以想到可以从以下几个方面来做文章:
? 1、TDI过滤驱动程序(TDI Filter Driver)
? 2、NDIS中间层驱动程序(NDIS Intermediate Driver)
? 3、Win2k Filter-Hook Driver
? 4、NDIS Hook Driver
以下我们大体介绍这几种方法。具体的实现细节请参见Win2k DDK文档。
TDI过滤驱动程序。当应用程序要发送或接收网络数据包的时候,都是通过与协议驱动所提供的接口来进行的。协议驱动提供了一套系统预定义的标准接口来和应用程序之间进行交互。在Windows 2000/NT下,ip,tcp,udp是在一个驱动程序里实现的,叫做tcp.sys,这个驱动程序创建了几个设备:DeviceRawIp,DeviceUdp,DeviceTcp,DeviceIp, DeviceMULTICAST。应用程序所有的网络数据操作都是通过这几个设备进行的。因此,我们只需要开发一个过滤驱动来截获这些交互的接口,就可以实现网络数据包的拦截。TDI层的网络数据拦截还可以得到操作网络数据包的进程详细信息,这也是个人防火墙的一个重要功能。
NDIS中间层驱动。中间层驱动介于协议层驱动和小端口驱动之间,它能够截获所有的网络数据包(如果是以太网那就是以太帧)。NDIS中间层驱动的应用很广泛,不仅仅是个人防火墙,还可以用来实现VPN,NAT,PPPOverEthernet以及VLan。中间层驱动的概念是在Window NT SP4之后才有的,因此对于Windows9x来说无法直接利用中间层驱动的功能。Windows DDK提供了两个著名的中间层驱动例子:Passthru以及Mux。开发人员可以在Passthru的基础上进行开发,Mux则实现了VLan功能。目前个人防火墙的产品还很少用到这种技术,主要的原因在于中间层驱动的安装过于复杂,尤其是在Windows NT下。Windows 2000下可以通过程序实现自动安装,但是如果驱动没有经过数字签名的话,系统会提示用户是否继续安装。中间层驱动功能强大,应该是今后个人防火墙技术的趋势所在,特别是一些附加功能的实现。
Win2k Filter-Hook Driver。这是从Windows2000开始系统所提供的一种驱动程序,该驱动程序主要是利用ipfiltdrv.sys所提供的功能来拦截网络数据包。Filter-Hook Driver在结构非常简单,易于实现。但是正因为其结构过于简单,并且依赖于ipfiltdrv.sys,Microsfot并不推荐使用Filter-Hook Driver。
NDIS Hook Driver。这是目前大多数个人防火墙所使用的方法。Hook的概念在Windows9x下非常流行,而且实现也很容易。在Windows9x下,驱动程序(VxD)通过使用Hook_Device_Service可以挂接NDIS所提供的所有服务。在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下是非公开的,因此开发人员需要利用各种调试工具来发掘该结构的详细定义。也正是因为如此,这种方法对平台的依赖性比较大,需要在程序中判断不同的操作系统版本而使用不同的结构定义。


总结
本文重点描述了在WindowsNT/2000/xp下个人防火墙核心技术-网络数据包拦截技术,分析了各种可能的方法以及各种方法的优缺点,实际上许多个人防火墙结合了几种不同的技术来在不同层面上进行网络数据包拦截。值得说明的是,网络数据包拦截技术不仅仅可以用来开发个人防火墙,还可以用来开发其他的产品。
 
一切随风!
daviswjk
驱动牛犊
驱动牛犊
  • 注册日期2003-03-26
  • 最后登录2009-06-12
  • 粉丝0
  • 关注0
  • 积分334分
  • 威望64点
  • 贡献值0点
  • 好评度33点
  • 原创分0分
  • 专家分0分
8楼#
发布于:2003-04-19 18:43
韩国网站的一篇,我打包了,感觉图片做的比较直观
附件名称/大小 下载次数 最后更新
2003-04-19_firewall.rar (402KB)  11
一切随风!
flyearly
驱动牛犊
驱动牛犊
  • 注册日期2003-01-14
  • 最后登录2016-01-07
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
9楼#
发布于:2003-04-21 12:02
好文章,学习!
:D
chsw1984
驱动牛犊
驱动牛犊
  • 注册日期2002-11-18
  • 最后登录2009-06-06
  • 粉丝0
  • 关注0
  • 积分12分
  • 威望21点
  • 贡献值0点
  • 好评度1点
  • 原创分0分
  • 专家分0分
10楼#
发布于:2003-04-25 23:45
thank u .
能不能给一份翻译的文件?
韩文看不懂
游客

返回顶部