Firewall
We now teach you how to
build a firewall. A firewall is nothing but a device driver that prevents
network packets from reaching our Operating system. We will write a simple
device driver that prevents ICMP packets from reaching our OS. We will drop all
ping packets that arrive at our OS.
What we can do from ICMP, we can do for all network protocols.
We start with creating a
directory driver1 in C: and first create the file y.c that will load and unload
our device driver.
y.c
#include <windows.h>
SC_HANDLE m,s;
void main(int argc, char
**argv)
{
if ( argv[1][1] == 'i')
{
m=OpenSCManager(0,0,SC_MANAGER_ALL_ACCESS
);
CreateService(m,"vijay","mukhi",SERVICE_ALL_ACCESS,SERVICE_KERNEL_DRIVER,SERVICE_DEMAND_START,SERVICE_ERROR_NORMAL,"C:\\driver1\\vijay.sys",0,0,0,0,0);
s=OpenService(m,"vijay",SERVICE_ALL_ACCESS);
StartService(s, 0, 0);
}
else
{
SERVICE_STATUS status;
m= OpenSCManager
(0,0,SC_MANAGER_ALL_ACCESS );
s=OpenService(m,"vijay",SERVICE_ALL_ACCESS);
ControlService(s,
SERVICE_CONTROL_STOP, &status);
}
}
Our driver loading
program can be called as y –I to load and y –u to unload. We use simple service
manager functions to first Open the service manager using the function
OpenSCManager. We then use the CreateService function to create a service called
vijay and it is here that we specify that we are not looking at a normal ring 3
service but a device driver vijay.sys in C:\driver1. We then use the
OpenService function to open the service vijay and finally use the StartService function to start it. When we want
to unload the driver, we open the Sc manager, Open the service and now use the
ControlService service to stop it. To build the exe file we use z.bat.
Z.bat
del y.exe
cl y.c advapi32.lib
Same batch file we have
been using all along.
b.bat
cd \winddk\2600.1106\bin
call setenv
c:\winddk\2600.1106
cd \driver1
del r.obj
del vijay.sys
cl
-Ic:\winddk\2600.1106\inc\ddk\wxp -Ic:\winddk\2600.1106\inc\crt -D_X86_=1 /c
/Gz r.c
link -subsystem:native,5.01 -entry:DriverEntry@8 -out:vijay.sys r.obj c:\winddk\2600.1106\lib\wxp\i386\ntoskrnl.lib
To build the driver we
use the bat file b.bat. The code as always is in r.c
#include <ntddk.h>
#include <ndis.h>
#include
<ipFirewall.h>
struct IPPacket
{
UCHAR hlen:4,ver:4,tos;
USHORT len,id,frag;
UCHAR ttl,protocol;
USHORT checksum;
ULONG src,dst;
};
FORWARD_ACTION
firewallfunc(VOID **rawdata,UINT a,UINT *b, UCHAR *c,VOID *d,UINT e,struct
IPRcvBuf **f)
{
char *p;
struct IPRcvBuf *buff;
struct IPPacket *ipp;
buff =(struct IPRcvBuf *)
*rawdata;
DbgPrint("cbFilterFunction
%d",buff->ipr_size);
ipp = (struct IPPacket
*)buff->ipr_buffer;
p = (char *)ipp;
DbgPrint("%d.%d.%d.%d
--> %d.%d.%d.%d",p[12],p[13],p[14],p[15],p[16],p[17],p[18],p[19]);
if(ipp->protocol == 1)
return DROP;
return FORWARD;
}
NTSTATUS ActivateFirewall(int
activate)
{
UNICODE_STRING fname;
PDEVICE_OBJECT device;
PFILE_OBJECT file;
IP_SET_FIREWALL_HOOK_INFO
hook;
PIRP irp;
RtlInitUnicodeString(&fname,
L"\\Device\\Ip");
DbgPrint("SetFilterFunction
%S",fname.Buffer);
IoGetDeviceObjectPointer
(&fname,STANDARD_RIGHTS_ALL, &file, &device);
hook. FirewallPtr = firewallfunc;
hook.Add = activate;
irp =
IoBuildDeviceIoControlRequest (IOCTL_IP_SET_FIREWALL_HOOK,device,(PVOID)
&hook,sizeof(hook),0,0,0,0,0);
IoCallDriver(device,
irp);
return STATUS_SUCCESS;
}
void
UnloadDriver(PDRIVER_OBJECT d)
{
DbgPrint("Unloading
driver");
ActivateFirewall(FALSE);
}
NTSTATUS DriverEntry
(PDRIVER_OBJECT d,PUNICODE_STRING r)
{
DbgPrint("Vijay1");
d-> DriverUnload =
UnloadDriver;
ActivateFirewall (TRUE);
return STATUS_SUCCESS;
}
We are now writing a
firewall driver which to start with is a driver that like all other drivers has
a DriverEntry function. Here we simply set the DriverUnload member to
UnloadDriver which will
be called when we unload our driver. We do not create any links but call a
function ActivateFirewall that sets our device driver to act as a firewall.
We initialize fname with
a Unicode string \Device\Ip and then get a handle to this device name in the
device structure using the IoGetDeviceObjectPointer function. We then place the
address of our function firewallfunc in the FirewallPtr member of the hook structure that we want to
be called each time a packet arrives on our network card. By setting the Add
member of the hook structure to true or 1 we are activating the function, 0
means do not call the function any more. All that we now need to do is use the
IoBuildDeviceIoControlRequest to build an IRP which can be send across to the
device driver \Device\Ip. The ioctl associated with the IRP is IOCTL_IP_SET_FIREWALL_HOOK.
The IoCallDriver will send the Irp across to the device driver whose handle is
stored in the device object. From now on every time a packet arrives at the
network card, our function firewallfunc will get called. The first parameter is
a pointer to a structure IPRcvBuf. This has two members that interest us.
Ipr_size that has the size of the packet and irp_buffer that points to
the actual data. We set two pointers to this buffer variable. The char * is
used to display the IP address in dotted decimal, the ipp pointer points to an
actual IP header. If the packet is ICMP the protocol member will be 1, we
return an enum DROP that has a value 1. Whenever the original drive receives
this value, it does not send the packet to the OS. If it receives a zero, it
means that we want the driver to forward it to the next driver in the chain or
to the OS running in ring 3. This is how easy it is to implement a firewall as
a device driver. Simply send the Ip device driver the address of a function to
be called. This function will now return a DROP or FORWARD depending upon
whether it wants others to see the packet. Setting the Add member to 0 in
Driver Unload will stop our function from being called.