csanycall
驱动牛犊
驱动牛犊
  • 注册日期2005-03-23
  • 最后登录2015-01-15
  • 粉丝0
  • 关注0
  • 积分75分
  • 威望237点
  • 贡献值0点
  • 好评度7点
  • 原创分0分
  • 专家分0分
阅读:2540回复:0

内核KeWaitForSingleObject的问题

楼主#
更多 发布于:2011-08-24 11:00
本人新手,小试一下拦截注册表的写入操作,然后将相关值发到应用,由应用判断是否允许写入,并将写入标志传给内核,同时使内核事件有信号。
现在关键是KeWaitForSingleObject等待的事件并没有设置为有信号,为啥还继续往下执行呢?
内核代码如下:
RegDispatchDeviceControl(...){
......


// 处理不同的IOCTL
    switch (ioControlCode)
    {
    case MY_IOCTL_MON_APP://应用过来取写入的注册表值
        {
            pwcRegVal = (WCHAR*)Irp->AssociatedIrp.SystemBuffer;

            if (outBufLength >= 1024)
            {                
                wcsncpy(pwcRegVal,  deviceExtension->wcRegVal, deviceExtension->uLen);
                
                Irp->IoStatus.Information = deviceExtension->uLen;
                
            }
            break;
        }
        case MY_IOCTL_MON_KER://应用将是否允许写入的标志告诉内核,比如1允许,0不允许
        {
            pwcRegVal = (WCHAR*)Irp->AssociatedIrp.SystemBuffer;
            deviceExtension->uFlag = *(ULONG*)pwcRegVal;
            KdPrint(("app -> ker deviceExtension->uFlag:%d\n", deviceExtension->uFlag));
            Irp->IoStatus.Information = inBufLength;
            
            break;
        }
        case MY_IOCTL_MON_EVT://将应用创建的事件句柄传给内核,让内核获取事件对象
        {
            NTSTATUS sts ;            
            //HANDLE* hEvt = (HANDLE*)Irp->AssociatedIrp.SystemBuffer;
            PEVT_HANDLE pEH = (PEVT_HANDLE)Irp->AssociatedIrp.SystemBuffer;
            
            KdPrint(("get event handle pEH->hApp:%x, pEH->hKer:%x\n", pEH->hApp, pEH->hKer));
            sts = ObReferenceObjectByHandle(pEH->hApp, EVENT_MODIFY_STATE, *ExEventObjectType, KernelMode, (PVOID*)&deviceExtension->pApp, NULL);
            if(sts != STATUS_SUCCESS) KdPrint(("trans evt error:%x\n", deviceExtension->pApp));
            sts = ObReferenceObjectByHandle(pEH->hKer, EVENT_MODIFY_STATE, *ExEventObjectType, KernelMode, (PVOID*)&deviceExtension->pKer, NULL);
            if(sts != STATUS_SUCCESS) KdPrint(("trans evt error:%x\n", deviceExtension->pKer));
            KdPrint(("pApp:%x, pKer:%x\n", deviceExtension->pApp, deviceExtension->pKer));
            KeClearEvent(deviceExtension->pApp);
            KeClearEvent(deviceExtension->pKer);
            
            Irp->IoStatus.Information = inBufLength;
            break;
        }        
    }
    
    Irp->IoStatus.Status = STATUS_SUCCESS;
    IoCompleteRequest(Irp, IO_NO_INCREMENT);    

    return STATUS_SUCCESS;


NTSTATUS NewZwSetValueKey(IN HANDLE KeyHandle,
                                                 IN PUNICODE_STRING ValueName,
                                                 IN ULONG TitleIndex OPTIONAL,                                                                                        
                                                 IN ULONG Type,
                                                 IN PVOID Data,
                                                 IN ULONG DataSize){    

.............................

RtlInitUnicodeString(&cmp, L"\\REGISTRY\\MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run");
.......................

tmp = 当前注册表路径;
//将
if(RtlPrefixUnicodeString(&cmp, &tmp, FALSE)){    
        //与策略抵触,发送到应用判断
            PDEVICE_EXTENSION pDeviceExt = (PDEVICE_EXTENSION)g_pDeviceObject->DeviceExtension;
            RtlZeroMemory(pDeviceExt->wcRegVal, sizeof(pDeviceExt->wcRegVal));
            if(DataSize >= 1024) DataSize = 1024;
            wcsncpy(pDeviceExt->wcRegVal,  (WCHAR*)Data, DataSize);
            pDeviceExt->wcRegVal[DataSize] = L"\0";
            pDeviceExt->uLen = DataSize + 1;
            KdPrint(("[拦截]:注册表路径:%ws,字符串内容:%ws\n", tmp.Buffer,  pDeviceExt->wcRegVal));
            
            __try{
                // 触发事件,通知应用程序
                if(pDeviceExt->pApp){
                    KeSetEvent(pDeviceExt->pApp, IO_NO_INCREMENT, FALSE);
                    KeClearEvent(pDeviceExt->pApp);
                    ObDereferenceObject(pDeviceExt->pApp);
                }else{
                    KdPrint(("pApp对象为空,不能通知应用处理\n"));
                }
            }__except(EXCEPTION_CONTINUE_EXECUTION){
                KdPrint(("EXCEPTION_CONTINUE_EXECUTION ERROR\n"));
            }
            
///以下为等待用户的事件信号,现在郁闷的是应用还没有调用SetEvent(eh.hKer);就直接执行了,汗死
            {
                KdPrint(("Enter Ker Wait...\n"));
                if(pDeviceExt->pKer) {
                    status = KeWaitForSingleObject(&pDeviceExt->pKer, Executive, KernelMode, FALSE, NULL);
                    if(status == STATUS_TIMEOUT){
                        //超时,禁止
                        KdPrint(("[RegMon]:超时拒绝\n"));                    
                        return STATUS_ACCESS_DENIED;
                    }else if(status == STATUS_SUCCESS){
                        //读取信息
                        KdPrint(("status == STATUS_SUCCESS:pDeviceExt->uFlag:%d\n", pDeviceExt->uFlag));                        
                        if(pDeviceExt->uFlag != 1){//禁止
                            return STATUS_ACCESS_DENIED;
                        }
                    }
                }else{
                    KdPrint(("pKer对象为空,不能接收应用处理,自行放过\n"));
                }
            }
    }
    if(pNameInfo)
        ExFreePool(pNameInfo);
    //剩下的交给我们的原函数
    return OldZwSetValueKey(KeyHandle,ValueName,TitleIndex,Type,Data,DataSize);


应用程序:

int main()
{
    EVT_HANDLE eh;
    WCHAR regval[1024+2];
    char  regv2[1024+2];
    char  regv22[1024+2];
    DWORD dwRet;
    BOOL  bRet = FALSE;    
    ULONG uFlag = 1;
    char  ic[16] = {0};

        
    // 打开驱动设备对象
    HANDLE hDriver = ::CreateFile(
                                SYMBOL_LINK,
                                GENERIC_READ | GENERIC_WRITE,
                                0,
                                NULL,
                                OPEN_EXISTING,
                                FILE_ATTRIBUTE_NORMAL,
                                NULL);
    if (hDriver == INVALID_HANDLE_VALUE)
    {
        printf("打开驱动设备对象失败!\n");
        
        return -1;
    }
    //创建对象并传递给内核
    eh.hApp = CreateEvent(NULL, TRUE, FALSE, EVENT_NAME_APP);
    eh.hKer = CreateEvent(NULL, TRUE, FALSE, EVENT_NAME_KER);
    printf("eh.hApp:%x, eh.hKer:%x\n", eh.hApp, eh.hKer);
    if(eh.hApp == NULL || eh.hKer == NULL){
        printf("create event error\n");
        ::CloseHandle(hDriver);
        return -1;
    }

    bRet = ::DeviceIoControl(
        hDriver,
        MY_IOCTL_MON_EVT,
        &eh,
        sizeof(eh),
        NULL,
        0,
        &dwRet,
        NULL);
    if(bRet){
        printf("send evt to ker okk\n");
    }else{
        printf("send evt to ker err\n");
        ::CloseHandle(hDriver);
        return -1;
    }
    //end trans evt to ker

    
    memset(regval, 0 , sizeof(regval));
    memset(regv2, 0 , sizeof(regv2));
    memset(regv22, 0 , sizeof(regv22));

    //get 写入注册表的值
    while (WAIT_FAILED != ::WaitForSingleObject(eh.hApp, INFINITE))
    {
        dwRet = 0;    
        
        bRet = ::DeviceIoControl(
                hDriver,
                MY_IOCTL_MON_APP,
                NULL,
                0,
                regval,
                1024,
                &dwRet,
                NULL);
        
        if (bRet){
            if(wcslen(regval) <= 0) continue;
            //regval[dwRet] = '\0';
            WideCharToMultiByte(CP_ACP, WC_COMPOSITECHECK, regval, dwRet, regv2, sizeof(regv2), NULL, NULL);
          
          if(0 == strcmp(regv2, regv22)) continue;

            printf("judge reg val:%s\n", regv2);
            strcpy(regv22, regv2);
        }else{
            printf("\n获取内核信息失败!\n");
            break;
        }
        printf("是否允许?(y/n):");
        scanf("%s", ic);

        if(0 == strcmp("y", ic))
            uFlag = 1;
        else
            uFlag = 0;
    
        printf("你选择了:%s\n", ic);

        //传入用户的选择,这里永远传入允许---------------------测试使用,按道理需要跑到这一步来,关键是没有来到这里哈
        bRet = ::DeviceIoControl(
            hDriver,
            MY_IOCTL_MON_KER,
            &uFlag,
            sizeof(ULONG),
            NULL,
            0,
            &dwRet,
            NULL);
        if(bRet){
            printf("send user select ok\n");
        }else{
            printf("send user select error\n");
        }
        //设置内核事件让其处理
        SetEvent(eh.hKer);
        ResetEvent(eh.hKer);

    }
    
    ::CloseHandle(hDriver);
    
    return 0;
}


求各位大侠分析一下!!!!


轻轻的来,轻轻的走 不带走一片云彩~
游客

返回顶部