IP过滤-驱动和应用程序通信
前段时间写一个IP过滤的驱动,以前没有接触过驱动,Google一把,网上有很多例子,不过都不能满足自己的需求,所以就参考大家的资料自己研究一下。呵呵。程序用了三层:第一层就是驱动来负责过滤数据包并把拦截的结果返回给应用程序。第二层VC动态链接库来负责加载卸载驱动,和驱动通信。并提供接口给第三层调用。第三层C#Winform,调用VC动态链接库提供的接口,间接和驱动通信,并显示驱动返回结果。
用到最多的就是DeviceIoControl这个函数,可以通过这个函数向驱动程序发送消息,还可以从驱动程序获取消息,下面让我们来看一下这个函数的结构吧:
BOOL DeviceIoControl( HANDLE hDevice, //创建的驱动设备句柄 DWORD dwIoControlCode, //应用程序调用驱动程序的控制命令 LPVOID lpInBuffer, //应用程序传递给驱动程序的数据缓冲区地址 DWORD nInBufferSize, //应用程序传递给驱动程序的数据缓冲区大小,字节数 LPVOID lpOutBuffer, //驱动程序返回给应用程序的数据缓冲区地址 DWORD nOutBufferSize, //驱动程序返回给应用程序的数据缓冲区大小,字节数 LPDWORD lpBytesReturned, //驱动程序实际返回给应用程序的数据字节数地址 LPOVERLAPPED lpOverlapped//重叠操作结构 一般设为NULL );
向驱动发消息:
DWORD WriteIo(DWORD code, PVOID buffer, DWORD count)
{
if(driverHandle == NULL)
return DRV_ERROR_INVALID_HANDLE;
DWORD bytesReturned;
BOOL returnCode = DeviceIoControl(driverHandle,
code,
buffer,
count,
NULL,
0,
&bytesReturned,
NULL);
if(!returnCode)
return DRV_ERROR_IO;
return DRV_SUCCESS;
}
从驱动获取消息:
DWORD ReadIo(DWORD code, PVOID buffer, DWORD count)
{
if(driverHandle == NULL)
return DRV_ERROR_INVALID_HANDLE;
DWORD bytesReturned;
BOOL retCode = DeviceIoControl(driverHandle,
code,
NULL,
0,
buffer,
count,
&bytesReturned,
NULL);
if(!retCode)
return DRV_ERROR_IO;
return DRV_SUCCESS;
}
有了这两个函数我们就可以向驱动发消息和从驱动获取数据了。我们可以通过Writeto 把要添加或删除的Ip过滤规则发给驱动程序。下一步我们要做的就是当驱动拦截到添加的IP过滤规则后怎么通知应用程序。这里用到了CreateEvent,然后把这个m_hCommEvent 通过Writeto 通知给驱动,
BOOL CreateFilterEvent(DWORD code)
{
m_hCommEvent= CreateEvent(NULL, false, false, NULL);
if(driverHandle == NULL)
{
MessageBox(NULL,TEXT("driverHandle is null"),NULL,MB_OK);
//return FALSE;
}
DWORD dwReturn;
//download event object to device driver
BOOL retCode = DeviceIoControl(driverHandle,
code,
&m_hCommEvent,
sizeof(m_hCommEvent),
NULL,
0,
&dwReturn,
NULL);
if(retCode)
{
return TRUE;
}
else
{
return FALSE;
}
}
然后通过CreateThread创建一下线程来接受驱动的消息,
在线程函数里写:
while(threadFlag)
{
if(m_hCommEvent)
{
WaitForSingleObject(m_hCommEvent,INFINITE);
//收到驱动的通知
//从驱动取数据
//通知C#窗体
ResetEvent(m_hCommEvent);
}
}
驱动里做一下处理:
HANDLE hEvent =*(PHANDLE)ioBuffer;
NTSTATUS status = ObReferenceObjectByHandle(
hEvent,
GENERIC_ALL,
NULL,
KernelMode,
&gpEventObject,
&objHandleInfo);
if(!NT_SUCCESS(status))
{
if(gpEventObject)
{
ObDereferenceObject(gpEventObject);
}
if(hEvent)
{
}
Irp->IoStatus.Status=STATUS_UNSUCCESSFUL;
}
if(status != STATUS_SUCCESS)
{
DbgPrint("ObReferenceObjectByHandle failed! status = %x\n", status);
Irp->IoStatus.Status=STATUS_UNSUCCESSFUL;
break;
}
当驱动拦截到过滤的IP数据包的时候:
if(gpEventObject)
{
//一个变量赋值等应用程序收到通知的时候来去这个数据
KeSetEvent(gpEventObject, 0,FALSE);//by Fs.song
}
只是程序记录。