驅動開發之四:NDIS過濾鉤子驅動實現ip包過濾

來源:互聯網
上載者:User
作者:FLASHSKY
EMAIL:flashsky@xfocus.org
網站:www.xfocus.net www.shopsky.com
轉載請註明原作者安全焦點

在普通的WINDOWS 2000下實現實現包過濾的方法主要是書寫NDIS過濾驅動程式,需要的技巧比較高,而且煩瑣,需要考慮很多細節。但是對於很多應用而言,只需要能更方便的對ip包進行過濾處理,其實NDIS對於ip包的過濾提供一種書寫過濾鉤子驅動的方式,主要方法是:
驅動中建立一個普通的裝置,然後通過IOCTL_PF_SET_EXTENSION_POINTER操作將你的核心模式的過濾鉤子掛接到系統預設的ip過濾驅動上,這樣你就可以在自己的過濾鉤子裡面實現完整的基於包的各種分析和過濾的處理了。
下面就是一個完整的NDIS過濾鉤子驅動的代碼拒絕所有外來的TCP帶S的建立串連的請求。
注意事項:
1。需要在DDK環境中編譯
2。需要修改註冊表中LMHK/System//CurrentControlSet//Services//IPFILTERDRIVER的START類型為3,讓他隨系統啟動而啟動
3。編譯產生了sys檔案後需要拷貝到winnt/system32/drivers目錄下
4。需要運行一個程式後手動產生登錄機碼
5。使用時用net start fxfilthook啟動驅動,用net stop fxfilthook停止驅動
6。此方法只能對ip包進行過濾,其他的協議不會經過這個過濾鉤子進行處理。

//驅動程式的標頭檔
#include "ntddk.h"
#include "ntddndis.h"
#include "pfhook.h"
#ifndef __NTHANDLE_H
#define __NTHANDLE_H

#define NT_DEVICE_NAME L"//Device//Fxfilthook"
#define DOS_DEVICE_NAME L"//DosDevices//Fxfilthook"

#define PROT_TCP 6

#include "ntddk.h"
#include "xfilthook.h"

typedef struct IPHeader {
UCHAR iph_verlen; // Version and length
UCHAR iph_tos; // Type of service
USHORT iph_length; // Total datagram length
USHORT iph_id; // Identification
USHORT iph_offset; // Flags, fragment offset
UCHAR iph_ttl; // Time to live
UCHAR iph_protocol; // Protocol
USHORT iph_xsum; // Header checksum
ULONG iph_src; // Source address
ULONG iph_dest; // Destination address
} IPHeader;

NTSTATUS
DriverEntry(
IN PDRIVER_OBJECT DriverObject,
IN PUNICODE_STRING RegistryPath);

NTSTATUS
CreateFilterHook
(IN PDRIVER_OBJECT DriverObject);

VOID
DriverUnload
(IN PDRIVER_OBJECT DriverObject);

PF_FORWARD_ACTION
IpFilterHook(
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);
#endif

//驅動程式的c檔案
#define PROT_TCP 6
#include "ntddk.h"
#include "ntddndis.h"
#include "pfhook.h"
#include "fxfilthook.h"

PDEVICE_OBJECT deviceObject;
UNICODE_STRING win32DeviceName;

//住驅動進入點
NTSTATUS
DriverEntry(
IN PDRIVER_OBJECT DriverObject,
IN PUNICODE_STRING RegistryPath
)
{
NTSTATUS status = STATUS_SUCCESS;
UNICODE_STRING ntDeviceName;

RtlInitUnicodeString(&ntDeviceName,NT_DEVICE_NAME);
//建立一個過濾鉤子驅動裝置
status = IoCreateDevice (DriverObject,0,&ntDeviceName,FILE_DEVICE_UNKNOWN,0,TRUE,&deviceObject);
if (!NT_SUCCESS (status)) {
goto ERROR;
}
RtlInitUnicodeString(&win32DeviceName, DOS_DEVICE_NAME);
//建立一個過濾鉤子驅動裝置符號串連
status = IoCreateSymbolicLink( &win32DeviceName, &ntDeviceName );
if (!NT_SUCCESS(status)) // If we couldn't create the link then
{ // abort installation.
goto ERROR;
}
//申明卸載常式
DriverObject->DriverUnload = DriverUnload;
//建立鉤子掛接
status = CreateFilterHook(DriverObject);
if (!NT_SUCCESS(status)) // If we couldn't create the link then
{ // abort installation.
IoDeleteSymbolicLink(&win32DeviceName);
goto ERROR;
}
return(STATUS_SUCCESS);
ERROR:
if(deviceObject)
IoDeleteDevice(deviceObject);
//DbgPrint( "Leave DriverEntry failed/n" );
return status;
}

NTSTATUS
CreateFilterHook(IN PDRIVER_OBJECT DriverObject)
{
PIRP nirp;
NTSTATUS status = STATUS_SUCCESS;
PFILE_OBJECT filtfileob;
UNICODE_STRING ntDeviceName;
PDEVICE_OBJECT filtdeviceob;
PF_SET_EXTENSION_HOOK_INFO filthook;
IO_STATUS_BLOCK filtstatus;

RtlInitUnicodeString(&ntDeviceName,L"//Device//IPFILTERDRIVER");
//將鉤子掛接函數放入結構中
filthook.ExtensionPointer = IpFilterHook;
//獲得系統ipfilterdriver驅動的裝置指標
status = IoGetDeviceObjectPointer(&ntDeviceName,FILE_GENERIC_READ|FILE_GENERIC_WRITE,&filtfileob,&filtdeviceob);
if(status!=STATUS_SUCCESS)
return status;
//綁定過濾鉤子到系統ipfilterdriver驅動的裝置指標
nirp = IoBuildDeviceIoControlRequest(
IOCTL_PF_SET_EXTENSION_POINTER,
filtdeviceob,
&filthook,
sizeof(PF_SET_EXTENSION_HOOK_INFO),
NULL,
0,
FALSE,
NULL,
&filtstatus);
if(nirp==NULL)
return filtstatus.Status;
//調度系統ipfilterdriver裝置重新操作irp
return (IoCallDriver(filtdeviceob,nirp));
}

VOID
DriverUnload(IN PDRIVER_OBJECT DriverObject)
{
//與載入一樣,只是鉤子函數結構中放NULL,讓系統ipfilterdriver卸載載入的鉤子函數

PIRP nirp;
NTSTATUS status = STATUS_SUCCESS;
PDEVICE_OBJECT filtdeviceob;
PFILE_OBJECT filtfileob;
PF_SET_EXTENSION_HOOK_INFO filthook;
IO_STATUS_BLOCK filtstatus;
UNICODE_STRING ntDeviceName;

RtlInitUnicodeString(&ntDeviceName,L"//Device//IPFILTERDRIVER");
filthook.ExtensionPointer = NULL;
status = IoGetDeviceObjectPointer(&ntDeviceName,FILE_GENERIC_READ|FILE_GENERIC_WRITE,&filtfileob,&filtdeviceob);
if(status==STATUS_SUCCESS)
{
nirp = IoBuildDeviceIoControlRequest(
IOCTL_PF_SET_EXTENSION_POINTER,
filtdeviceob,
&filthook,
sizeof(PF_SET_EXTENSION_HOOK_INFO),
NULL,
0,
FALSE,
NULL,
&filtstatus);
if(nirp!=NULL)
IoCallDriver(filtdeviceob,nirp);
}
IoDeleteSymbolicLink(&win32DeviceName);
IoDeleteDevice(deviceObject);
return;
}

PF_FORWARD_ACTION
IpFilterHook(
unsigned char *PacketHeader,
unsigned char *Packet,
unsigned int PacketLength,
unsigned int RecvInterfaceIndex,
unsigned int SendInterfaceIndex,
IPAddr RecvLinkNextHop,
IPAddr SendLinkNextHop
)
{
//過濾鉤子函數,這兒只簡單判斷屬於TCP協議且資料是抵達而且帶SYN標誌則過濾。大家可以根據需要修改自己的過濾判斷和處理。
if(((IPHeader *)PacketHeader)->iph_protocol == PROT_TCP)
{
//Packet[13]==0x2就是TCP中SYN的標誌
//SendInterfaceIndex==INVALID_PF_IF_INDEX說明包是抵達而不是發送的,因此這樣過濾就不會影響自己的包出去,但是外來帶SYN請求的包則會拒絕。
if(Packet[13]==0x2 && SendInterfaceIndex==INVALID_PF_IF_INDEX)
return PF_DROP;
}
return PF_FORWARD;
}

//簡單的建立登錄機碼的程式

unsigned char sysdir[256];
unsigned char drivcedir[256];
int RegHandelDev(char * exename)
{
//修改註冊表啟動一個NTHANDLE驅動程式
char subkey[200];
int buflen;
HKEY hkResult;
char Data[4];
DWORD isok;
buflen = sprintf(subkey,"System//CurrentControlSet//Services//%s",exename);
subkey[buflen]=0;
isok = RegCreateKey(HKEY_LOCAL_MACHINE,subkey,&hkResult);
if(isok!=ERROR_SUCCESS)
return FALSE;
Data[0]=3;
Data[1]=0;
Data[2]=0;
Data[3]=0;
isok=RegSetValueEx(hkResult,"Start",0,4,(const unsigned char *)Data,4);
Data[0]=1;
isok=RegSetValueEx(hkResult,"Type",0,4,(const unsigned char *)Data,4);
isok=RegSetValueEx(hkResult,"ErrorControl",0,4,(const unsigned char *)Data,4);
GetSystemDirectory(sysdir,256);
buflen = sprintf(drivcedir,"%s//Drivers//FxFiltHook.sys",sysdir);
buflen = sprintf(subkey,"//??//%s",drivcedir);
subkey[buflen]=0;
isok=RegSetValueEx(hkResult,"ImagePath",0,1,(const unsigned char *)subkey,buflen);
RegCloseKey(hkResult);
buflen = sprintf(subkey,"//Registry//Machine//System//CurrentControlSet//Services//%s",exename);
subkey[buflen]=0;
return TRUE;
}

int main(int argc,char *argv[])
{
//註冊驅動程式
if(RegHandelDev("Fxfilthook")==FALSE)
return FALSE;
return TRUE;
}

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.