剖析一个典型的Keyboard_Hook

//本人巨菜,纯粹的学习笔记

//高手飘过就可以了

//不当之处还请指出,谢谢了.

 

//先mark下,回头再弄,笔记本没电了...

1.键盘过滤

2.深入native application

3.进程与线程 EPROCESS 分析

 

//关于I/O堆栈

1.当前设备堆栈不对IRP做任何处理.

//给出一个通用的DispatchCommon函数

NTSTATUS DispatchCommon(IN PDEVICE_OBJECT pDeviceObject, IN PIRP pIrp)

{

  PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION)pDevObj->DeviceExtension;

  IoSkipCurrentIrpStackLocation(pIrp);

  status=IoCallDriver(pdx->TargetDevice,pIrp);

}

 

2.当前IRP也需要参与操作 ,需要将当前的I/0堆栈的参数复制到下一层.

NTSTATUS Dispatch_Other(IN PDEVICE_OBJECT pDeviceObject, IN PIRP pIrp)

{

  PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION)pDevObj->DeviceExtension;

 

  // PIO_STACK_LOCATION currentIrpStack = IoGetCurrentIrpStackLocation(pIrp);
   // PIO_STACK_LOCATION nextIrpStack = IoGetNextIrpStackLocation(pIrp);
  // *nextIrpStack = *currentIrpStack;

  IoCopyCurrentIrpStackLocationToNext(pIrp);

  

  // IoSetCompletionRoutine(pIrp, OnOtherCompletion, pDeviceObject, TRUE, TRUE, TRUE);

  status=IoCallDriver(pdx->TargetDevice,pIrp);

}

//关于完成例程IoSetCompletionRoutine

//一旦底层驱动讲IRP完成后,IRP的完成例程立刻被触发

VOID 
  IoSetCompletionRoutine(
    IN PIRP  Irp,
    IN PIO_COMPLETION_ROUTINE  CompletionRoutine  OPTIONAL,
    IN PVOID  Context  OPTIONAL,
    IN BOOLEAN    InvokeOnSuccess,
    IN BOOLEAN  InvokeOnError,
    IN BOOLEAN  InvokeOnCancel
    );

// in the CompletionRoutine ,you should call IoMarkPending(),

 

//关于新创建的Keyboard Device

//调用IoCreateDevice,传入的Device_Type是FILE_DEVICE_KEYBOARD

//新创建的设备相关标记 应该设置与底层键盘设备相同.可以使用DeviceTree工具查看

//一般而言:

 pKeyboardDeviceObject->Flags = pKeyboardDeviceObject->Flags | (DO_BUFFERED_IO | DO_POWER_PAGABLE);
 pKeyboardDeviceObject->Flags = pKeyboardDeviceObject->Flags & ~DO_DEVICE_INITIALIZING;

 

//关于IoAttachDevice

NTSTATUS 
  IoAttachDevice(
    IN PDEVICE_OBJECT  SourceDevice,
    IN PUNICODE_STRING  TargetDevice,
    OUT PDEVICE_OBJECT  *AttachedDevice
    );

 

//关于PsCreateSystemThread

//The PsCreateSystemThread routine creates a system thread that executes in kernel mode and returns a handle for the thread.

NTSTATUS 
  PsCreateSystemThread(
    OUT PHANDLE  ThreadHandle,
    IN ULONG  DesiredAccess,
    IN POBJECT_ATTRIBUTES  ObjectAttributes  OPTIONAL,
    IN HANDLE  ProcessHandle  OPTIONAL,
    OUT PCLIENT_ID  ClientId  OPTIONAL,
    IN PKSTART_ROUTINE  StartRoutine,
    IN PVOID  StartContext
    );

//补充下最后两个参数的说明,其他的参考wdk或者ddk

//

// StartRoutine

//  Is the entry point for a driver thread.

// StartContext

//  Supplies a single argument that is passed to the thread when it begins execution.

 

//关于CONTAINING_RECORD

The CONTAINING_RECORD macro returns the base address of an instance of a structure given the type of the structure and the address of a field within the containing structure.

PCHAR 
  CONTAINING_RECORD(
    IN PCHAR  Address,
    IN TYPE  Type,
    IN PCHAR  Field
    );

 

//最后随便扯点思路

//主要是分层驱动程序过滤,Hook键盘的话,主要是捕获IRP_MJ_READ 信息

//1.首先Hook IRP_MJ_READ的分发函数,通过IoSetCompletionRoutine设置一个完成例程OnReadCompletionRoutine;

//2.通过IoCreateDevice创建一个新的键盘设备,然后调用IoAttachDevice(),将该设备挂上old设备栈上

// 通过上面两步,过滤驱动安装好.然后是对所捕获的键盘消息的处理

//3.在Klog的src所实现的是,通过PsCreateSystemThread创建一个工作线程来实现对键盘消息的处理.

//4.在该工作线程中,讲所记录的键盘码,写入klog.txt 文件中.

 

//总结下,思路很简单,但是code起来,细节很多...很多地方需要注意.同步,线程的创建和释放,对KEYBOARD_INPUT_DATA的处理

//还有如何将扫描码转换成真正的键盘码.ConvertScanCodeToKeyCode...

posted @ 2010-05-11 01:28  Tbit  阅读(763)  评论(0编辑  收藏  举报