阅读:2540回复:0
内核KeWaitForSingleObject的问题
本人新手,小试一下拦截注册表的写入操作,然后将相关值发到应用,由应用判断是否允许写入,并将写入标志传给内核,同时使内核事件有信号。
现在关键是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; } 求各位大侠分析一下!!!! |
|
|