监听 IP 数据包

作者:

在

利用系统的 ipfltdrv.sys 实现的过滤器钩子驱动(Filter-Hook Drivers)。

测试前请确保 SystemRoot\System32\Drivers\ipfltdrv.sys 已经加载(存在设备 \Device\IpFilterdriver)。如果没有加载的话可以用各种加载驱动的工具来加载(比如 Coderui 的 InstDrv.exe)。

注意在回调里面,Packet 是包括了 TCP / UDP / IGMP / ICMP 的报头的(但是不包括 IP 报头。)。

[FilterHookDriver] DriverEntry: Driver loaded. Built time: Jun 29 2012 01:37:03.
[FilterHookDriver] PacketFilterCallbackProc: Sent a packet from 10.0.0.2 to 10.0.0.1 with length 8
[FilterHookDriver] PacketFilterCallbackProc: Sent a packet from 10.0.0.2 to 10.0.0.255 with length 8
[FilterHookDriver] PacketFilterCallbackProc: Received a packet from 10.0.0.2 to 10.0.0.255 with length 209
[FilterHookDriver] PacketFilterCallbackProc: Received a packet from 10.0.0.1 to 10.0.0.2 with length 1064
[FilterHookDriver] PacketFilterCallbackProc: Sent a packet from 10.0.0.2 to 10.0.0.1 with length 8
[FilterHookDriver] PacketFilterCallbackProc: Received a packet from 10.0.0.1 to 10.0.0.2 with length 1064
[FilterHookDriver] PacketFilterCallbackProc: Sent a packet from 10.0.0.2 to 10.0.0.1 with length 8
[FilterHookDriver] PacketFilterCallbackProc: Received a packet from 10.0.0.1 to 10.0.0.2 with length 1064
[FilterHookDriver] DriverUnload: Driver unloaded.

#include
#include
#include #include

//
// 类型定义。
//

typedef struct _IP_HEADER {
UCHAR HeaderVersion;
UCHAR TypeOfService;
USHORT PacketSize;
USHORT PacketId;

//
// 分片偏移也在 Flags 中。参考 IP 报头。
//

USHORT Flags;
UCHAR TimeToLive;
UCHAR Protocol;
USHORT Checksum;
ULONG Source;
ULONG Destination;
} IP_HEADER, *PIP_HEADER;

typedef PacketFilterExtensionPtr PACKET_FILTER_EXTENSION_PTR;

//
// 字符串形式的 IP 地址的最大长度。
//

#define STRING_ADDRESS_LENGTH 16

//
// 输出调试信息。
//

#define PROJECT_NAME "FilterHookDriver"

#define DbgWrite(Format, ...) DbgPrint("[" PROJECT_NAME "] " __FUNCTION__ ": " Format, __VA_ARGS__)
#define DbgWriteLine(Format, ...) DbgWrite(Format "\n", __VA_ARGS__)

//
// 修改指针位置。
//

#define PointerAdd(Pointer, Increment, Type) ((Type)((ULONG_PTR)(Pointer) + (Increment)))

//
// 计算静态数组中的元素个数。
//

#define CountOf(Array) ((sizeof(Array) / sizeof((Array)[0])))

//
// 过滤器驱动的设备对象名称。
//

#define IP_FILTER_DEVICE_NAME L"\\Device\\Ipfilterdriver"

//
// 函数原型。
//

DRIVER_INITIALIZE DriverEntry;

DRIVER_UNLOAD DriverUnload;

NTSTATUS OpenFilterDeviceObject(
__out PDEVICE_OBJECT *DeviceObject
);

NTSTATUS RegisterFilterCallback(
__in PACKET_FILTER_EXTENSION_PTR FilterCallbackProc
);

//
// 函数所属区段标记。
//

#ifdef ALLOC_PRAGMA
#pragma alloc_text(INIT, DriverEntry)
#pragma alloc_text(PAGE, DriverUnload)
#pragma alloc_text(PAGE, OpenFilterDeviceObject)
#pragma alloc_text(PAGE, RegisterFilterCallback)
#endif

//
// 将 ULONG 型 IP 地址转换为 xxx.xxx.xxx.xxx 形式的 IP 地址。
//
// StringAddress 的长度至少需要为 STRING_ADDRESS_LENGTH。
//

VOID ConvertNumericAddressToString(
__out PUCHAR StringAddress,
__in ULONG NumericAddress
)
{
ULONG CurrentPosition;
ULONG Index;

CurrentPosition = 0;

//
// 将 IP 地址按字节分开,分别转换为字符串写入 StringAddress。
//

for (Index = 0; Index < sizeof(ULONG); Index++) { LPTSTR DestinationEnd; UCHAR Current; NTSTATUS Status; // // 得到这一位的数值。 // Current = *PointerAdd(&NumericAddress, Index, PUCHAR); // // 转换为字符串。 // ASSERT(STRING_ADDRESS_LENGTH > CurrentPosition);

Status = RtlStringCchPrintfExA(PointerAdd(StringAddress, CurrentPosition, PCHAR),
STRING_ADDRESS_LENGTH - CurrentPosition, &DestinationEnd, NULL, 0, "%d",
Current);

ASSERT(NT_SUCCESS(Status));

CurrentPosition = (PUCHAR)DestinationEnd - StringAddress;

//
// 如果不是最后一段,则增加分隔符(“.”)。
//

if (Index != sizeof(ULONG) - 1) {
StringAddress[CurrentPosition++] = '.';
}
}

//
// 末尾补 0。
//

StringAddress[CurrentPosition++] = 0;

ASSERT(CurrentPosition <= STRING_ADDRESS_LENGTH); return; } // // 过滤回调。 // // Packet、PacketSize 均不包含 IP 报头。 // // 本应为 PacketFilterExtensionPtr 类型,为了方便处理此处稍微有点变化。 // PacketFilterExtensionPtr 的定义参考 // http://msdn.microsoft.com/en-us/library/windows/hardware/ff562312(v=vs.85).aspx。 // PF_FORWARD_ACTION PacketFilterCallbackProc( __in PIP_HEADER Header, __in PUCHAR Packet, __in ULONG PacketSize, __in ULONG ReceiveInterfaceIndex, __in ULONG SendInterfaceIndex, __in PVOID ReceiveLinkNextHoop, __in PVOID SendLinkNextHoop ) { static const CHAR *OperationDescription[] = {"Sent", "Received"}; UCHAR Source[STRING_ADDRESS_LENGTH], Destination[STRING_ADDRESS_LENGTH]; ULONG OperationType; // // 将 IP 地址转换为字符串形式。 // ConvertNumericAddressToString(Source, Header->Source);
ConvertNumericAddressToString(Destination, Header->Destination);

//
// 获取操作类型。
//
// 如果 ReceiveInterfaceIndex 为 INVALID_PF_IF_INDEX,则表示当前过滤的是发送操作。
// 如果 SendInterfaceIndex 为 INVALID_PF_IF_INDEX,则表示当前过滤的是接受操作。
//
// ReceiveInterfaceIndex 和 SendInterfaceIndex 中有且只可能有一个是 INVALID_PF_IF_INDEX。
//

ASSERT(((ReceiveInterfaceIndex == INVALID_PF_IF_INDEX ^
SendInterfaceIndex == INVALID_PF_IF_INDEX)) == TRUE);

if (ReceiveInterfaceIndex == INVALID_PF_IF_INDEX) {
OperationType = 0;
} else {
OperationType = 1;
}

ASSERT(OperationType < CountOf(OperationDescription)); // // 输出信息。 // DbgWriteLine("%s a packet from %s to %s with length %d", OperationDescription[OperationType], Source, Destination, PacketSize); // // 放行。 // return PF_FORWARD; } // // 打开 IP 过滤器驱动的设备对象。 // // 这个函数在返回之前会引用 IP 过滤器驱动的设备对象。稍后应释放引用。 // NTSTATUS OpenFilterDeviceObject( __out PDEVICE_OBJECT *DeviceObject ) { UNICODE_STRING DeviceName = RTL_CONSTANT_STRING(IP_FILTER_DEVICE_NAME); PDEVICE_OBJECT LocalDeviceObject; PFILE_OBJECT FileObject; NTSTATUS Status; PAGED_CODE(); // // 获得设备对象的指针。 // Status = IoGetDeviceObjectPointer(&DeviceName, SYNCHRONIZE | GENERIC_READ | GENERIC_WRITE, &FileObject, &LocalDeviceObject); if (!NT_SUCCESS(Status)) { return Status; } // // IoGetDeviceObjectPointer 只会引用 FileObject (FileObject 间接引用了 DeviceObject。) // 此处引用 DeviceObject 并释放对 FileObject 的引用。 // ObReferenceObject((PVOID)LocalDeviceObject); ObDereferenceObject((PVOID)FileObject); // // 返回设备对象给调用方。 // *DeviceObject = LocalDeviceObject; return Status; } // // 注册过滤回调。 // // FilterCallbackProc 输入 NULL 则会从过滤器驱动中清除已经注册的过滤回调。 // NTSTATUS RegisterFilterCallback( __in PACKET_FILTER_EXTENSION_PTR FilterCallbackProc ) { PF_SET_EXTENSION_HOOK_INFO SetExtensionHookInfo; PDEVICE_OBJECT FilterDeviceObject; IO_STATUS_BLOCK IoStatusBlock; KEVENT Event; PIRP Irp; NTSTATUS Status; PAGED_CODE(); // // 打开过滤器驱动的设备对象。 // Status = OpenFilterDeviceObject(&FilterDeviceObject); if (!NT_SUCCESS(Status)) { return Status; } // // 填充注册信息。 // SetExtensionHookInfo.ExtensionPointer = FilterCallbackProc; // // 初始化用于同步操作的事件。 // KeInitializeEvent(&Event, NotificationEvent, FALSE); // // 构造 IRP。 // Irp = IoBuildDeviceIoControlRequest(IOCTL_PF_SET_EXTENSION_POINTER, FilterDeviceObject, (PVOID)&SetExtensionHookInfo, sizeof(PF_SET_EXTENSION_HOOK_INFO), NULL, 0, FALSE, &Event, &IoStatusBlock); if (!Irp) { ObDereferenceObject((PVOID)FilterDeviceObject); return STATUS_INSUFFICIENT_RESOURCES; } // // 注册过滤回调。 // Status = IoCallDriver(FilterDeviceObject, Irp); if (Status == STATUS_PENDING) { (VOID)KeWaitForSingleObject((PVOID)&Event, Executive, KernelMode, FALSE, NULL); Status = IoStatusBlock.Status; } // // 释放资源。 // // IRP 会由过滤器驱动在 IoCompleteRequest 时被系统释放。 // ObDereferenceObject((PVOID)FilterDeviceObject); if (!NT_SUCCESS(Status)) { return Status; } return Status; } // // 入口点。 // NTSTATUS DriverEntry( __in PDRIVER_OBJECT DriverObject, __in PUNICODE_STRING RegistryPath ) { NTSTATUS Status; UNREFERENCED_PARAMETER(RegistryPath); DbgWriteLine("Driver loaded. Built time: %s %s.", __DATE__, __TIME__); // // 填充回调函数。 // DriverObject->DriverUnload = DriverUnload;

//
// 注册过滤回调。
//

Status = RegisterFilterCallback((PACKET_FILTER_EXTENSION_PTR)PacketFilterCallbackProc);

if (!NT_SUCCESS(Status)) {
DbgWriteLine("We failed to register our filter hook. Unloading.");

return Status;
}

return Status;
}

//
// 卸载回调。
//

VOID DriverUnload(
__in PDRIVER_OBJECT DriverObject
)
{
NTSTATUS Status;

PAGED_CODE();

//
// 注销过滤回调。
//

Status = RegisterFilterCallback(NULL);

ASSERT(NT_SUCCESS(Status));

DbgWriteLine("Driver unloaded.");

return;
}

评论

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注