65.9K
CodeProject 正在变化。 阅读更多。
Home

设备挂钩

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.80/5 (13投票s)

2012年5月25日

CPOL

4分钟阅读

viewsIcon

42507

downloadIcon

1446

设备挂钩

引言

网络嗅探器是文章 https://codeproject.org.cn/Articles/163408/APIHooking 的续篇,主要侧重于设备钩取。在这里,我计划介绍设备栈、设备扩展,并使用 C++(在 Windows 7:64 位系统上)使用 WDM 构建驱动程序。

背景

建议读者阅读 Toby Opferman 关于设备驱动程序的文章,读者需要了解如何构建驱动程序。此外,您还需要 WDK (Windows Driver Kit) 和 Dbgview(请自行搜索)。

我们将编写在“0”环(内核模式)下执行的代码,处理器特权保护机制用于执行高于“0”环的任务。请随时修改代码以使用 DbgPrint 打印 CS 寄存器。请注意,最后两位将设置为 0,表示“0”环代码执行。需要“0”环代码来访问内存中被页面表标记为特权的某些部分。特权页面只能被特权段访问(即,当前特权级别 < 3),用户代码在 CPL=3 下运行(因此无法访问它们)。此外,要访问 IO,CPL <= IOPL。

使用代码

附带的代码是用 C++ 编写的,必须随时参考。

我们将从编写一个设备入口函数开始(类似于 C/C++ 用户模式程序的 'main'/'winmain')

extern "C" NTSTATUS DriverEntry(PDRIVER_OBJECT pDriverObject, PUNICODE_STRING RegistryPath);
// remember we are using C++, remember to provide external linkages for C//

接下来我们需要做的是创建一个设备

NtStatus = IoCreateDevice(pDriverObject, sizeof(PDEVICE_OBJECT), NULL, 
     FILE_DEVICE_UNKNOWN, FILE_DEVICE_SECURE_OPEN, FALSE, &pDeviceObject_main);
//allocate in-device memory: sizeof(PDEVICE_OBJECT)) 

IoCreateDevice 允许您创建设备并分配四个字节:sizeof(PDEVICE_OBJECT)。这块内存将属于我们创建的设备的上下文,称为设备扩展。这个与设备扩展相关的内存始终可以通过设备指针访问。它通常用于存储调用 ExAllocatePool 创建的内存的指针,并且非常适合在不同驱动程序之间传递内存。其他驱动程序可以通过调用 IoAttachDevice(稍后详述)或调用 IoGetDeviceObjectPointer 来访问此指针。

现在我们附加驱动程序。

RtlInitUnicodeString(&usDeviceToFilter, L"\\Device\\tcp"); 
NtStatus = IoAttachDevice(pDeviceObject_main, &usDeviceToFilter, 
              (PDEVICE_OBJECT*)&pDeviceObject_main->DeviceExtension);

如前所述,我们使用 IoAttachDevice,我们将其附加到 device\TCP,因为我们正在钩取 TCP 调用。

当一个驱动程序被钩取时,进行钩取的驱动程序(我们创建的驱动程序,而不是 device\TCP)将接收到发往该设备的所有调用。我们的驱动程序现在位于设备栈的顶部(除非有人钩取了 device\TCP)。驱动程序的责任是将这些请求向下传递给栈中的较低驱动程序。最低的驱动程序通常是您的端口驱动程序(又名,迷你端口)。

请求连同参数通过 IRP(IO 请求包)传递给设备,在分层驱动程序(如我们的,使用设备栈)中。栈中的每个设备都有一个 IRP。因此,我们有一个 IRP 栈。

我们必须注册所有可能的 IRP 函数,以便为每个 IRP 都有一个函数

for(uiIndex = 0; uiIndex < IRP_MJ_MAXIMUM_FUNCTION; uiIndex++)
   pDriverObject->MajorFunction[uiIndex] = UnSupportedFunction;

UnSupportedFunction 仅将 IRP 传递给较低的驱动程序,不做任何其他操作。

NTSTATUS UnSupportedFunction(PDEVICE_OBJECT DeviceObject, PIRP Irp) { NTSTATUS NtStatus = STATUS_NOT_SUPPORTED; 
  IoSkipCurrentIrpStackLocation(Irp);
NtStatus = IoCallDriver((PDEVICE_OBJECT)DeviceObject->DeviceExtension, Irp); }
return NtStatus; 

我们必须跳过当前的 IRP 处理,并将其直接传递给栈中的下一个驱动程序。

为了嗅探网络数据包,我们只对 IRP_MJ_INTERNAL_DEVICE_CONTROL 感兴趣。我们添加以下行以确保调用与 IO 处理相关的适当函数

pDriverObject->MajorFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL] = IOFunction; //(refer to code)

每次 IRP 的当前堆栈位置主函数等于 IRP_MJ_INTERNAL_DEVICE_CONTROL 时,都会调用 IOFunction

要处理任何函数(在本例中为 IOFunction),我们必须获取当前的堆栈位置

PIO_STACK_LOCATION StackIrpPointer= IoGetCurrentIrpStackLocation(Irp);

通过此,我们可以获取从用户模式代码传递下来的参数(参考代码)

PTDI_REQUEST_KERNEL_CONNECT TDI_connectRequest =
   ( PTDI_REQUEST_KERNEL_CONNECT ) (& StackIrpPointer -> Parameters );
PTA_ADDRESS TA_Address_data =( ( PTRANSPORT_ADDRESS )( TDI_connectRequest -> 
   RequestConnectionInformation -> RemoteAddress ))-> 
   Address; PTDI_ADDRESS_IP TDI_data = ( PTDI_ADDRESS_IP ) ( TA_Address_data->Address );
   { UINT Address = TDI_data -> in_addr ; UINT Port = TDI_data -> sin_port ; 
     DbgPrint (address:%x Port: %x",Address,Port) } 

我还添加了发送和接收的代码。

对于发送代码,我们使用 MmGetSystemAddressForMdlSafe,因为我们使用的是 METHOD_IN_DIRECT

对于接收

PCHAR pWriteDataBuffer = 0;
DbgPrint ( IoCopyCurrentIrpStackLocationToNext(Irp);
IoSetCompletionRoutine(Irp,Complete,0,TRUE,TRUE,TRUE);
NtStatus = IoCallDriver((PDEVICE_OBJECT)
  DeviceObject->DeviceExtension, Irp); "inside recv function to pull out data");

我们现在将当前堆栈位置复制到下一个,而不是跳过它,因为我们正在调用 IOSetCompletionRoutine。这将设置一个完成例程,在 IO 完成时会被调用。

让我们启动它

驱动程序的安装方式与服务类似,我们将为此使用服务控制管理器。

system(sc create Driver1 binPath= "..//Driver.sys" type= kernel");
system("sc start Driver1");
MessageBoxA(0,"UnloadFilter","UnloadFilter",0);"sc stop Driver1");
system("sc stop Driver1");
system("sc delete Driver1");

附加代码:SimpleSocket 是供您测试代码的,simple socket 是一个简单的服务器,在使用过滤驱动程序处于活动状态时,使用 Telnet 连接到它,并在 Dbgview 中查看输出。

关注点

我希望读者已经学会了作为网络嗅探器(过滤驱动程序)实现的设备栈。

如前所述,本文仅旨在教授读者设备栈而不是网络过滤器,TDI 的实现改编自互联网上的文章。

© . All rights reserved.