http://www.cnblogs.com/adward/archive/2009/04/27/1444921.html
键盘钩子比较麻烦的就是得到KeyboardInterruptService 的地址,有什么方法呢?lkd> !idt
Dumping IDT:
37: 806d0728 hal!PicSpuriousService37
3d: 806d1b70 hal!HalpApcInterrupt
41: 806d19cc hal!HalpDispatchInterrupt
50: 806d0800 hal!HalpApicRebootService
62: 84d587ec atapi!IdePortInterrupt (KINTERRUPT 84d587b0)
63: 84cebdd4 USBPORT!USBPORT_InterruptService (KINTERRUPT 84cebd98)
USBPORT!USBPORT_InterruptService (KINTERRUPT 84ce4988)
USBPORT!USBPORT_InterruptService (KINTERRUPT 84cddb78)
USBPORT!USBPORT_InterruptService (KINTERRUPT 84cd6d10)
USBPORT!USBPORT_InterruptService (KINTERRUPT 84ccfd98)
73: 84d08044 VIDEOPRT!pVideoPortInterrupt (KINTERRUPT 84d08008)
82: 84d58044 atapi!IdePortInterrupt (KINTERRUPT 84d58008)
83: 84dbf67c atapi!IdePortInterrupt (KINTERRUPT 84dbf640)
atapi!IdePortInterrupt (KINTERRUPT 84dbf3d0)
92: 84c0a044 serial!SerialCIsrSw (KINTERRUPT 84c0a008)
93: 84c0bdd4 i8042prt!I8042KeyboardInterruptService (KINTERRUPT 84c0bd98)
a3: 84c0b044 i8042prt!I8042MouseInterruptService (KINTERRUPT 84c0b008)
lkd> dt _KINTERRUPT 84c0bd98
nt!_KINTERRUPT
+0x000 Type : 22
+0x002 Size : 484
+0x004 InterruptListEntry : _LIST_ENTRY [ 0x84c0bd9c - 0x84c0bd9c ]
+0x00c ServiceRoutine : 0xf76cc495 /*就是这儿了*/ unsigned char i8042prt!I8042KeyboardInterruptService+0
+0x010 ServiceContext : 0x84d5da88
+0x014 SpinLock : 0
+0x018 TickCount : 0xffffffff
+0x01c ActualLock : 0x84d5db48 -> 0
+0x020 DispatchAddress : 0x80541aa0 void nt!KiInterruptDispatch+0
+0x024 Vector : 0x193
+0x028 Irql : 0x8 ''
+0x029 SynchronizeIrql : 0x9 ''
+0x02a FloatingSave : 0 ''
+0x02b Connected : 0x1 ''
+0x02c Number : 0 ''
+0x02d ShareVector : 0 ''
+0x030 Mode : 1 ( Latched )
+0x034 ServiceCount : 0
+0x038 DispatchCount : 0xffffffff
+0x03c DispatchCode : [106] 0x56535554
当然还可以特征码搜索啦!也麻烦!
rootkit上那个键盘王子介绍了一种很妙的方法!上代码。
PKINTERRUPT GetI8042PrtInterruptObject(void)
{
PDEVICE_OBJECT pDeviceObject = NULL; // Keyboard DeviceObject
PFILE_OBJECT fileObject;
UNICODE_STRING keyName;
// PPORT_KEYBOARD_EXTENSION KeyboardExtension;
PKINTERRUPT ReturnValue = NULL;
RtlInitUnicodeString( &keyName, NT_KEYBOARD_NAME0 );
// Getting the DeviceObject top-of-the-stack of the kbdclass device
IoGetDeviceObjectPointer(&keyName,
FILE_READ_ATTRIBUTES,
&fileObject,
&pDeviceObject);
// if fails
if( !pDeviceObject )
{
return NULL;
}
// Tracking the DeviceStack
//
//
// If it is not a i8042prt
while( pDeviceObject->DeviceType != FILE_DEVICE_8042_PORT )//下一个就是了,0x27
{
// go to the lower level object
if (((PR_DEVOBJ_EXTENSION)pDeviceObject->DeviceObjectExtension)->AttachedTo)
pDeviceObject = ((PR_DEVOBJ_EXTENSION)pDeviceObject->DeviceObjectExtension)->AttachedTo;
else // here is lowest-level and couldn't find i8042prt
return NULL;
}
//
// pDeviceObject == i8042prt's DeviceObject
//
ReturnValue = (PKINTERRUPT)((PPORT_KEYBOARD_EXTENSION)pDeviceObject->DeviceExtension)->InterruptObject;
return ReturnValue;
}
主函数中调用
ADDR= (ULONG)GetI8042PrtInterruptObject( );
dprintf("keyboatserv.SYS: 0X%08X\n", ADDR);
// +0x00c ServiceRoutine : 0xf76cc495 unsigned char i8042prt!I8042KeyboardInterruptService+0
// 找到了函数的地址了;
I8042KeyboardInterruptServiceADDR=(ULONG)((PKINTERRUPT)GetI8042PrtInterruptObject()->ServiceRoutine);
dprintf("keyboatserv.SYS: 0X%08X\n", I8042KeyboardInterruptServiceADDR);
要用的结构
typedef struct _R_DEVOBJ_EXTENSION
{
CSHORT Type;
USHORT Size;
PDEVICE_OBJECT DeviceObject;
ULONG PowerFlags;
PVOID Dope;
ULONG ExtensionFlags;
PVOID DeviceNode;
PDEVICE_OBJECT AttachedTo;
ULONG StartIoCount;
ULONG StartIoKey;
ULONG StartIoFlags;
PVOID Vpb;
} R_DEVOBJ_EXTENSION, *PR_DEVOBJ_EXTENSION;
typedef struct _PORT_KEYBOARD_EXTENSION {
// Pointer back to the this extension's device object.
PDEVICE_OBJECT Self;
PKINTERRUPT InterruptObject;
} PORT_KEYBOARD_EXTENSION, *PPORT_KEYBOARD_EXTENSION;
typedef struct _KINTERRUPT {
CSHORT Type;
CSHORT Size;
LIST_ENTRY InterruptListEntry;
ULONG ServiceRoutine;
ULONG ServiceContext;
KSPIN_LOCK SpinLock;
ULONG TickCount;
PKSPIN_LOCK ActualLock;
PVOID DispatchAddress;
ULONG Vector;
KIRQL Irql;
KIRQL SynchronizeIrql;
BOOLEAN FloatingSave;
BOOLEAN Connected;
CHAR Number;
UCHAR ShareVector;
KINTERRUPT_MODE Mode;
ULONG ServiceCount;
ULONG DispatchCount;
ULONG DispatchCode[106];
} KINTERRUPT, *PKINTERRUPT;
有了函数地址大家就自己发挥了啊!什么模拟按键,读取端口。
还可以接着找鼠标的函数了,那就方便了啊