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.