wildcatstar
驱动牛犊
驱动牛犊
  • 注册日期2006-06-23
  • 最后登录2010-05-20
  • 粉丝0
  • 关注0
  • 积分191分
  • 威望31点
  • 贡献值0点
  • 好评度20点
  • 原创分0分
  • 专家分0分
阅读:1263回复:5

请问一个键盘过滤驱动的问题

楼主#
更多 发布于:2008-04-13 20:06
我参考Ctrl2cap做了一个键盘过滤驱动,总是出问题,请帮忙看一下。我只列重点的部分,太多不好看
入口代码
NTSTATUS DriverEntry( IN PDRIVER_OBJECT theDriverObject, IN PUNICODE_STRING theRegistryPath )
{
NTSTATUS status = STATUS_SUCCESS;
int i;
__try
{
DbgPrint(" DriverEntry... \n");

g_DriverObject.pDriverObj = theDriverObject;
for (i = 0; i < IRP_MJ_MAXIMUM_FUNCTION; i++)
{
g_DriverObject.pDriverObj->MajorFunction = DispatchMajorFunction;
}
g_DriverObject.pDriverObj->DriverUnload = DriverUnload;
status = CreateDeviceAndLink(DEVICE_NAME,LINK_NAME);
。。。。。。
}

然后就是创建设备对象的代码,我创建了两个,一个是FILE_DEVICE_UNKNOWN,一个是FILE_DEVICE_KEYBOARD

//创建设备和符号
NTSTATUS CreateDeviceAndLink(PCWSTR DeviceName,PCWSTR LinkName)
{
NTSTATUS status = STATUS_SUCCESS;

CCHAR ntNameBuffer[64];
STRING ntNameString;
UNICODE_STRING ntUnicodeString;
__try
{
DbgPrint(" CreateDeviceAndLink …… \n");
// 创建、初始化设备对象
// 设备名称
RtlInitUnicodeString(&g_DriverObject.ustrDevName, DeviceName);
// 创建设备对象
status = IoCreateDevice(g_DriverObject.pDriverObj,
sizeof(DEVICE_EXTENSION), // 为设备扩展结构申请空间,
&g_DriverObject.ustrDevName,
FILE_DEVICE_UNKNOWN,
0,
FALSE,
&g_DriverObject.pDeviceObj);

if(!NT_SUCCESS(status))
{
DbgPrint(" CreateDevice Failed \n");
return status;
}

// 创建符号连接名称
// 符号连接名称
RtlInitUnicodeString(&g_DriverObject.ustrLinkName, LinkName);
// 创建关联
status = IoCreateSymbolicLink(&g_DriverObject.ustrLinkName, &g_DriverObject.ustrDevName);
if(!NT_SUCCESS(status))
{
DbgPrint(" CreateLink Failed \n");
IoDeleteDevice(g_DriverObject.pDeviceObj);
return status;
}

//创建键盘对象

sprintf( ntNameBuffer, "\\Device\\KeyboardClass0" );
RtlInitAnsiString( &ntNameString, ntNameBuffer );
RtlAnsiStringToUnicodeString( &ntUnicodeString, &ntNameString, TRUE );

status = IoCreateDevice( g_DriverObject.pDriverObj,
0,
NULL,
FILE_DEVICE_KEYBOARD,
0,
FALSE,
&g_DriverObject.pKBDDeviceObj );

if( !NT_SUCCESS(status) ) {

DbgPrint(("Ctrl2cap: Keyboard hook failed to create device!\n"));

RtlFreeUnicodeString( &ntUnicodeString );

return STATUS_SUCCESS;
}

//
// Keyboard uses buffered I/O so we must as well.
//

g_DriverObject.pKBDDeviceObj->Flags |= DO_BUFFERED_IO | DO_POWER_PAGABLE;
g_DriverObject.pKBDDeviceObj->Flags &= ~DO_DEVICE_INITIALIZING;

//
// Attach to the keyboard chain.
//

status = IoAttachDevice( g_DriverObject.pKBDDeviceObj, &ntUnicodeString, &g_DriverObject.pKbdTopOfStack );

if( !NT_SUCCESS(status) ) {

DbgPrint(("Ctrl2cap: Connect with keyboard failed!\n"));

IoDeleteDevice( g_DriverObject.pKBDDeviceObj );

RtlFreeUnicodeString( &ntUnicodeString );
}

RtlFreeUnicodeString( &ntUnicodeString );

DbgPrint(" CreateDeviceAndLink OK \n");
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
DbgPrint("Exception occured, caught in CreateDeviceAndLink(). Unknown error\n");
}
return status;
}
然后就是在这里,IoAttachDevice的时候,前面设置的DispatchMajorFunction函数被调用了,这个函数是这样的:
NTSTATUS DispatchMajorFunction(PDEVICE_OBJECT pDevObj, PIRP pIrp)
{
//这里需要对驱动对象进行区分
__try
{
PIO_STACK_LOCATION irpStack = NULL;
PIO_STACK_LOCATION nextIrpStack = NULL;
irpStack = IoGetCurrentIrpStackLocation(pIrp);
//键盘设备对象
if(pDevObj==g_DriverObject.pKBDDeviceObj)
{
pIrp->IoStatus.Status = STATUS_SUCCESS;
switch(irpStack->MajorFunction)
{
case IRP_MJ_READ:
nextIrpStack = IoGetNextIrpStackLocation(pIrp);
*nextIrpStack = *irpStack;

IoSetCompletionRoutine(pIrp, OnKbdReadComplete, pDevObj, TRUE, TRUE, TRUE );

// Return the results of the call to the keyboard class driver.
return IoCallDriver(g_DriverObject.pKbdTopOfStack, pIrp);
default:
pIrp->CurrentLocation++;
pIrp->Tail.Overlay.CurrentStackLocation++;
// pass this onto whoever we stole it from...
return IoCallDriver(g_DriverObject.pKbdTopOfStack, pIrp);
}
}
//默认的设备对象
else if(pDevObj==g_DriverObject.pDeviceObj)
{
switch(irpStack->MajorFunction)
{
case IRP_MJ_CREATE:
case IRP_MJ_CLOSE:
return DispatchCreateClose(pDevObj,pIrp);

case IRP_MJ_DEVICE_CONTROL:
return DispatchIoctl(pDevObj,pIrp);
}
}


// 完成请求
pIrp->IoStatus.Status = STATUS_SUCCESS;
IoCompleteRequest(pIrp, IO_NO_INCREMENT);
}
__finally
{
DbgPrint("Exception occured, caught in DispatchMajorFunction(). Unknown error\n");
}
return STATUS_SUCCESS;
}
第一次调用到这个函数的时候执行了
default:
pIrp->CurrentLocation++;
pIrp->Tail.Overlay.CurrentStackLocation++;
// pass this onto whoever we stole it from...
return IoCallDriver(g_DriverObject.pKbdTopOfStack, pIrp);
这部分代码,然后就在IoCallDriver出错了~
以后每次到这个函数都会在调用IoCallDriver是出错。请问是哪儿的问题啊?
wildcatstar
驱动牛犊
驱动牛犊
  • 注册日期2006-06-23
  • 最后登录2010-05-20
  • 粉丝0
  • 关注0
  • 积分191分
  • 威望31点
  • 贡献值0点
  • 好评度20点
  • 原创分0分
  • 专家分0分
沙发#
发布于:2008-04-13 22:01
用ctrl2cap的代码倒是不会出错,但是
status = IoAttachDevice( HookDeviceObject, &ntUnicodeString, &kbdDevice );
这样连接上以后如何删除呢?

VOID DriverUnload(PDRIVER_OBJECT pDriverObj)
{    
        IoDetachDevice(kbdDevice);
        IoDeleteDevice(HookDeviceObject);
}
这样的方式会出错
wildcatstar
驱动牛犊
驱动牛犊
  • 注册日期2006-06-23
  • 最后登录2010-05-20
  • 粉丝0
  • 关注0
  • 积分191分
  • 威望31点
  • 贡献值0点
  • 好评度20点
  • 原创分0分
  • 专家分0分
板凳#
发布于:2008-04-13 22:58
用ctrl2cap的代码倒是不会出错,是不是我的
DispatchMajorFunction函数写的有问题呢?
另外,
status = IoAttachDevice( HookDeviceObject, &ntUnicodeString, &kbdDevice );
这样连接上以后如何删除呢?

VOID DriverUnload(PDRIVER_OBJECT pDriverObj)
{    
        IoDetachDevice(kbdDevice);
        IoDeleteDevice(HookDeviceObject);
}
这样的方式会出错
tracera
禁止发言
禁止发言
  • 注册日期2006-01-09
  • 最后登录2018-09-25
  • 粉丝8
  • 关注0
  • 积分-5788分
  • 威望135321点
  • 贡献值0点
  • 好评度625点
  • 原创分1分
  • 专家分0分
  • 社区居民
地板#
发布于:2008-04-15 23:23
用户被禁言,该主题自动屏蔽!
wildcatstar
驱动牛犊
驱动牛犊
  • 注册日期2006-06-23
  • 最后登录2010-05-20
  • 粉丝0
  • 关注0
  • 积分191分
  • 威望31点
  • 贡献值0点
  • 好评度20点
  • 原创分0分
  • 专家分0分
地下室#
发布于:2008-04-16 00:01
TO tracera:
    深表感谢!
我参考了SINISTER的一篇键盘过滤驱动的文章,还有rootkit网站的klog的代码,这个地方大概明白了,需要等待到最后一个键盘读IRP处理完才退出。
但是还有一个问题,我用

        for (i = 0; i < IRP_MJ_MAXIMUM_FUNCTION; i++)
        {
            DriverObject->MajorFunction = DispatchMajorFunction;
        }
把所有处理过程放一起了,而原程序是分开的(IRP_MJ_READ是单独的)。结果这个统一处理的函数总是出意外:
NTSTATUS DispatchMajorFunction(PDEVICE_OBJECT pDevObj, PIRP pIrp)
{
    //这里需要对设备对象进行区分,也许会有多个
    __try
    {        
        PIO_STACK_LOCATION irpStack = NULL;
        PIO_STACK_LOCATION nextIrpStack = NULL;
        irpStack = IoGetCurrentIrpStackLocation(pIrp);
        //键盘设备对象
        if(pDevObj==HookDeviceObject)
        {
            pIrp->IoStatus.Status = STATUS_SUCCESS;
            switch(irpStack->MajorFunction)
            {
                case IRP_MJ_READ:
                    nextIrpStack = IoGetNextIrpStackLocation(pIrp);
                    *nextIrpStack = *irpStack;
                    
                    IoSetCompletionRoutine(pIrp, Ctrl2capReadComplete, pDevObj, TRUE, TRUE, TRUE );
            
                    // Return the results of the call to the keyboard class driver.
                    return IoCallDriver(kbdDevice, pIrp);
                default:
                    pIrp->CurrentLocation++;
                    pIrp->Tail.Overlay.CurrentStackLocation++;
                     // pass this onto whoever we stole it from...
                    return IoCallDriver(kbdDevice, pIrp);//就是这里,第一次调用到这里就出错了!看起来和分开写的没什么区别呀
            }
        }
        else
        {
            pIrp->IoStatus.Status = STATUS_UNSUCCESSFUL;
            IoCompleteRequest (pIrp,
                           IO_NO_INCREMENT
                           );
        }
                                  
    }
    __finally
    {
        DbgPrint("Exception occured, caught in DispatchMajorFunction().  Unknown error\n");
    }                
    return pIrp->IoStatus.Status;
}

我不是做驱动开发的,只是对有些东西比较感兴趣,只了解一些皮毛,基础不好
我打算一点一点把没问题的代码改变为有问题的代码,看看到底是哪不对。
不过还是希望能看出问题的大虾指点一下啊~我的机器已经蓝屏N多次了~痛苦~
wildcatstar
驱动牛犊
驱动牛犊
  • 注册日期2006-06-23
  • 最后登录2010-05-20
  • 粉丝0
  • 关注0
  • 积分191分
  • 威望31点
  • 贡献值0点
  • 好评度20点
  • 原创分0分
  • 专家分0分
5楼#
发布于:2008-04-19 17:30
真是奇怪了,我把
switch(irpStack->MajorFunction)
            {
                case IRP_MJ_READ:
                    nextIrpStack = IoGetNextIrpStackLocation(pIrp);
                    *nextIrpStack = *irpStack;
                    
                    IoSetCompletionRoutine(pIrp, Ctrl2capReadComplete, pDevObj, TRUE, TRUE, TRUE );
            
                    // Return the results of the call to the keyboard class driver.
                    return IoCallDriver(kbdDevice, pIrp);
                default:
                    pIrp->CurrentLocation++;
                    pIrp->Tail.Overlay.CurrentStackLocation++;
                     // pass this onto whoever we stole it from...
                    return IoCallDriver(kbdDevice, pIrp);
            }
改为
if(IRP_MJ_READ == (currentIrpStack->MajorFunction))
      {
          *nextIrpStack = *currentIrpStack;
          IoSetCompletionRoutine( Irp, Ctrl2capReadComplete, DeviceObject, TRUE, TRUE, TRUE );     //&micro;÷&Oacute;&Atilde;&Iacute;ê&sup3;&Eacute;&Agrave;&yacute;&sup3;&Igrave;
    
            //
            // &frac12;&laquo; IRP &frac14;&AElig;&Ecirc;&yacute;&AElig;÷&frac14;&Oacute;&Ograve;&raquo;&pound;&not;&Icirc;&ordf;&Ouml;§&sup3;&Ouml; SMP &Ecirc;&sup1;&Oacute;&Atilde;×&Ocirc;&ETH;&yacute;&Euml;&oslash;
            //
          KeAcquireSpinLock( &MySpinLock, &IrqLevel );
          InterlockedIncrement( &g_number_of_pending_IRPs );
          KeReleaseSpinLock( &MySpinLock, IrqLevel );

          return IoCallDriver( kbdDevice, Irp );
      }
      else
        {
                IoSkipCurrentIrpStackLocation(Irp);
                return IoCallDriver( kbdDevice, Irp );
        }
就没问题了。不知道是为什么
游客

返回顶部