☆ Filter-hook driver
☆ PacketFilTeRextensionPtr
☆ Setting / clear callback function
1) Call IOGETDEVICEOBJECTPOINTER () Get the corresponding device objects for IPFilterDriver
2) Call IOBUILDDEVICEIOCONTROLREQUEST () Construct IRP
3) Call ocallDriver () Submit IRP to IPFilterDriver
☆ A complete Filter-Hook Driver Frame (Discard all ICMP packets, and received RST packets)
1) ipflthookdrv.c
2) DIRS
3) Sources
4) Makefile
5) InstallDriver.c
6) ipflthookdrvtest.c
7) Verification effect
☆ Reference resources
-------------------------------------------------- ---------------------------------------------------------------------------------------------------------------------------------------
☆ Filter-hook driver
IPFilterDriver from Windows 2000 is a driver that comes with the system, as the name suggests, is IP filtering
Drive, correspond to the IPFLtdrv.sys file. By default, this driver is not loaded, but it can be manually loaded.
> SC Queryex IPFilterDriver
Service_name: ipfilterdriver
TYPE: 1 KERNEL_DRIVER
State: 1 stopped
(Not_Stoppable, Not_Pausable, Ignores_Shutdown)
WIN32_EXIT_CODE: 0 (0x0)
SERVICE_EXIT_CODE: 0 (0x0)
Checkpoint: 0x0
WAIT_HINT: 0X0
PID: 0
Flags:
> ENUMSERVICE.EXE | FINDSTR / I IPFilter
Device Driver Stop IpfilterDriver IP Traffic Filter Driver
> NET Start IPfilterdriver
The IP Traffic Filter Driver Service Was Started SuccessFully.
> ENUMSERVICE.EXE | FINDSTR / I IPFilter
Equipment driver runs IPfilterDriver ip Traffic Filter Driver
> NET STOP IPFILTERDRIVER
The IP Traffic Filter Driver Service Was Stopped SuccessFully.
Filter-hook driver is a KMD that matches IPFilterDriver. Obviously this can only be used for TCP / IP
Agreement, and other protocols such as IPX / SPX, NetBeui are unable to force.
You can only install a Filter-Hook Driver up to one. Only when Filter-Hook Callback function is empty
When Filter-Hook Driver can register ipfilterdriver to the callback function provided by ipfilterdriver, the latter
Use the Filter-Hook Callback Function to determine how to handle the received or ready-to-send IP packets.
After the registration callback function is over, IPFilterDriver will follow the file object of Filter-Hook Driver.
The adjustment is associated to ensure that only one Filter-Hook Driver is available. Starting with Windows XP, Microsoft is not recommended to use Filter-Hook Driver to implement firewalls. From the network level
Filter-hook driver is too high. In addition, Filter-Hook Driver will also ignore ICS or
Other personal firewalls. ICS is Internet Connection Sharing, you can easily understand XP / 2003
The personal firewall belled, of course, is not as simple as it, ICS can realize port forwarding, NAT and other similar functions.
If you like, you can try to use ICS to make an XP / 2003 into a NAT gateway. I have not actually tested, TK has been
Some experiments. For XP / 2003, NDIS Intermediate Driver is recommended to implement a firewall. Although if
This, I still learn Filter-Hook Driver because it is relatively simple.
The user state has a set of Packet Filtering API, dealing with IPFilterDriver, and has modified optimization.
It can be filtered according to SRCIP, DSTIP, SrcPort, Dstport, but with Filter-Hook Driver
Unrelated! If you only pay attention to the IP address and port, you can consider the set of APIs, but try to filter ICMP packets.
Consider Filter-Hook Driver.
☆ PacketFilTeRextensionPtr
The prototype of the callback function mentioned earlier is as follows:
Typedef pf_forward_action (* packetfilterextensionptr)
(
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
);
Because it is a callback function, the function name does not matter, the DDK document recommends a meaningful name. Letter
There are three returns:
Pf_forward
The IP protocol stack is handed directly. If the IP packet is sent to the unit, the extension IP protocol stack is transmitted upward. in case
IP packets are sent to another host, and this machine enables "IP forwarding (routing function)", according to routing
The table is forwarded.
PF_DROP
The IP protocol stack will discard the IP packet.
PF_pass
If the User-state Packet Filtering API defines the filtering rule, you get the opportunity to filter. Such as
Filter-Hook Driver feels a chance to give the user-state packet filtering api, must
Returns PF_PASS, at this time, by IPFilterDriver is filtered. Returns PF_forward means packet
Filtering rules defined by the Filtering API failed, hehe.
☆ Setting / clear callback function
1) Call IOGETDEVICEOBJECTPOINTER () Get the corresponding device objects for IPFilterDriver
NTSTATUS IOGETDEVICEOBJECTPOINTER
(
In Punicode_String ObjectName,
IN Access_mask desidaccess,
OUT Pfile_Object * fileObject,
OUT PDEVICE_Object * DeviceObject);
Objectname
To correspond to DD_IPFLTRDRVR_DEVICE_NAME, this is the macro defined in pfhook.h, ie
L "// device // ipfilterdriver". Pay attention to the type of ObjectName, need to call
RTLinitunicodeString ().
DespedAccess
DDK documents indicate that "Synchronize | Generic_Read | Generic_Write" should be specified. in case
If you can specify STANDARD_RIGHTS_ALL.
See the Access_Mask Reference in Platform SDK DOC.
FILEOBJECT
When uninstalling the Filter-Hook Driver, you should call ObdereferenceObject () to reduce this file object.
Reference count, at this time, indirectly reduce the reference count of the corresponding device object, otherwise IpFilterDriver
The method is correctly uninstalled.
Void ObdereferenceObject
(
In Pvoid Object
);
DEVICEOBJECT
This will be used back to return data
2) Call IOBUILDDEVICEIOCONTROLREQUEST () Construct IRP
PirP IobuildDeviceiocontrolRequest
(
In Ulong IoControlcode,
In PDEvice_Object DeviceObject,
In Pvoid InputBuffer Optional,
In Ulong InputBufferLength,
Out Pvoid OutputBuffer Optional,
In Ulong OutputBufferlength,
In Boolean InternalDeviceiocontrol,
In Pkevent Event,
OUT PIO_STATUS_BLOCK IOSTATUSBLOCK
);
IOControlcode
Must specified IOCTL_PF_SET_EXTENSION_POINTER
DEVICEOBJECT
IpFilterDriver's corresponding device object
InputBuffer
It should be forced to convert to PPF_SET_EXTENSION_HOOK_INFO, its extensionpointer member
Is equal to the callback function address. If the ExtensionPointer member is NULL, it means the clearance operation.
Typedef struct _pf_set_extension_hook_info
{
Packetfilterextensionptr extensionPointer;
} Pf_set_extension_hook_info, * ppf_set_extension_hook_info;
When uninstalling the Filter-Hook Driver, the callback function must be cleared.
InputBufferLength
SIZEOF (PF_SET_EXTENSION_HOOK_INFO)
OutputBuffer
NULL
OutputBufferlength
0
InternalDeviceIocontrol
Must specify False so that IPFilterDriver processes the Dispatch of IRP_MJ_DEVICE_CONTROL
The routine is called.
Event
NULL
Iostatusblock
You should specify a valid value
3) Call ocallDriver () Submit IrPntStatus IocallDriver to IPFilterDriver
(
In PDEvice_Object DeviceObject,
In out PIRP IRP
);
DEVICEOBJECT
IpFilterDriver's corresponding device object
IRP
Step 2 IRP
☆ A complete Filter-Hook Driver Frame (Discard all ICMP packets, and received RST packets)
1) ipflthookdrv.c
This example can discard all ICMP packets and the received RST packets. Generally discarding all ICMP messages will not make
Big problem. Obviously, ping, tracert This type of tool that relies on ICMP packets will not be used properly, others
You can't ping you, huh. Discard all RST packets sent to this unit according to TH_FLAGS, but allow this machine to be sent
RST packets give others. As for the more complex demonstration related to TCP / IP protocol, it is not to write.
firewall.
-------------------------------------------------- ---------------------------------------------------------------------------------------------------------------------------------------
/ *
* For x86 / ewindows XP SP1 & VC 7 & Windows DDK 2600.1106
* build -cz -x86
* /
/ ************************************************** **********************
* *
* Head file *
* *
*********************************************************** ********************* /
#include
/ *
* typedef ulong ipaddr, ipmask;
* /
#include
#include
/ *
* Use the CTL_CODE macro
* /
#include
/ ************************************************** **********************
* *
* Macro *
* *
*********************************************************** ********************* /
/ *
* Behind it is necessary to add DEVICENUMBER
* /
#define interName L "// device // ipfilterhootinternal"
/ *
* Dosdevices
* /
#DEfine ExternalName L "// ?? // ipfilterhookexternal" / *
* Participation DDK documentation in ExallocatePoolwithtag
* /
#define privatetag 'OFSN'
/ *
* 0x0800 is the minimum usable value
* /
#define ipfilterhook_index 0x0800
#define ioctl_ipfilterhook_get_firewallflags CTL_CODE /
(/
FILE_DEVICE_NETWORK, /
IPFilTerhook_index 0, /
Method_buffered, /
FILE_READ_ACCESS /
)
#define ioctl_ipfilterhook_set_firewallflags CTL_CODE /
(/
FILE_DEVICE_NETWORK, /
IPFilTerhook_index 1, /
Method_buffered, /
FILE_WRITE_ACCESS /
)
/ *
* Set - enable
* Reset - Disable
* /
#define firewallflags_disableAll 0x00000000
/ *
* All ICMP packets, including reception, send
* /
#DEFINE FIREWALLFLAGS_ALLICMP 0x00000001
/ *
* Received RST packet
* /
#define firewallflags_inboundrst 0x00000002
#define fireflags_enableall 0xfffffffff
/ *
* The default setting is all allowed, that is, do not discard any packets
* /
#define fireflags_default firewallflags_enableAll
/ *
* Device extension is a custom structure
* /
Typedef struct _device_extension
{
PDEvice_Object DeviceObject;
Ulong DeviceNumber;
} Device_extension, * pdevice_extension;
#define offsetof (Type, Member) ((SIZE_T) & ((TYPE) 0) -> MEMBER)
/ *
* Definitions for ip type of service (ip_tos) *
* Repeat definition is to facilitate transplantation
* /
#define iptos_lowdelay 0x10
#define iptos_throughput 0x08
#define iptos_reliability 0x04
#define iptos_mincost 0x02
#define ipproto_ICMP 1
#define ipproto_tcp 6
#define ipproto_udp 17
/ *
* Customization The following structure is for convenient porting
* /
#pragma Pack (Push, 1)
/ *
* Structure of an Internet header, Naked of Options.
* /
Struct ipheader
{
#ifdef little_endian
/ *
* 0x45, Little_endian order is behind. IP_HL is in 4 bytes.
* /
Unsigned char ip_hl: 4; / * header length * /
Unsigned char ip_v: 4; / * version * /
#ELSE
/ *
* 0x45, BIG_ENDIAN order high
* /
Unsigned char ip_v: 4; / * version * /
Unsigned char ip_hl: 4; / * header length * /
#ENDIF
Unsigned char ip_tos; / * type of service * /
/ *
* ip_len is in bytes
* /
Unsigned short int ip_len; / * total length * /
Unsigned short int ip_id; / * identification * /
/ *
* ip_off in 8 bytes
* /
Unsigned short int ip_off; / * fragment offset field * /
/ *
* ip_off only accounts for 13-bits, the last two of the first 3-bits is DF, MF
* /
#define ip_df 0x4000 / * DONT FRAGMENT FLAG * /
#define ip_mf 0x2000 / * more Fragments flag * /
Unsigned char ip_ttl; / * time to live * /
Unsigned char ip_p; / * protocol * /
Unsigned short int ip_sum; / * checksum * /
#if 0
/ *
* We don't use these two members to reduce them in order to reduce compilation.
* /
Struct in_addr ip_src; / * source address * /
Struct in_addr ip_dst; / * dest address * / # Endif
}
/ *
* TCP Header. (With some options)
* Per RFC 793, September, 1981.
* /
Struct TCPHEADER
{
Unsigned short int th_sport; / * source port * /
Unsigned short int th_dport; / * destination port * /
Unsigned int th_seq; / * sequence number * /
Unsigned int th_ack; / * Acknowledgement number * /
#ifdef littletlendian
/ *
* 0x50, Littlendian order high
* /
Unsigned char TH_X2: 4, / * (unused) * /
TH_OFF: 4; / * Data Offset * /
#ELSE
/ *
* 0x50, BiGendian order high before. TH_OFF is in 4 bytes.
* /
Unsigned char th_off: 4, / * data offset * /
TH_X2: 4; / * (unused) * /
#ENDIF
Unsigned char th_flags;
#define TH_FIN 0x01
#define TH_SYN 0x02
#define TH_RST 0x04
#define TH_PSH 0x08
#define TH_ACK 0x10
#define TH_URG 0x20
Unsigned short int th_win; / * window * /
Unsigned short int th_sum; / * checksum * /
UNSIGNED SHORT INT TH_URP; / * Urgent Pointer * /
/ *
* See W.Richard Stevens TCP / IP Illustrate Volume I 18.10 Section
*
* Kind = 2 LEN = 4 MSS (excluding IP head, TCP head)
*
* /
Unsigned char th_optmsskind;
Unsigned char th_optmsslen
Unsigned short int th_optmss;
/ *
* Kind = 1
* /
Unsigned char th_optnopa;
Unsigned char th_optnopb;
/ *
* Kind = 4 len = 2
* /
Unsigned char th_optsackpermittedkind;
Unsigned char th_optsackpermittedlen;
}
#pragma pack (POP)
/ ************************************************** **********************
* *
* Function prototype ** *
*********************************************************** ********************* /
/ *
* Non-dispatch function
* /
Static NTSTATUS IFHCREATEDEVICE
(
In PDRIVER_OBJECT DriverObject,
In Ulong DeviceNumber
);
/ *
* Non-dispatch function
* /
Static void ifdeleteDevice
(
In PDEvice_Object DeviceObject
);
/ *
* Search in DDK Documents DISPATCHCLOSE
* /
Static NTSTATUS IFHDISPATCHCLOSE
(
In PDEvice_Object DeviceObject,
In PIRP IRP
);
/ *
* Search for DispatchCreate in DDK documentation
* /
Static NTSTATUS IFHDISPATCHCREATE
(
In PDEvice_Object DeviceObject,
In PIRP IRP
);
/ *
* Search in DDK documentation DispatchDeviceControl
* /
Static NTSTATUS IFHDISPATCHDEVICECONTROL
(
In PDEvice_Object DeviceObject,
In PIRP IRP
);
Static NTSTATUS IFHDOHOOK
(
PacketfilTeRextensionPtr FWFUNC
);
/ *
* Non-dispatch function, search unload in DDK documentation
* /
Static void ifdriverunload
(
In PDRIVER_OBJECT DriverObject
);
/ *
* Tune function, search for packetfilterextensionptr in DDK documentation
* /
Static pf_forward_action ifhfirewall
(
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
);
/ *
* Unique extraction function
* /
NTSTATUS DRIVERENTRY
(
In PDRIVER_OBJECT DriverObject,
In dunicode_string registrypath;
/ *
* See << The Windows 2000 Device Driver Book, SECOND Edition >> 5.2.6,
* 5.2.7 Section. INIT, PAGE should be sensitive, but I actually saw init, page, unclear
* What is going on? It's still in init, and it's calculated.
*
* Ifhfirewall is called, I am in what IRQL, I don't know, the security is, not here.
* /
#ifdef alloc_pragma
#pragma alloc_text (init, ifhcreateDevice)
#pragma alloc_text (Page, IFHDELETEDEVICE)
#pragma alloc_text (Page, IFHDISPATCHCLOSE)
#pragma alloc_text (Page, IFHDISPATCHCREATE)
#pragma alloc_text (page, ifdispatchDeviceControl)
#pragma alloc_text (Page, IFHDOHOK)
#pragma alloc_text (Page, IFHDRIVERUNLOAD)
#pragma alloc_text (init, driverentry)
#ENDIF
/ ************************************************** **********************
* *
* Static global var *
* *
*********************************************************** ********************* /
/ *
* Since the callback function if IFHFIREWALL wants to use this flag, set to a static global variable.
* /
Static Ulong FireWallFlags = FireWallFlags_Default;
/ ************************************************** ********************** /
/ *
* Non-Dispatch functions. If you don't make an error handling, the function will be streamlined. In fact, it is called two letters.
* Number, IOCREATEDEVICE and IOCREATESYMBOLICLINK, establish internal device names, external devices, respectively
* Name.
* /
Static NTSTATUS IFHCREATEDEVICE
(
In PDRIVER_OBJECT DriverObject,
In Ulong DeviceNumber
)
{
NTSTATUS STATUS;
PDEvice_Object DeviceObject;
PDEvice_EXTENSION DEVICEEXTENSITION;
Unicode_string deficename;
Unicode_String SymbolicLinkName; Unicode_String NumberUnicodestring;
Unicode_String InternalNameUnicodestring;
Unicode_String ExternalNameUnicodestring;
KDPrint ("Entering ifhcreateDevice () / n"))
/ *
* If the string is null-terminated, length does not incrude the
* Trailing null.
* /
NumberunicodeString.Length = 0;
/ *
* 0xffffffFFFFFFFFFFFFFFFFFF is 4294967295, up to 10 characters, plus NUL end, no
* More than 11.
* /
NumberunicodeString.maximum lonngune = 16;
/ *
* Pvoid ExallocatePoolwithtag
*
* In pool_type pooltype,
* In size_t numberofbytes,
* In ulong tag
*);
*
* The memory is allocated, remember to release it later.
* /
NumberunicodeString.Buffer = (pwstr) ExallocatePoolwithtag
(
PagedPool,
Numberunicodestring.maximumlength,
PrivateTag
);
IF (null == NumberunicodeString.Buffer)
{
/ *
* DDK document pointed out that if ExallocatePool returns NULL, the main adjustment should return
* Status_insuffectient_resources. But did not point out in the DDK document
* How is exallocatepoolwithtag Returns NULL, I have to ratio, return it.
* Status_insuffectient_resources. I don't know if it can be returned here.
* Status_no_memory.
* /
Return (status_insuffect_resources);
}
/ *
* NTSTATUS RTLINTEGERTOUNICODESTRINGERTUNICODESTRING
*
* In Ulong Value,
* In Ulong Base Optional,
* In Out Punicode_String String
*);
*
* Converts An Unsigned Integer Value to a Null-Terminated String of ONE
* or more Unicode Characters in The Specified Base.
* /
Status = RTLINTEGERTOUNICODESTRING
(
DeviceNumber,
10,
& NumberUnicodestring
);
IF (! NT_Success (status))
{
EXFREEPOOLWITHTAG
(
NumberunicodeString.Buffer,
PrivateTag
);
RTLZEROMEMORY
(
& NumberunicodeString, Sizeof (NumberunicodeString)
);
Return (status);
}
/ *
* Void rtlinitunicodeString
*
* In Out Punicode_String DestinationString,
* In pcwstr sourcestring
*);
*
* This function is not dynamically allocated
* /
RTLinitunicodeString (& DeviceName, INTERNAME);
/ *
* Additional DeviceNumber later. No wsprintf () is available, no already, I have to change this.
* deal with.
* /
INTERNALNAMEUNICODESTRING.LENGTH = DeviceName.length NumberunicodeString.Length
INTERNALNAMEUNICODESTRING.MAXIMUMLENGTH = INTERNALNAMEUNICODESTRING.LENGTH 2;
INTERNALNAMEUNICODESTRING.BUFFER = (PWSTR) ExallocatePoolwithTAG
(
PagedPool,
INTERNALNAMEUNICODESTRING.MAXIMUMLENGTH,
PrivateTag
);
IF (null == internameunicodeString.buffer)
{
/ *
* NTkernelapi Void EXFREEPOOLWITHTAG
*
* In pvoid P,
* In ulong tag
*);
*
* Need to release NumberUnicodestring.buffer
* /
EXFREEPOOLWITHTAG
(
NumberunicodeString.Buffer,
PrivateTag
);
/ *
* Void RTLZERMEMORY
*
* In void unaligned * Destination,
* In size_t length
*);
* /
RTLZEROMEMORY
(
& Numberunicodestring,
SIZEOF (NumberunicodeString)
);
Return (status_insuffect_resources);
}
/ *
* Void RTLCopyUnicodestring
*
* In Out Punicode_String DestinationString,
* In Punicode_String SourceString
*);
* /
RTLCopyUnicodestring
(
& InternalNameUnicodestring,
& DeviceName
);
/ *
* NTSTATUS RTLAPPPENDUNICODESTRINGTOSTRING
*
* In Out Punicode_String Destination,
* In Punicode_String Source
*);
* /
Status = RTLAPPPENDUNICODESTRINGTOSTRING
(
& InternalNameUnicodestring,
& NumberUnicodestring
);
/ *
* No NumberunicodeString.buffer is required, release it early. * /
EXFREEPOOLWITHTAG
(
NumberunicodeString.Buffer,
PrivateTag
);
RTLZEROMEMORY
(
& Numberunicodestring,
SIZEOF (NumberunicodeString)
);
IF (! NT_Success (status))
{
EXFREEPOOLWITHTAG
(
INTERNALNAMEUNICODESTRING.BUFFER,
PrivateTag
);
RTLZEROMEMORY
(
& InternalNameUnicodestring,
SIZEOF (InternalNameUnicodestring)
);
Return (status);
}
InternameunicodeString.Buffer [InternameUnicodestring.Length / 2]
= Unicode_null;
/ *
* NTSTATUS IOCREATEDEVICE
*
* In PDRIVER_Object DriverObject,
* In Ulong DeviceExtensions Ize,
* In Punicode_String DeviceName Optional,
* In Device_Type DeviceType,
* In Ulong DeviceCharacteristics,
* In Boolean Exclusive,
* OUT PDEVICE_OBJECT * DEVICEOBJECT
*);
* /
Status = IOCREATEVICE
(
DriverObject,
SIZEOF (Device_extension),
& InternalNameUnicodestring,
File_Device_network,
0,
False,
& DeviceObject
);
IF (! NT_Success (status))
{
EXFREEPOOLWITHTAG
(
INTERNALNAMEUNICODESTRING.BUFFER,
PrivateTag
);
RTLZEROMEMORY
(
& InternalNameUnicodestring,
SIZEOF (InternalNameUnicodestring)
);
Return (status);
}
DeviceObject-> flags | = do_buffered_io;
/ *
* Initialize the Device Extension
*
* The memory space of the device extension is given by IOCREATEDEVICE.
* /
DeviceExtension = (PDEvice_extension) DeviceObject-> DeviceExtension;
DeviceExtension-> DeviceObject = DeviceObject;
DeviceExtension-> DeviceNumber = DeviceNumber;
/ *
* The following starts processing SymbolicLink
* /
NumberunicodeString.Length = 0; NumberunicodeString.maximumLength = 16;
/ *
* The memory is allocated, remember to release it later.
* /
NumberunicodeString.Buffer = (pwstr) ExallocatePoolwithtag
(
PagedPool,
Numberunicodestring.maximumlength,
PrivateTag
);
IF (null == NumberunicodeString.Buffer)
{
IodeleteDevice (DeviceObject);
DeviceObject = NULL;
EXFREEPOOLWITHTAG
(
INTERNALNAMEUNICODESTRING.BUFFER,
PrivateTag
);
RTLZEROMEMORY
(
& InternalNameUnicodestring,
SIZEOF (InternalNameUnicodestring)
);
Return (status_insuffect_resources);
}
/ *
* General internal device number from 0, external device number from 1
* /
Status = RTLINTEGERTOUNICODESTRING
(
DeviceNumber 1,
10,
& NumberUnicodestring
);
IF (! NT_Success (status))
{
IodeleteDevice (DeviceObject);
DeviceObject = NULL;
EXFREEPOOLWITHTAG
(
INTERNALNAMEUNICODESTRING.BUFFER,
PrivateTag
);
RTLZEROMEMORY
(
& InternalNameUnicodestring,
SIZEOF (InternalNameUnicodestring)
);
EXFREEPOOLWITHTAG
(
NumberunicodeString.Buffer,
PrivateTag
);
RTLZEROMEMORY
(
& Numberunicodestring,
SIZEOF (NumberunicodeString)
);
Return (status);
}
RTLinitunicodeString (& SymbolicLinkName, ExternalName);
ExternalNameUnicodestring.Length = SymbolicLinkName.Length NumberunicodeString.Length;
ExternalNameUnicodestring.maximumlength = ExternalNameUnicodestring.LENGTH 2;
ExternalNameUnicodestring.buffer = (pwstr) ExallocatePoolwithtag
(
PagedPool,
ExternalNameUnicodestring.maximumlength,
PrivateTag
);
IF (null == externalNameUnicodestring.buffer)
{
/ *
* Void IodeleteDevice
*
* In PDEvice_Object DeviceObject
*);
*
* Need to cancel IOCREATEDEVICE
* /
IodeleteDevice (DeviceObject);
DeviceObject = NULL;
EXFREEPOOLWITHTAG
(
INTERNALNAMEUNICODESTRING.BUFFER,
PrivateTag
);
RTLZEROMEMORY
(
& InternalNameUnicodestring,
SIZEOF (InternalNameUnicodestring)
);
EXFREEPOOLWITHTAG
(
NumberunicodeString.Buffer,
PrivateTag
);
RTLZEROMEMORY
(
& Numberunicodestring,
SIZEOF (NumberunicodeString)
);
Return (status_insuffect_resources);
}
/ *
* Void RTLCopyUnicodestring
*
* In Out Punicode_String DestinationString,
* In Punicode_String SourceString
*);
* /
RTLCopyUnicodestring
(
& ExtelNameUnicodestring,
& Symboliclinkname
);
Status = RTLAPPPENDUNICODESTRINGTOSTRING
(
& ExtelNameUnicodestring,
& NumberUnicodestring
);
/ *
* No NumberunicodeString.buffer is required, release it early.
* /
EXFREEPOOLWITHTAG
(
NumberunicodeString.Buffer,
PrivateTag
);
RTLZEROMEMORY
(
& Numberunicodestring,
SIZEOF (NumberunicodeString)
);
IF (! NT_Success (status))
{
EXFREEPOOLWITHTAG
(
ExternalNameUnicodestring.buffer,
PrivateTag
);
RTLZEROMEMORY
(
& ExtelNameUnicodestring,
SIZEOF (ExternalNameUnicodestring)
);
IodeleteDevice (DeviceObject);
DeviceObject = NULL;
EXFREEPOOLWITHTAG
(
INTERNALNAMEUNICODESTRING.BUFFER,
PrivateTag
);
RTLZEROMEMORY
(
& InternalNameUnicodestring,
SIZEOF (InternalNameUnicodestring)
);
Return (status);
}
ExternalNameUnicodestring.buffer [ExternalNameUnicodestring.Length / 2]
= Unicode_null;
/ *
* NTSTATUS IOCREATESYMBOLICLINK
*
* In Punicode_String SymbolicLinkName,
* In Punicode_String DeviceName
*);
* /
Status = IOCREATESYMBOLICLICLINK
& ExtelNameUnicodestring,
& INTERNALNAMEUNICODESTRING
);
/ *
* No need in INTERNALNAMEUNICODESTRING.Buffer, ExternalNameUnicodestring.buffer
* /
EXFREEPOOLWITHTAG
(
ExternalNameUnicodestring.buffer,
PrivateTag
);
RTLZEROMEMORY
(
& ExtelNameUnicodestring,
SIZEOF (ExternalNameUnicodestring)
);
EXFREEPOOLWITHTAG
(
INTERNALNAMEUNICODESTRING.BUFFER,
PrivateTag
);
RTLZEROMEMORY
(
& InternalNameUnicodestring,
SIZEOF (InternalNameUnicodestring)
);
IF (! NT_Success (status))
{
IodeleteDevice (DeviceObject);
DeviceObject = NULL;
}
Return (status_success);
} / * End of ifhcreateDevice * /
/ *
* Non-Dispatch functions. In fact, call two functions, IodeeteSymbolicLink and
* Odeletedevice.
* /
Static void ifdeleteDevice
(
In PDEvice_Object DeviceObject
)
{
NTSTATUS STATUS;
PDEvice_EXTENSION DEVICEEXTENSITION;
Unicode_String SymbolicLinkName;
Unicode_String NumberunicodeString;
Unicode_String ExternalNameUnicodestring;
Kdprint ("Entering ifhdeletedEvice () / n"))
DeviceExtension = (PDEvice_extension) DeviceObject-> DeviceExtension;
NumberunicodeString.Length = 0;
NumberunicodeString.maximum lonngune = 16;
/ *
* The memory is allocated, remember to release it later.
* /
NumberunicodeString.Buffer = (pwstr) ExallocatePoolwithtag
(
PagedPool,
Numberunicodestring.maximumlength,
PrivateTag
);
IF (null == NumberunicodeString.Buffer)
{
/ *
* Consider output some debugging information
*
* This routine is defined in ntddk.h, wdm.h, and ndis.h.
* A call to this macro required double parentheses.
* /
KDPRINT (("exallocatepoolwithtag () for number inicodestring.buffer failed / n")); Return;
}
/ *
* General internal device number from 0, external device number from 1
* /
Status = RTLINTEGERTOUNICODESTRING
(
DeviceExtension-> DeviceNumber 1,
10,
& NumberUnicodestring
);
IF (! NT_Success (status))
{
EXFREEPOOLWITHTAG
(
NumberunicodeString.Buffer,
PrivateTag
);
RTLZEROMEMORY
(
& Numberunicodestring,
SIZEOF (NumberunicodeString)
);
KDPRINT ("RTLINTEGERTOUNICODESTRING () FAILED / N"));
Return;
}
RTLinitunicodeString (& SymbolicLinkName, ExternalName);
ExternalNameUnicodestring.Length = SymbolicLinkName.Length NumberunicodeString.Length;
ExternalNameUnicodestring.maximumlength = ExternalNameUnicodestring.LENGTH 2;
ExternalNameUnicodestring.buffer = (pwstr) ExallocatePoolwithtag
(
PagedPool,
ExternalNameUnicodestring.maximumlength,
PrivateTag
);
IF (null == externalNameUnicodestring.buffer)
{
EXFREEPOOLWITHTAG
(
NumberunicodeString.Buffer,
PrivateTag
);
RTLZEROMEMORY
(
& Numberunicodestring,
SIZEOF (NumberunicodeString)
);
Kdprint ("ExternalNameUnicodestring.buffer filed / n");
Return;
}
/ *
* Void RTLCopyUnicodestring
*
* In Out Punicode_String DestinationString,
* In Punicode_String SourceString
*);
* /
RTLCopyUnicodestring
(
& ExtelNameUnicodestring,
& Symboliclinkname
);
Status = RTLAPPPENDUNICODESTRINGTOSTRING
(
& ExtelNameUnicodestring,
& NumberUnicodestring
);
/ *
* No NumberunicodeString.buffer is required, release it early.
* /
EXFREEPOOLWITHTAG
(
NumberunicodeString.Buffer,
PrivateTAG);
RTLZEROMEMORY
(
& Numberunicodestring,
SIZEOF (NumberunicodeString)
);
IF (! NT_Success (status))
{
EXFREEPOOLWITHTAG
(
ExternalNameUnicodestring.buffer,
PrivateTag
);
RTLZEROMEMORY
(
& ExtelNameUnicodestring,
SIZEOF (ExternalNameUnicodestring)
);
Kdprint ("RTLAPPENDUNICODESTRINGTOSTRING () FAILED / N"));
Return;
}
ExternalNameUnicodestring.buffer [ExternalNameUnicodestring.Length / 2]
= Unicode_null;
/ *
* NTSTATUS IODELETESYMBOLICLINK
*
* In Punicode_String SymbolicLinkName
*);
* /
Status = odeletessymboliclink
(
& ExternaMeunicodeString
);
/ *
* Don't need ExternalNameUnicodestring.buffer
* /
EXFREEPOOLWITHTAG
(
ExternalNameUnicodestring.buffer,
PrivateTag
);
RTLZEROMEMORY
(
& ExtelNameUnicodestring,
SIZEOF (ExternalNameUnicodestring)
);
IF (! NT_Success (status))
{
Kdprint ("IodeeteSymbolicLink () Failed / N"));
Return;
}
/ *
* Void IodeleteDevice
*
* In PDEvice_Object DeviceObject
*);
* /
IodeleteDevice (DeviceObject);
Return;
} / * End of ifhndeleteDevice * /
/ *
* Handles Call from Win32 CloseHandle Request. For Ipfilterhook Driver, FreeES
* Any buffer.
* /
Static NTSTATUS IFHDISPATCHCLOSE
(
In PDEvice_Object DeviceObject,
In PIRP IRP
)
{
Kdprint ("Entering ifhdispatchClose () / n"));
IRP-> iostatus.status = status_success;
IRP-> iostatus.information = 0;
IOCOMPLETEREQUEST (IRP, IO_NO_INCREMENT);
Return (status_success);
} / * End of if.patchClose * /
/ *
* Handles Call from Win32 CreateFile Request. For ipfilterhook driver, does
* Nothing.
* /
Static NTSTATUS IFHDISPATCHCREATE
(
In PDEvice_Object DeviceObject, in PIRP IRP
)
{
Kdprint ("Entering ifhdispatchCreate () / n"));
/ *
* Although IRP is serial transmission for the driver, the I / O Manager uses IRP in parallel. In general,
* The Dispatch routine needs to modify a member of the IRP, you should create a copy on your stack or device extension.
* /
IRP-> iostatus.status = status_success;
/ *
* Report That no bytes were transfered
* /
IRP-> iostatus.information = 0;
/ *
* Void iocompleterequest
*
* In PIRP IRP,
* In cchar priorityboost
*);
*
* IOCOMPLETEREQUEST INDICES The Caller Has Completed All Processing
* for a given I / o Request and is returbing the given Irp to the I / O
* Manager.
*
* Priorityboost is io_no_increment if the Original Thread Requested
* an Operation The Driver Could Complete Quickly or if The IRP IS
* Completed with an error.
*
* Mark The IRP AS "Complete" - No further processing, no priority
* increment.
* /
IOCOMPLETEREQUEST (IRP, IO_NO_INCREMENT);
/ *
* After calling IOCOMPLETEREQUEST (), I / O Manager can release the IRP from the non-tap pool, so
* Codes such as Return (IRP-> iostatus.status) cannot appear.
* /
Return (status_success);
} / * End of ifhdispatchcreate * /
/ *
* Handles Call from Win32 DeviceioControl Request.
* /
Static NTSTATUS IFHDISPATCHDEVICECONTROL
(
In PDEvice_Object DeviceObject,
In PIRP IRP
)
{
NTSTATUS STATUS;
PIO_STACK_LOCATION IRPSTACKLOCATION;
Ulong IoControlcode;
Ulong InputBufferLength;
Ulong OutputBufferlength;
Ulong TransferSize;
PVOID TRANSFERBUFFER;
Kdprint ("Entering ifhdispatchDeviceControl () / n"))));
Status = status_success;
TransferSize = 0;
TransferBuffer = IRP-> AssociatedIrp.systembuffer;
IrpstackLocation = IOGETCURRENTIRPSTACKLOCATION (IOCONTROLCODE = IrPStackLocation-> Parameters.Deviceiocontrol.iocontrolcode;
InputBufferLength = IrpstackLocation-> Parameters.Deviceiocontrol.InputBufferLength;
OutputBufferLength = IrpstackLocation-> parameters.deviceiocontrol.outputbufferLength;
Switch (IOCONTROLCODE)
{
Case ioctl_ipfilterhook_get_firewallflags:
IF (OutputBufferLength! = Sizeof (FireWallFlags))
{
Status = status_INVALID_BUFFER_SIZE;
Break;
}
TransferSize = OutputBufferLength;
/ *
* Return to FireWallFlags
* /
RTLCopyMemory
(
TransferBuffer,
& Flirewallflags,
TRANSFERSIZE
);
Break;
Case ioctl_ipfilterhook_set_firewallflags:
IF (InputBufferLength! = Sizeof (FireWallFlags))
{
Status = status_INVALID_BUFFER_SIZE;
Break;
}
TransferSize = InputBufferLength;
/ *
* Set FireWallFlags
* /
RTLCopyMemory
(
& Flirewallflags,
TransferBuffer,
TRANSFERSIZE
);
Break;
DEFAULT:
Status = status_INVALID_DEVICE_REQUEST;
Break;
}
/ *
* Now Complete THE IRP
* /
IRP-> iostatus.status = status;
IRP-> iostatus.information = transportsize;
IOCOMPLETEREQUEST (IRP, IO_NO_INCREMENT);
Return (status);
} / * End of ifdispatchDeviceControl * /
Static NTSTATUS IFHDOHOHOK (PacketFilterextensionPtr FWFUNC)
{
NTSTATUS STATUS;
Unicode_string deficename;
PDEvice_Object DeviceObject;
Pfile_Object fileObject = null;
PIRP IRP = NULL;
Pf_set_extension_hook_info hookinfo;
IO_STATUS_BLOCK IOSTATUSBLOCK;
RTLINITUNICODESTRING (& DeviceName, DD_IPFLTRDRVR_DEVICE_NAME); / *
* NTSTATUS IOGETDEVICEOBJECTPOINTER
*
* In Punicode_String ObjectName,
* In Access_mask desiredAccess,
* OUT PFILE_OBJECT * FileObject,
* OUT PDEVICE_OBJECT * DEVICEOBJECT
*);
* /
Status = IOGETDEVICEOBJECTPOINTER
(
& DeviceName,
SYNCHRONIZE | generic_read | generic_write,
& FileObject,
& DeviceObject
);
IF (! NT_Success (status))
{
Kdprint ("IOGETDEVICEOBJECTPOITER () FAILED / N"));
Goto ifhdohook_exit;
}
Hookinfo.extensionPointer = fwfunc;
/ *
* PirP IobuildDeviceIocontrolRequest
*
* In Ulong IoControlcode,
* In PDEvice_Object DeviceObject,
* In pvoid InputBuffer Optional,
* In Ulong InputBufferLength,
* Out Pvoid OutputBuffer Optional,
* In Ulong OutputBufferlength,
* In Boolean InternalDeviceioControl,
* In Pkevent Event,
* OUT PIO_STATUS_BLOCK IOSTATUSBLOCK
*);
* /
Irp = IOBUILDDEVICEIOCONTROLREQUEST
(
IOCTL_PF_SET_EXTENSION_POINTER,
DEVICEOBJECT,
& hookinfo,
Sizeof (HookInfo),
NULL,
0,
False,
NULL,
& Iostatusblock
);
IF (NULL == IRP)
{
STATUS = iostatusblock.status;
Kdprint ("IOBUILDDEVICEIOCONTROLREQUEST () FAILED / N"));
Goto ifhdohook_exit;
}
/ *
* NTSTATUS IOCALLDRIVER
*
* In PDEvice_Object DeviceObject,
* In Out PirP IRP
*);
* /
Status = IocallDriver
(
DEVICEOBJECT,
IRP
);
IF (! NT_Success (status))
{
KDPRINT (("IocallDriver () failed / n"));
/ *
* IRPS CREATED USING IOBUILDDEVICEIOCONTROLREQUEST MUST BE Completed
* by calling ocompleterequest and not by merely deallocating the IRP
* with IOFREEIRP.
* /
IRP = NULL;
IFHDOHOK_EXIT:
IF (NULL! = fileObject)
{
ObdereferenceObject (fileObject);
FileObject = NULL;
}
Return (status);
} / * End of ifhdohook * /
Static void ifdriverunload
(
In PDRIVER_OBJECT DriverObject
)
{
PDEvice_Object NextDeviceObject;
PDEvice_EXTENSION DEVICEEXTENSITION;
KDPRINT ("Entering ifhdriverunload () / n")));
/ *
* Loop THROUGH Each Device Controlled by Driver
* /
NextDeviceObject = driverObject-> deviceObject;
/ *
* This is a single-way non-circular chain list
* /
While (NextDeviceObject)
{
/ *
* Dig Out the device extension from the device object
* /
DeviceExtension = (PDEvice_extension) NextDeviceObject-> DeviceExtension;
NextDeviceObject = nextDeviceObject-> nextdevice;
Ifdeletedevice (DeviceExtension-> DeviceObject);
} / * End of while * /
/ *
* Clear the callback function
* /
IF (! nt_success (ifhdohook (null))
{
KDPRINT ("IFHDOHOK (NULL) FAILED / N")))
}
Return;
} / * End of ifhdriverunload * /
/ *
* Don't know if the process reaches this callback function, have you have done some inspections, safely, or
* Do some tests.
* /
Static pf_forward_action ifhfirewall
(
In unsigned char * packetheader,
In unsigned char * packet,
/ *
* This size does not include the size of the ip header
* /
In unsigned int packetlength,
In unsigned int recvinterfaceIndex,
In unsigned int sendInterfaceIndex,
In ipaddr recvlinknexthop,
In ipaddr sendlinknexthop
)
{
/ *
* The principle is that if it is not explicit, it is allowed, and a machine for the user-state packet filtering api
* meeting.
* /
Pf_forward_action action = pf_pass; / *
* IP header data is definitely in place
* /
Struct ipheader * iPh = (struct ipheader *) packetheader;
Struct TCPHEADER * TCPH = (struct tcpheader *) packet;
IF
(
(Ipproto_icmp == iph-> ip_p) &&
(! (FireWallFlags & FireWallFlags_allicmp))
)
{
/ *
* Discard all ICMP packets
* /
Action = PF_DROP;
Goto ifhfirewall_exit;
}
/ *
* For received packets, sendinterfaceIndex is set to invalid_pf_if_index
* /
IF
(
(Ipproto_tcp == iph-> ip_p) &&
(Invalid_PF_IF_Index == SendinterfaceIndex) &&
(! (FireWallFlags & FireWallFlags_inboundRST))
)
{
/ *
* Discard all received RST messages.
*
* Check if it is a valid TCP message and considers the packet sent by Raw Socket.
* /
IF (PacketLength> = Offsetof (struct tcpheader *, t_win))
{
IF (TCPH-> TH_FLAGS & TH_RST)
{
Action = PF_DROP;
}
}
}
IFHFIREWALL_EXIT:
Return (Action);
} / * End of ifhfirewall * /
/ *
* Driverentry Is The First Routine Called After a Driver is loaded, and
* Is Responsible for Initializing The Driver.
*
* You'll Find A List of Ntstatus Status Codes in The Ddk Header
* ntstatus.h (/Winddk/2600.1106/inc/ddk/wXP/)
* /
NTSTATUS DRIVERENTRY
(
In PDRIVER_OBJECT DriverObject,
In Punicode_String RegistryPath
)
{
NTSTATUS STATUS;
/ *
* kernel-mode functions and the functions in your driver user
* __stdcall calling convention1 compiled for an x86 computer.
* This kind't Affect Any of Your Programming, But It's Something
* to Bear in Mind when're debugging
*
* This Routine Has No Effect If Compiled in a Free Build Environment.
* You Should Compiled in a Checked Build Environment.
* /
Kdprint ("Entering DriveREntry () / N")); / *
* If this Driver Controlled Real Hardware, Code Would Be Placed Here
* to locate it. using ioreportDetecteddevice, The Ports, IRQs, And
* DMA Channels Would Be "Marked" AS "in use" and under the control of
* This Driver. This Ipfilterhook Driver Has No HW, So ...
* /
/ *
* Announce Other Driver Entry Points
* /
DriverObject-> driverunload = ifhdriverunload;
/ *
* This include Dispatch Routines for Create, Write & Read
* /
DriverObject-> majorfunction [IRP_MJ_CREATE] = ifhdispatchcreate;
DriverObject-> Majorfunction [IRP_MJ_DEVICE_CONTROL] = ifhdispatchDeviceControl;
DriverObject-> Majorfunction [IRP_MJ_CLOSE] = ifhdispatchclose;
/ *
* Part III Chapter 3 << Programming The Microsoft Windows Driver Model, 2nd Ed >> Chapter 3
* Section "Error Handling" section.
*
* Which Exceptions Can Be Trapped
*
* Gary Nebbett Research CAN Be Be BE Question Of Which Exceptions Can Be
* Trapped with the structured Exception Mechanism and Reported HIS
* Results in a newsgroup Post Several Years ago. in summary, the
* Following Exceptions Will Be Caught When The Occur At Irql Less
* Than or equal to dispatch_level (Note That Some of these Are
* Specific to the intel x86 processor:
*
* a. Anything Signaled by ExraisesTatus and Related Functions
* b. Attempt to Dereference Invalid Pointer to User-Mode Memory
* c. Debug or breakpoint exception
* d. Integer overflow (INTO INSTRUCTION)
* e. invalid opcode
*
* Note That a reason to an invalid kernel-mode Pointer Leads
* Directly to a bug check and can't be trapped. Likewise, A
* Divide-by-zero exception or a bound instruction exception leads to * a bug check.
*
* Sustain, or use the SEH mechanism, try to avoid debugging.
* /
__TRY
{
Kdprint (("You Should See Message [0] / N"));
/ *
* Set the callback function
* /
Status = ifhdohook (ifhfirewall);
IF (! NT_Success (status))
{
Kdprint ("IFHDOHFIREWALL) FAILED / N")))
}
Else
{
/ *
* For Each Physical or Logical Device Detected That Will BE Under
* This Driver's Control, A New Device Object Must Be CREATED.
*
* This Call Would Be Repeated Until All Devices Are Created.
*
* We only created one device object here.
* /
Status = ifhcreateDevice
(
DriverObject,
0
);
}
KDPRINT (("You Should See Message [1] / N"));
}
__EXCEPT (Exception_execute_Handler)
{
KDPRINT (("__Except {} / n"))))
Status = status_unsuccessful;
}
Kdprint ("EXITING DRIVERENTRY () / N"))
Return (status);
} / * End of driverentry * /
/ ************************************************** ********************** /
-------------------------------------------------- ---------------------------------------------------------------------------------------------------------------------------------------
2) DIRS
DIRS = CODE
3) Sources
-------------------------------------------------- ---------------------------------------------------------------------------------------------------------------------------------------
#
# Use the targetname macro to specify the name of the library to be built.
# Do not include the file name extension
#
TargetName = ipflthookdrv
#
# All build products (Such as .exe, .dll, and .lib files) Will Be Placed
# in this Directory
#
# Build_alt_dir's value will be appended behind TargetPath, if you suspect that build_alt_dir is too eye,
# You can delete the environment variable.
#
TargetPath = OBJ
#
# Use the targettype macro to specify the Type of Product Being Built.
# TargetType Gives The Build Utility Clues About Some of the Input Files
# That it soould. You must incrude this macro in your source. # # # # # # # # # # # # # #
Targettype = driver
#
# Use the us_pdb macro if your debug symbolic files will use a vc4 PDB.
# This is the default in the windows xp Build Environment.
#
USE_PDB = 1
#
# Use the includees macro to indeicate the location of the headers to becoming
# included in your build
#
Includes =
#
# Use the msc_warning_level macro to set the warning level to use on
# Compiler. The default IS / w3.
#
#After Your Code Builds without Errors, You Might Want To Change
# Msc_warning_level to / w3 / wx. Setting this value causes warnings to show
# as errors.
#
MSC_warning_level = -w3 -wx
#
# The Sources Macro Specifier The Files To Be Compiled. The Sources Macro
# Is Required by the build utility. this macro must be placed in Your
# Sourcees file. All files specified by this macro must reside in
# Directory Containing The Sources File.
#
Sources = ipflthookdrv.c
-------------------------------------------------- ---------------------------------------------------------------------------------------------------------------------------------------
4) Makefile
Include $ (NTMAKEENV) /MAKEFILE.DEF
Suppose it enters "Win XP Checked Build Environment":
J: / source / driver / ipflthookdrv> set build_alt_dir
Build_alt_dir = chK_WXP_X86
J: / source / driver / ipflthookdrv> Tree / F / A
IpfltHookDRV
| DIRS
|
/ --- Code
INSTALLDRIVER.C
IpfltHookDrv.c
IpfltHookDrvtest.c
Makefile
Sources
J: / source / driver / ipflthookdrv> Build -cz -x86
5) InstallDriver.c
IpFilterhook relies on IPfilterDriver, you need to modify it for easy installation of IPFilTerhook.
INSTALLDRIVER.C. That is to call CREATSERVICE () to specify dependencies.
LPDependencies
Pointing a buffer such as "AAAA / 0BBB / 0cccc / 0/0" buffer. In order to simplify the processing of installDriver.c,
Requires [-P Dependencies] Dependencies, such as "AAAA, BBBB, CCCC, / 0".
-------------------------------------------------- ------------------------ / *
* Version: 1.10
* Compile: for x86 / ewindows XP SP1 & VC 7
*: CL InstallDriver.c / NOLOGO / OS / G6 / GZ / GS65536 / W3 / WX / D "WIN32" / D "NDEBUG" / D "_console" / link / transase
*:
* Create: 2003-12-08 16:47
* Modify: 2004-07-15 18:26
* /
/ ************************************************** **********************
* *
* Head file *
* *
*********************************************************** ********************* /
/ *
* #define _win32_winnt 0x0501
* /
#include
#include
#include
#include
/ ************************************************** **********************
* *
* Macro *
* *
*********************************************************** ********************* /
#pragma comment (Linker, "/ Incremental: no")
#pragma comment (Linker, "/ subsisystem: console")
#pragma comment (lib, "kernel32.lib")
#pragma comment (Lib, "Advapi32.lib")
#define Version "1.10"
/ ************************************************** **********************
* *
* Function Prototype *
* ********************************************************** *********************** /
Static void Printwin32errorCli
(
Char * message,
DWORD dwmessageid
);
Static void usage
(
Char * arg
);
/ ************************************************** **********************
* *
* Static global var *
* *
*********************************************************** ********************* /
/ ************************************************** ********************** /
Static void Printwin32error (Char * Message, DWORD DWMESSAGEID)
{
Char * errmsg;
FormatMessage
(
FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
NULL,
DwMessageID,
Makelangid (Lang_neutral, SUBLANG_DEFAULT),
(Lptstr) & errmsg,
0,
NULL
);
FPRINTF (stderr, "% s:% s", message, errmsg;
Localfree (errmsg);
Return;
} / * End of printwin32errorcli * /
Static Void Usage (Char * Arg)
{
FPRINTF
(
STDERR,
"USAGE:% s [-h] [-v] [-t target] [-S serviceename] / n"
"[-C cmdline] [-P dependencies] / N",
arg
);
EXIT (exit_failure);
} / * End of usage * /
INT __CDECL Main (int Argc, char * argv [])
{
SC_HANDLE SCM = (SC_HANDLE) NULL,
SC_HANDLE = (sc_handle) NULL;
Unsigned char * target = null,
* Servicename = NULL,
* DisplayName = NULL,
* cmdline = NULL,
* Dependencies = NULL,
* P;
INT C,
Ret = exit_failure;
IF (1 == argc) {
USAGE (Argv [0]);
}
/ *
* Start loop processing command line parameters from Argv [1]
* /
FOR (c = 1; c { / * * Simultaneously support - and / two ways to introduce command line parameters * / IF (((Argv [C]! = '-') && (Argv [C] [0]! = ')) || (Strlen (Argv [C]) <2)) { USAGE (Argv [0]); } Else { / * * On this byte, case sensitive * / Switch (TOLOWER (Argv [C] [1])) { Case 'C': IF ((C 1)> = argc) { USAGE (Argv [0]); } CMDLINE = Argv [ C]; Break; Case 'd': IF ((C 1)> = argc) { USAGE (Argv [0]); } DisplayName = Argv [ C]; Break; Case 'P': IF ((C 1)> = argc) { USAGE (Argv [0]); } Dependencies = argv [ c]; Break; Case 's': IF ((C 1)> = argc) { USAGE (Argv [0]); } ServiceName = Argv [ C]; Break; Case 'T': IF ((C 1)> = argc) { USAGE (Argv [0]); } Target = Argv [ C]; Break; Case 'V': FPRINTF (stderr, "% s ver" version "/ n", argv [0]); Return (exit_success); Case 'h': Case '?': DEFAULT: USAGE (Argv [0]); Break; } / * End of switch * / } } / * End of for * / / * * Check parameter validity * / IF (null == serviceename) { FPRINTF (stderr, "checking your [-s serviceename] / n"); Return (exit_failure); } IF (NULL == DisplayName) { FPRINTF (stderr, "checking your [-d displayName] / n"); Return (exit_failure); } IF (null == cmdline) { FPRINTF (stderr, "checking your [-c cmdline] / n"); Return (exit_failure); } / * * Header: declared in winsvc.h; incrude windows.h. * Library: USE Advapi32.lib. * * SC_Handle OpenScManager * * LPCTSTR LPMACHINENAME, / / COMPUTER NAME * LPCTSTR LPDATABASENAME, / / SCM Database Name * DWORD DWDESIREDACCESS // Access Type *); * * The first ginseng can use Target or // * / SCM = OpenScManager ( Target, Services_Active_Database, SC_Manager_create_Service ); IF (NULL == SCM) { PrintWin32error ("OpenScManager () Failed, getLastError ()); Goto main_exit; } / * * Requires the end of each service name with a comma * / IF (NULL! = dependencies) { P = dependencies; While (* p) { IF (',' == * P) { * p = '/ 0'; } P ; } / * End of while * / } / * * SC_Handle CreateService * * SC_Handle Hscmanager, // Handle to SCM Database * LPCTSTR LPSERVICENAME, // Name of Service to Start * Lpctstr lpdisplayName, // Display name * DWORD DWDESIREDACCESS, // Type of Access To Service * DWORD DWSERVICEPE, // TYPE OF SERVICE * DWORD DWSTARTTYPE, // When to Start Service * DWORD DWERRORCONTROL, // Severity of Service Failure * Lpctstr lpbinaryPathname, // name of binary file * Lpctstr lplandordergroup, // name of loading Ordering Group * LPDWORD LPDWTAGID, / / TAG IDENTIFIER * LPCTSTR LPDependencies, // Array of Dependency Names * LPCTSTR LPSERVICESTARTNAME, // Account Name * Lpctstr lpassword // Account Password *); * / SC_HANDE = CREATSERVICE ( SCM, Servicename, DisplayName, SERVICE_ALL_ACCESS, Service_kernel_driver, Service_demand_start, Service_ERROR_NORMAL, CMDLINE, NULL, NULL, Dependencies, NULL, NULL ); IF (NULL == SC_HANDLE) { Printwin32erRorCli ("CreateService () Failed, getLastError ()); Goto main_exit; } RET = EXIT_SUCCESS; Main_exit: IF (NULL! = SC_HANDLE) { ClosESERVICEHANDLE (SC_HANDLE); SC_HANDLE = (sc_handle) NULL; } IF (NULL! = SCM) { ClosEServiceHandle (SCM); SCM = (SC_HANDLE) NULL; } Return (RET); } / * End of main * / / ************************************************** ********************** / -------------------------------------------------- --------------------------------------------------------------------------------------------------------------------------------------- Example: > InstallDriver.exe -s ipfilterhook -d ipfilterhook -c c: /onlytemp/ipflthookdrv.sys -p ipfilterdriver, This installation is much dependent compared to installing loopback.sys: -------------------------------------------------- --------------------------------------------------------------------------------------------------------------------------------------- Windows Registry Editor Version 5.00 [HKEY_LOCAL_MACHINE / SYSTEM / CURRENTCONTROLSET / SERVICES / IPFILTERHOOK] "Dependonservice" = HEX (7): 49,00, 70,00, 46, 0, 69, 100, 6c, 00, 74, 100, 65, 0, 72, 0, 44, 00, / 72,00, 69,00, 76,00, 65,00, 72,00,00,00,00 "Dependongroup" = HEX (7): 00, 00 -------------------------------------------------- --------------------------------------------------------------------------------------------------------------------------------------- 6) ipflthookdrvtest.c This program is used to set the flag FireWallFlags used by the callback function and display the value of the flag before and after the setting. Discard all ICMP packets, including reception, send two situations, discard the received RST packet ipflthookdrvtest.exe -f 0 Don't make any filter ipflthookdrvtest.exe Just discard all ICMP packets ipflthookdrvtest.exe -f 0xffffe Just discard the received RST message ipflthookdrvtest.exe -f 0xffffffd -------------------------------------------------- --------------------------------------------------------------------------------------------------------------------------------------- / * * For x86 / ewindows XP SP1 & VC 7 * CL ipflthookdrvtest.c / nologo / os / g6 / gz / gs65536 / w3 / wx / d "win32" / d "ndebug" / d "_console" / link / release * / / ************************************************** ********************** * * * Head file * * * *********************************************************** ********************* / / * * #define _win32_winnt 0x0501 * / #include #include #include #include / * * Use the CTL_CODE macro * / #include / ************************************************** ********************** * * * Macro * * * *********************************************************** ********************* / #pragma comment (Linker, "/ Incremental: no") #pragma comment (Linker, "/ subsisystem: console") #define version "1.00" #define externalName ".//IPFilTerhookexternal1" / * * 0x0800 is the minimum usable value * / #define ipfilterhook_index 0x0800 #define ioctl_ipfilterhook_get_firewallflags CTL_CODE / (/ FILE_DEVICE_NETWORK, / IPFilTerhook_index 0, / Method_buffered, / FILE_READ_ACCESS / #define ioctl_ipfilterhook_set_firewallflags CTL_CODE / (/ FILE_DEVICE_NETWORK, / IPFilTerhook_index 1, / Method_buffered, / FILE_WRITE_ACCESS / ) / * * Set - enable * Reset - Disable * / #define firewallflags_disableAll 0x00000000 / * * All ICMP packets, including reception, send * / #DEFINE FIREWALLFLAGS_ALLICMP 0x00000001 / * * Received RST packet * / #define firewallflags_inboundrst 0x00000002 #define fireflags_enableall 0xfffffffff / * * The default setting is all allowed, that is, do not discard any packets * / #define fireflags_default firewallflags_enableAll / ************************************************** ********************** * * * Function Prototype * * * *********************************************************** ********************* / Static void Printwin32errorCli ( Char * message, DWORD dwmessageid ); Static void usage ( Char * arg ); / ************************************************** ********************** * * * Static global var * * * *********************************************************** ********************* / / ************************************************** ******************************** / Static Void Printwin32error (Char * Message, DWMESSAGEID) { Char * errmsg; FormatMessage ( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, NULL, DwMessageID, Makelangid (Lang_neutral, SUBLANG_DEFAULT), (Lptstr) & errmsg, 0, NULL ); FPRINTF (stderr, "% s:% s", message, errmsg; Localfree (errmsg); Return; } / * End of printwin32errorcli * / Static Void Usage (Char * Arg) { FPRINTF ( STDERR, "USAGE:% s [-h] [-v] [-f firewallflags] / N", arg ); EXIT (exit_failure); } / * End of usage * / INT __CDECL Main (int Argc, char * argv []) { INT C, Ret = exit_failure; Handle device = invalid_handle_value; Ulong fireflags = firewallflags_default; Ulong OrigfireWallFlags; DWORD BYTESRETURNED; #if 0 IF (1 == argc) { USAGE (Argv [0]); } #ENDIF / * * Start loop processing command line parameters from Argv [1] * / FOR (c = 1; c { / * * Simultaneously support - and / two ways to introduce command line parameters * / IF (((Argv [C]! = '-') && (Argv [C] [0]! = ')) || (Strlen (Argv [C]) <2)) { USAGE (Argv [0]); } Else { / * * On this byte, case sensitive * / Switch (TOLOWER (Argv [C] [1])) { Case 'f': IF ((C 1)> = argc) { USAGE (Argv [0]); } FireWallFlags = Strtoul (Argv [ C], NULL, 0); Break; Case 'V': FPRINTF (stderr, "% s ver" version "/ n", argv [0]); Return (exit_success); Case 'h': Case '?': DEFAULT: USAGE (Argv [0]); Break; } / * End of switch * / } } / * End of for * / / * * Handle Createfile * * LPCTSTR LPFILENAME, / / FILE Name * DWORD DWDESIREDACCESS, // Access Mode * DWORD DWSHAREMODE, // Share Mode * Lpsecurity_attributes lpsecurityattributes, // sd * DWORD dwcreationdisposition, // how to create * DWORD DWFLAGSANDATTRIBUTES, / / File Attributes * Handle HTemplateFile // Handle to Template File *); * * If the function fails, the return value is invalid_handle_value. To * Get Extended Error Information, Call GetLastError. * / Device = Createfile ( ExternalName, Generic_read | generic_write, 0, Null, // if lpsecurityattributes is null, the handle cannot be inherited Open_existing, // The function fails if the file does not exist FILE_ATTRIBUTE_NORMAL, NULL ); IF (Invalid_Handle_Value == Device) { Printwin32error ("CreateFile () failed, getLastError ()); Goto main_exit; } / * * Bool Deviceiocontrol * * Handle HDevice, * DWORD DWIOCONTROLCODE, * LPVOID LPINBUFFER, * DWORD NINBUFFERSIZE, * LPVOID LPOUTBUFFER, * DWORD NOUTBUFFERSIZE, * LPDWORD LPBYTESRETURNED, * LPOVERLAPPED LPOVERLAPPED *); * / IF ( False == DeviceIocontrol ( DEVICE, IOCTL_IPFILTERHOK_GET_FIREWALLFLAGS, NULL, 0, & OrigfireWallFlags, SizeOf (OrigfireWallFlags), & BytesReturned, NULL ) ) { Printwin32erRorCli ("Deviceiocontrol (Get) for OrigfireWallFlags Failed, getLastError ()); Goto main_exit; } Printf ("OrigfireWallFlags = 0x% 08X / N", OrigfireWallFlags; if ( False == DeviceIocontrol ( DEVICE, IOCTL_IPFILTERHOK_SET_FIREWALLFLAGS, & Flirewallflags, Sizeof (FireWallFlags), NULL, 0, & BytesReturned, NULL ) ) { Printwin32erRorCli ("DeviceioControl (SET) FAILED, GetLastError ()); Goto main_exit; } IF ( False == DeviceIocontrol ( DEVICE, IOCTL_IPFILTERHOK_GET_FIREWALLFLAGS, NULL, 0, & Flirewallflags, Sizeof (FireWallFlags), & BytesReturned, NULL ) ) { Printwin32error ("DeviceioControl (GET) for FireWallFlags Failed, getLastError ()); Goto main_exit; } Printf ("firewallflags = 0x% 08x / n", firewallflags; RET = EXIT_SUCCESS; Main_exit: IF (Invalid_Handle_Value! = Device) { CloseHandle (Device); Device = invalid_handle_value; } Return (RET); } / * End of main * / / ************************************************** ********************** / -------------------------------------------------- --------------------------------------------------------------------------------------------------------------------------------------- 7) Verification effect Copy IPFLTHOKDRV.C, IPFLTHOKDRV.PDB, IPFLTHOOKDRV.SYS to VMware Guest In a directory, such as ONLYTEMP. Install IPFLTHOOKDRV.SYS with InstallDriver.exe. InstallDriver.exe -s ipfilterhook -d ipfilterhook -c c: /onlytemp/ipflthookdrv.sys -p ipfilterdriver, Since IPFilTerhook depends on IPFilterDriver, this time you should specify dependencies, otherwise the total test is always To manually start IPFilterDriver in advance. Now specify the dependencies, you can launch IPFilTerhook directly. The system checks the dependencies and automatically launches IPFilterDriver. If you need to use Softice to make source code debugging for IPFLTHOKDRV.SYS, use the following command: NMSYM.EXE / Translate: Always, Source, package /output:ipflthookdrv.ns ipflthookdrv.sys NMSYM.EXE /SYMLOAD: IPFLTHOOKDRV.NMS NMSYM.EXE /UNLOAD: IPFLTHOOKDRV.NMS This time I was lucky, I didn't collapse, and I got one time. Generally speaking, you should use the Sync.exe tool to refresh the disk buffer before testing, prevent data loss, damage your hard disk, and so on. > SC Queryex IPFilterhook Service_name: ipfilterhook TYPE: 1 KERNEL_DRIVER State: 1 stopped (Not_Stoppable, Not_Pausable, Ignores_Shutdown) WIN32_EXIT_CODE: 0 (0x0) SERVICE_EXIT_CODE: 0 (0x0) Checkpoint: 0x0 WAIT_HINT: 0X0 PID: 0 Flags: > SC Queryex IPFilterDriver Service_name: ipfilterdriver TYPE: 1 KERNEL_DRIVER State: 1 stopped (Not_Stoppable, Not_Pausable, Ignores_Shutdown) WIN32_EXIT_CODE: 0 (0x0) SERVICE_EXIT_CODE: 0 (0x0) Checkpoint: 0x0 WAIT_HINT: 0X0 PID: 0 Flags: > SC ENUMDEPEND IPFILTERDRIVER (rely, this command is actually an enumeration who relies on ipfilterdriver) ENUM: EntriesRead = 1 Service_name: ipfilterhook Display_name: ipfilterhook TYPE: 1 KERNEL_DRIVER State: 1 stopped (Not_Stoppable, Not_Pausable, Ignores_Shutdown) WIN32_EXIT_CODE: 0 (0x0) SERVICE_EXIT_CODE: 0 (0x0) Checkpoint: 0x0 WAIT_HINT: 0X0 > NET Start Ipfilterhook The ipfilterhook service is started successful. Let's introduce how to verify the firewall role: Just discard all ICMP packets > ipflthookdrvtest.exe -f 0xffffffe Origfirewallflags = 0xfffffffff FireWallFlags = 0xffffffe From this machine PING other machine > ping 192.168.7.254 General failure. General failure. General failure. General failure. From another machine ping native > ping 192.168.7.152 Request timed out. Request timed out. Request timed out. Request timed out. Ping from this unit > ping 127.0.0.1 General failure. General failure. General failure. General failure. Just discard the received RST message > ipflthookdrvtest.exe -f 0xffffffffdorigFireWallFLAGS = 0xffffffe FireWallFlags = 0xffffffd > Telnet 192.168.7.100 1 From the port of the machine Telnet other machine, the RST packet received by the alternative response according to the constant reason. That is, but because the firewall discards this RST message, the TCP / IP protocol stack does not get RST reports. Text, resulting in the TCP finite state machine for a long time to remain in the SYN_SENT state until the TCB is destroyed until the timeout. It is difficult to see the SYN_SENT state in the interaction. > NetStat -na | Find / I "SYN_SENT" TCP 192.168.7.152:1038 192.168.7.100:1 SYN_SENT The verification process can be mounted with a Sniffer. Uninstall IPFilTerhook after verification: > NET STOP IPFILTERDRIVER The Following Services Are Dependent on The IP Traffic Filter Driver Service. Stopping The IP Traffic Filter Driver Service Will Also Stop these Services. Ipfilterhook Do you want to continche this operation? (Y / n) [N]: Y The ipfilterhook service is stopped successful. The IP Traffic Filter Driver Service Was Stopped SuccessFully. > SC Delete IPfilterhook [Sc] deleteService SUCCESS ☆ Reference resources [1] Network Devices and Protocols: Windows DDK Filter-Hook Driver Design Guide Network Devices and Protocols: Windows DDK Filter-Hook Driver Reference [2] << The Windows 2000 Device Driver Book, Second Edition >> - Art Baker, Jerry Lozano