NTSTATUS GetObjectName(PVOID Object, PUNICODE_STRING *pObjectName) { POBJECT_NAME_INFORMATION ObjectNameInfo; NTSTATUS Status; ULONG ReturnLength; ObjectNameInfo = NULL; Status = ObQueryNameString(Object, ObjectNameInfo, 0, &ReturnLength); if (!NT_SUCCESS(Status) && (Status != STATUS_INFO_LENGTH_MISMATCH)) { KLErr("ObQueryNameString Object %p Status 0x%x", Object, Status); return Status; } ObjectNameInfo = NpAlloc(ReturnLength, MTAG_GEN); if (!ObjectNameInfo) return STATUS_INSUFFICIENT_RESOURCES; Status = ObQueryNameString(Object, ObjectNameInfo, ReturnLength, &ReturnLength); if (!NT_SUCCESS(Status)) { KLErr("ObQueryNameString Object %p Status 0x%x", Object, Status); NpFree(ObjectNameInfo, MTAG_GEN); return Status; } *pObjectName = &ObjectNameInfo->Name; return Status; }
/****************************************************************************\ * * NT_QueryObjectName() * * DESCRIPTION: * * Queries the name of the object (such as a device or file object). * The caller must deallocate the return value with MEM_Free. The * returned string (if not NULL) is guaranteed to be NULL terminated. * * ARGUMENTS: * * obj - the object whose name to query * \****************************************************************************/ OBJECT_NAME_INFORMATION * NT_QueryObjectName(PVOID obj) { ULONG len = 0; NTSTATUS status = ObQueryNameString(obj, NULL, 0, &len); ASSERT(status != STATUS_SUCCESS); /* Unlike the rest of the system, ObQueryNameString returns * STATUS_INFO_LENGTH_MISMATCH instead of STATUS_BUFFER_TOO_SMALL * when passed too small a buffer. We expect to get this error here. * Anything else we can't handle. */ if (status == STATUS_INFO_LENGTH_MISMATCH && len > 0) { OBJECT_NAME_INFORMATION * name = MEM_Alloc(len + sizeof(WCHAR)); if (name) { /* NOTE: ObQueryNameString may return STATUS_SUCCESS and empty * string for unnamed objects */ status = ObQueryNameString(obj, name, len, &len); if (NT_SUCCESS(status) && name->Name.MaximumLength > 0) { /* make sure it's NULL terminated */ ULONG Last = name->Name.Length/sizeof(name->Name.Buffer[0]); name->Name.Buffer[Last] = 0; return name; } MEM_Free(name); } } return NULL; }
static NTSTATUS _GetObjectName(_In_ PVOID Object, _Out_ POBJECT_NAME_INFORMATION *ObjectName) { ULONG objectNameLen = 0; POBJECT_NAME_INFORMATION tmpObjectName = NULL; NTSTATUS status = STATUS_UNSUCCESSFUL; DEBUG_ENTER_FUNCTION("Object=0x%p; ObjectName=0x%p", Object, ObjectName); *ObjectName = NULL; status = ObQueryNameString(Object, NULL, 0, &objectNameLen); if (status == STATUS_INFO_LENGTH_MISMATCH) { objectNameLen += sizeof(OBJECT_NAME_INFORMATION); tmpObjectName = (POBJECT_NAME_INFORMATION)HeapMemoryAllocPaged(objectNameLen); if (tmpObjectName != NULL) { status = ObQueryNameString(Object, tmpObjectName, objectNameLen, &objectNameLen); if (NT_SUCCESS(status)) *ObjectName = tmpObjectName; if (!NT_SUCCESS(status)) HeapMemoryFree(tmpObjectName); } else status = STATUS_INSUFFICIENT_RESOURCES; } else if (NT_SUCCESS(status)) { objectNameLen = sizeof(OBJECT_NAME_INFORMATION); tmpObjectName = (POBJECT_NAME_INFORMATION)HeapMemoryAllocPaged(objectNameLen); if (tmpObjectName != NULL) { memset(tmpObjectName, 0, objectNameLen); *ObjectName = tmpObjectName; status = STATUS_SUCCESS; } else status = STATUS_INSUFFICIENT_RESOURCES; } DEBUG_EXIT_FUNCTION("0x%x, *ObjectName=0x%p", status, *ObjectName); return status; }
NTSTATUS FltpGetObjectName(_In_ PVOID Object, _Inout_ PUNICODE_STRING ObjectName) { POBJECT_NAME_INFORMATION ObjectNameInfo = NULL; OBJECT_NAME_INFORMATION LocalNameInfo; ULONG ReturnLength; NTSTATUS Status; if (ObjectName == NULL) return STATUS_INVALID_PARAMETER; /* Get the size of the buffer required to hold the nameinfo */ Status = ObQueryNameString(Object, &LocalNameInfo, sizeof(LocalNameInfo), &ReturnLength); if (Status == STATUS_INFO_LENGTH_MISMATCH) { ObjectNameInfo = ExAllocatePoolWithTag(PagedPool, ReturnLength, FM_TAG_UNICODE_STRING); if (ObjectNameInfo == NULL) return STATUS_INSUFFICIENT_RESOURCES; /* Get the actual name info now we have the buffer to hold it */ Status = ObQueryNameString(Object, ObjectNameInfo, ReturnLength, &ReturnLength); } if (NT_SUCCESS(Status)) { /* Make sure the buffer we were passed is large enough to hold the string */ if (ObjectName->MaximumLength < ObjectNameInfo->Name.Length) { /* It wasn't, let's enlarge the buffer */ Status = FltpReallocateUnicodeString(ObjectName, ObjectNameInfo->Name.Length, FALSE); } if (NT_SUCCESS(Status)) { /* Copy the object name into the callers buffer */ RtlCopyUnicodeString(ObjectName, &ObjectNameInfo->Name); } } if (ObjectNameInfo) { ExFreePoolWithTag(ObjectNameInfo, FM_TAG_UNICODE_STRING); } return Status; }
NTSTATUS ImScsiGetControllerObject() { PDEVICE_OBJECT dev_obj; if (pMPDrvInfoGlobal->ControllerObject != NULL) { return STATUS_SUCCESS; } KdBreakPoint(); for (dev_obj = pMPDrvInfoGlobal->pDriverObj->DeviceObject; dev_obj != NULL; #pragma warning(suppress: 28175) dev_obj = dev_obj->NextDevice) { if (dev_obj->DeviceType == FILE_DEVICE_CONTROLLER) { ObReferenceObject(dev_obj); pMPDrvInfoGlobal->ControllerObject = dev_obj; #if DBG { POBJECT_NAME_INFORMATION objstr = (POBJECT_NAME_INFORMATION) ExAllocatePoolWithTag(NonPagedPool, 1024, MP_TAG_GENERAL); if (objstr != NULL) { ULONG retl; NTSTATUS status; status = ObQueryNameString(pMPDrvInfoGlobal->ControllerObject, objstr, 1024, &retl); if (NT_SUCCESS(status)) { DbgPrint("PhDskMnt::ImScsiGetControllerObject: Successfully opened '%wZ'.\n", &objstr->Name); } ExFreePoolWithTag(objstr, MP_TAG_GENERAL); } } #endif return STATUS_SUCCESS; } } DbgPrint("PhDskMnt::ImScsiGetControllerObject: Could not locate SCSI adapter device object by name.\n"); return STATUS_DEVICE_DOES_NOT_EXIST; }
BOOLEAN GetRegistryObjectCompleteName(PUNICODE_STRING pRegistryPath, PUNICODE_STRING pPartialRegistryPath, PVOID pRegistryObject) { BOOLEAN foundCompleteName = FALSE; BOOLEAN partial = FALSE; if((!MmIsAddressValid(pRegistryObject)) || (pRegistryObject == NULL)) { return FALSE; } /* Check to see if the partial name is really the complete name */ if(pPartialRegistryPath != NULL) { if((((pPartialRegistryPath->Buffer[0] == '\\') || (pPartialRegistryPath->Buffer[0] == '%')) || ((pPartialRegistryPath->Buffer[0] == 'T') && (pPartialRegistryPath->Buffer[1] == 'R') && (pPartialRegistryPath->Buffer[2] == 'Y') && (pPartialRegistryPath->Buffer[3] == '\\'))) ) { RtlUnicodeStringCopy(pRegistryPath, pPartialRegistryPath); partial = TRUE; foundCompleteName = TRUE; } } if(!foundCompleteName) { /* Query the object manager in the kernel for the complete name */ NTSTATUS status; ULONG returnedLength; PUNICODE_STRING pObjectName = NULL; status = ObQueryNameString(pRegistryObject, (POBJECT_NAME_INFORMATION)pObjectName, 0, &returnedLength ); if(status == STATUS_INFO_LENGTH_MISMATCH) { pObjectName = ExAllocatePoolWithTag(NonPagedPool, returnedLength, REGISTRY_POOL_TAG); status = ObQueryNameString(pRegistryObject, (POBJECT_NAME_INFORMATION)pObjectName, returnedLength, &returnedLength ); if(NT_SUCCESS(status)) { RtlUnicodeStringCopy(pRegistryPath, pObjectName); foundCompleteName = TRUE; } ExFreePoolWithTag(pObjectName, REGISTRY_POOL_TAG); } } //ASSERT(foundCompleteName == TRUE); return foundCompleteName; }
NTSTATUS NewZwMapViewOfSection( HANDLE SectionHandle, HANDLE ProcessHandle, PVOID *BaseAddress, ULONG ZeroBits, ULONG CommitSize, PLARGE_INTEGER SectionOffset, PSIZE_T ViewSize, SECTION_INHERIT InheritDisposition, ULONG AllocationType, ULONG Protect ) { NTSTATUS status; #ifdef DEBUG NTSTATUS rtn; PVOID Object; WCHAR buf[1024]; rtn= ObReferenceObjectByHandle(SectionHandle, 0, 0, KernelMode, &Object, NULL); if (rtn==STATUS_SUCCESS) { int bytes; rtn=ObQueryNameString(Object, (PUNICODE_STRING)buf, sizeof(buf), &bytes); ObDereferenceObject(Object); if (rtn==STATUS_SUCCESS) { WCHAR *p = ((PUNICODE_STRING)buf)->Buffer; debugOutput(L"MapViewOfSection "); debugOutput(p); if ((Protect&PAGE_READWRITE) || (Protect&PAGE_EXECUTE_READWRITE)) { swprintf(buf,L" protect: 0x%lx\n", Protect); debugOutput(buf); } debugOutput(L"\n"); } } #endif status = (OldZwMapViewOfSection)(SectionHandle, ProcessHandle, BaseAddress, ZeroBits, CommitSize, SectionOffset, ViewSize, InheritDisposition, AllocationType, Protect); return status; }
NTSTATUS RegSetValueKey( IN HANDLE KeyHandle, IN PUNICODE_STRING ValueName, IN ULONG TitleIndex, IN ULONG Type, IN PVOID Data, IN ULONG DataSize ) { WCHAR szFullPath[MAXPATHLEN] = {0}; PVOID pKeyObj = NULL; ULONG ulRet = 0; PUNICODE_STRING fullUniName = NULL; int i; ULONG nAllowd = 1; WCHAR szValueName[256] = {0}; WCHAR szValue[512] = {0}; if(FALSE == IsGuardStart()) goto allowed; if(STATUS_SUCCESS == ObReferenceObjectByHandle(KeyHandle, 0, NULL, KernelMode, &pKeyObj, NULL)) { PINNERPACK_LIST pList; LONG nSubType = 0; fullUniName = ExAllocateFromPagedLookasideList(&gRegMonLooaside); if(NULL == fullUniName) goto allowed; fullUniName->MaximumLength = MAXPATHLEN * 2; ObQueryNameString(pKeyObj, (POBJECT_NAME_INFORMATION)fullUniName, MAXPATHLEN, &ulRet); ObDereferenceObject(pKeyObj); // 转换路径 ConvertKeyPath(szFullPath, fullUniName->Buffer, MAXPATHLEN); ExFreeToPagedLookasideList(&gRegMonLooaside, fullUniName); // 复制路径 wcsncpy(szValueName, (NULL != ValueName)?ValueName->Buffer:L"" , (NULL != ValueName)?ValueName->Length:0); // 比较路径 if(FALSE == IsRegGuardPath(szFullPath, szValueName, &nSubType)) goto allowed; if(REG_SZ == Type) { wcsncpy(szValue, Data, arrayof(szValueName)); } // 到用户求请 if(FALSE != CheckRequestIsAllowed(MAKEGUARDTYPE(MASK_GUARDLITE_REGMON, nSubType) , szFullPath, szValueName, szValue)) { goto allowed; } } return STATUS_ACCESS_DENIED; allowed: return RealRegSetValueKey(KeyHandle, ValueName, TitleIndex, Type, Data, DataSize); }
int getFullPath(PWCHAR buf, USHORT bufsize, POBJECT_ATTRIBUTES oa) { NTSTATUS rtn; PVOID Object; int curlen=0; buf[0]=L'\0'; if (!oa) return 0; if (oa->RootDirectory != NULL) { rtn= ObReferenceObjectByHandle(oa->RootDirectory, 0, 0, KernelMode, &Object, NULL); if (rtn==STATUS_SUCCESS) { int bytes; rtn=ObQueryNameString(Object, (PUNICODE_STRING)buf, bufsize, &bytes); ObDereferenceObject(Object); if (rtn==STATUS_SUCCESS) { WCHAR *p = ((PUNICODE_STRING)buf)->Buffer, *q=buf; USHORT len = (((PUNICODE_STRING)buf)->Length)/sizeof(WCHAR); if ((len+2)*sizeof(WCHAR)<bufsize) { while (len-->0 && *p!=L'\0') { *q++ = *p++; ++curlen; } *q++=OBJ_NAME_PATH_SEPARATOR; ++curlen; } *q = L'\0'; } } } if (oa->ObjectName && oa->Length+(curlen+1)*sizeof(WCHAR) < bufsize) { curlen += uwcscat(buf+curlen, oa->ObjectName); } else *buf = L'\0'; return curlen; }
NTSTATUS HwndNameDriverIOControl(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp) { PIO_STACK_LOCATION stack; UCHAR *in_buffer, *out_buffer; ULONG code,ret,pid,handle_object,return_length; UCHAR buffer[1024]; PEPROCESS eprocess; HANDLE handle,hProcess,hToken; stack = IoGetCurrentIrpStackLocation(Irp); out_size = stack->Parameters.DeviceIoControl.OutputBufferLength; code = stack->Parameters.DeviceIoControl.IoControlCode; in_buffer = out_buffer = Irp->AssociatedIrp.SystemBuffer; ret = STATUS_SUCCESS; switch(code) { case IOCTL_GET_NAME_STRING: { pid = ((DIB_NAME_STRING *)in_buffer)->pid; handle = ((DIB_NAME_STRING *)in_buffer)->hwnd; ((DOB_NAME_STRING *)out_buffer)->status = 0; Irp->IoStatus.Information = sizeof(ULONG); if(NT_SUCCESS(PsLookupProcessByProcessId((PVOID)pid,&eprocess))) { KeAttachProcess(eprocess); if(NT_SUCCESS(ObReferenceObjectByHandle(handle,0x80000000,0,0, (void *)&handle_object,0))) { if(*(USHORT *)handle_object==5 && *((USHORT *)handle_object+1)==0x70) { if(return_length=handle_fobject((PFILE_OBJECT)handle_object, out_buffer)) { ((DOB_NAME_STRING *)out_buffer)->status=1; Irp->IoStatus.Information+=return_length; *((USHORT *)out_buffer+2)=(USHORT)(return_length-12); } } else { if(NT_SUCCESS(ObQueryNameString((void *)handle_object, (POBJECT_NAME_INFORMATION)buffer, sizeof(buffer),&return_length))) if(((UNICODE_STRING *)buffer)->Buffer!=NULL) { ((DOB_NAME_STRING *)out_buffer)->name.MaximumLength \ = (USHORT)out_size-20; ((DOB_NAME_STRING *)out_buffer)->name.Buffer \ = (char *)((ULONG *)out_buffer+3); if(NT_SUCCESS(RtlUnicodeStringToAnsiString( &((DOB_NAME_STRING *)out_buffer)->name, (UNICODE_STRING *)buffer,FALSE))) { ((DOB_NAME_STRING *)out_buffer)->status = 1; Irp->IoStatus.Information += 8+ ((DOB_NAME_STRING *)out_buffer)->name.Length; } } ObDereferenceObject((void *)handle_object); } } KeDetachProcess(); ObDereferenceObject((void *)eprocess); } break; } case IOCTL_GET_TOKEN_HANDLE: { hProcess = ((DIB_TOKEN_HANDLE *)in_buffer)->hwnd; ((DOB_TOKEN_HANDLE *)out_buffer)->status = 0; Irp->IoStatus.Information = sizeof(ULONG); if (NT_SUCCESS(ZwOpenProcessToken(hProcess,TOKEN_QUERY,&hToken))) { ((DOB_TOKEN_HANDLE *)out_buffer)->status = 1; ((DOB_TOKEN_HANDLE *)out_buffer)->hwnd = hToken; Irp->IoStatus.Information += 4; } break; } default: ((DOB_UNKNOWN *)out_buffer)->status = 0; Irp->IoStatus.Information = sizeof(DOB_UNKNOWN); ret = STATUS_INVALID_DEVICE_REQUEST; break; } Irp->IoStatus.Status = ret; IoCompleteRequest(Irp,IO_NO_INCREMENT); return ret; }
NTSTATUS PerfInfoFileNameRunDown ( ) /*++ Routine Description: This routine walks through multiple lists to collect the names of all files. It includes: 1. Handle table: for all file handles 2. Process Vad for all file objects mapped in VAD. 3. MmUnusedSegment List 4. CcDirtySharedCacheMapList & CcCleanSharedCacheMapList Arguments: None. --*/ { PEPROCESS Process; ULONG AllocateBytes; PFILE_OBJECT *FileObjects; PFILE_OBJECT *File; PERFINFO_ENTRY_TABLE HashTable; extern POBJECT_TYPE IoFileObjectType; POBJECT_NAME_INFORMATION FileNameInfo; ULONG ReturnLen; NTSTATUS Status; LONG i; // // First create a temporary hash table to build the list of // files to walk through // AllocateBytes = PAGE_SIZE + sizeof(PVOID) * IoFileObjectType->TotalNumberOfObjects; // // Run up to page boundary // AllocateBytes = PERFINFO_ROUND_UP(AllocateBytes, PAGE_SIZE); HashTable.Table = ExAllocatePoolWithTag(NonPagedPool, AllocateBytes, PERFPOOLTAG); if (HashTable.Table == NULL) { return STATUS_NO_MEMORY; } else { // // Allocation Succeeded // HashTable.NumberOfEntries = AllocateBytes / sizeof(PVOID); RtlZeroMemory(HashTable.Table, AllocateBytes); } // // Allocate Buffers for FileNames // FileNameInfo = ExAllocatePoolWithTag (NonPagedPool, MAX_FILENAME_TO_LOG, PERFPOOLTAG); if (FileNameInfo == NULL) { ExFreePool(HashTable.Table); return STATUS_NO_MEMORY; } // // Walk through the Cc SharedCacheMapList // CcPerfFileRunDown(&HashTable); // // Now, walk through each process // for (Process = PsGetNextProcess (NULL); Process != NULL; Process = PsGetNextProcess (Process)) { // // First Walk the VAD tree // FileObjects = MmPerfVadTreeWalk(Process); if (FileObjects != NULL) { File = FileObjects; while (*File != NULL) { PerfInfoAddToFileHash(&HashTable, *File); ObDereferenceObject(*File); File += 1; } ExFreePool(FileObjects); } // // Next, walk the handle Table // ObPerfHandleTableWalk (Process, &HashTable); } // // Walk through the kernel handle table; // ObPerfHandleTableWalk(NULL, &HashTable); // // Walk through the MmUnusedSegmentList; // FileObjects = MmPerfUnusedSegmentsEnumerate(); if (FileObjects != NULL) { File = FileObjects; while (*File != NULL) { PerfInfoAddToFileHash(&HashTable, *File); ObDereferenceObject(*File); File += 1; } ExFreePool(FileObjects); } // // Now we have walked through all list. // Log the filenames and dereference the objects. // for (i = 0; i < HashTable.NumberOfEntries; i++) { if (HashTable.Table[i]) { PFILE_OBJECT FileObject = HashTable.Table[i]; Status = ObQueryNameString( FileObject, FileNameInfo, MAX_FILENAME_TO_LOG, &ReturnLen ); if (NT_SUCCESS (Status)) { PerfInfoLogFileName(FileObject, &FileNameInfo->Name); } ObDereferenceObject(FileObject); } } // // Free the pool reserved. // ExFreePool(HashTable.Table); ExFreePool(FileNameInfo); return STATUS_SUCCESS; }
NTSTATUS RegistryCallback(IN PVOID CallbackContext, IN PVOID Argument1, IN PVOID Argument2) { NTSTATUS ntStatus; PDEVICE_CONTEXT pContext = (PDEVICE_CONTEXT) CallbackContext; REG_NOTIFY_CLASS Action = (REG_NOTIFY_CLASS) Argument1; POBJECT_NAME_INFORMATION ObjectNameInfo; ULONG ReturnLength,ReturnLength1; UNICODE_STRING *path_str = NULL; UNICODE_STRING *key = NULL; UNICODE_STRING *value = NULL; UNICODE_STRING *data = NULL; UNICODE_STRING unicode_registry ; UNICODE_STRING KeyInformation; UNICODE_STRING *unicode_test=NULL; ANSI_STRING key_ansi; ANSI_STRING value_ansi; ANSI_STRING temp_ansi; ANSI_STRING pathname_ansi; size_t size = 9; ProcessInformationFile process; ProcessInformation process_uni; char security_sbject[525]; char droit[324]; char droit_temp[300]; char buf_temp[1024]; int bool =0; PAGED_CODE(); if( ExGetPreviousMode() == KernelMode) return STATUS_SUCCESS; RtlZeroMemory(&security_sbject, sizeof(security_sbject)); RtlZeroMemory(&droit, sizeof(droit)); RtlZeroMemory(&droit_temp, sizeof(droit_temp)); RtlZeroMemory(&buf_temp, sizeof(buf_temp)); switch (Action) { case RegNtPreDeleteKey: { PREG_DELETE_KEY_INFORMATION pInfo = (PREG_DELETE_KEY_INFORMATION) Argument2; __try{ ntStatus = ObQueryNameString(pInfo->Object, (POBJECT_NAME_INFORMATION)key, 0, &ReturnLength); key = (PUNICODE_STRING)ExAllocatePoolWithTag(NonPagedPool, ReturnLength, 0); if (ntStatus == STATUS_INFO_LENGTH_MISMATCH) { if (key) { ntStatus = ObQueryNameString(pInfo->Object, (POBJECT_NAME_INFORMATION)key, ReturnLength, &ReturnLength); } else return STATUS_SUCCESS; } process = GetProcessInfoFile(); if(process.pid == 4) { sprintf(security_sbject,"system_u:system_r:system_t"); RtlZeroMemory(&process.pathname, sizeof(process.pathname)); sprintf(process.pathname, "System"); } else GetSecurityContextSubject(process, security_sbject); GetSecurityContextSubject(process, security_sbject); RtlUnicodeStringToAnsiString(&key_ansi, key, TRUE); sprintf(droit,"delete "); bool = 1; } __except(EXCEPTION_EXECUTE_HANDLER) { ntStatus=GetExceptionCode(); DbgPrint("Exception RegNtPreDeleteKey : %x\n", ntStatus); } ExFreePoolWithTag(key,0); break; } case RegNtPreCreateKeyEx: { PREG_CREATE_KEY_INFORMATION pInfo = (PREG_CREATE_KEY_INFORMATION) Argument2; __try{ ntStatus = ObQueryNameString(pInfo->RootObject, (POBJECT_NAME_INFORMATION)path_str, 0, &ReturnLength); path_str = (PUNICODE_STRING)ExAllocatePoolWithTag(NonPagedPool, ReturnLength, 0); if (ntStatus == STATUS_INFO_LENGTH_MISMATCH) { if (path_str) { ntStatus = ObQueryNameString(pInfo->RootObject, (POBJECT_NAME_INFORMATION)path_str, ReturnLength, &ReturnLength); } else return STATUS_SUCCESS; } process_uni = GetProcessInfo(); if(process_uni.pid == 4) return STATUS_SUCCESS; else GetSecurityContextSubjectReg(process_uni.name,security_sbject); GetDroit(droit, pInfo); //sprintf(droit, "create_key_function %s", droit_temp); RtlUnicodeStringToAnsiString(&key_ansi, pInfo->CompleteName, TRUE); WriteInLog(droit,process_uni.pid, process_uni.name, process_uni.ppid , key_ansi.Buffer ,security_sbject , "system_u:object_r:registry_t", "registry",0,0); } __except(EXCEPTION_EXECUTE_HANDLER) { ntStatus=GetExceptionCode(); DbgPrint("Exception RegNtPreCreateKeyEx : %x\n", ntStatus); } // ExFreePoolWithTag(path_str,0); break; } case RegNtSetValueKey: { PREG_SET_VALUE_KEY_INFORMATION pInfo = (PREG_SET_VALUE_KEY_INFORMATION) Argument2; __try{ ntStatus = ObQueryNameString(pInfo->Object, (POBJECT_NAME_INFORMATION)key, 0, &ReturnLength); key = (PUNICODE_STRING)ExAllocatePoolWithTag(NonPagedPool, ReturnLength, 1); if (ntStatus == STATUS_INFO_LENGTH_MISMATCH) { if (key) { ntStatus = ObQueryNameString(pInfo->Object, (POBJECT_NAME_INFORMATION)key, ReturnLength, &ReturnLength); process_uni = GetProcessInfo(); if(process_uni.pid == 4) return STATUS_SUCCESS; else GetSecurityContextSubjectReg(process_uni.name,security_sbject); RtlUnicodeStringToAnsiString(&key_ansi, key, TRUE); sprintf(droit, "setvaluekey "); DbgPrint("%wZ \n", pInfo->ValueName); WriteInLog(droit,process_uni.pid, process_uni.name, process_uni.ppid , key_ansi.Buffer ,security_sbject , "system_u:object_r:registry_t", "registry",0,0); } } if(key) ExFreePoolWithTag(key,1); } __except(EXCEPTION_EXECUTE_HANDLER) { ntStatus=GetExceptionCode(); DbgPrint("Exception RegNtSetValueKey : %x\n", ntStatus); } break; } case RegNtQueryValueKey: { PREG_QUERY_VALUE_KEY_INFORMATION pInfo = (PREG_QUERY_VALUE_KEY_INFORMATION) Argument2; __try { ntStatus = ObQueryNameString(pInfo->Object, (POBJECT_NAME_INFORMATION)key, 0, &ReturnLength); key = (PUNICODE_STRING)ExAllocatePoolWithTag(NonPagedPool, ReturnLength, 1); if (ntStatus == STATUS_INFO_LENGTH_MISMATCH) { if (key) { ntStatus = ObQueryNameString(pInfo->Object, (POBJECT_NAME_INFORMATION)key, ReturnLength, &ReturnLength); process_uni = GetProcessInfo(); if(process_uni.pid == 4) return STATUS_SUCCESS; else GetSecurityContextSubjectReg(process_uni.name,security_sbject); switch(pInfo->KeyValueInformationClass) { case 0: {sprintf(droit, "KeyValueBasicInformation "); break;} case 1: {sprintf(droit, "KeyValueFullInformation "); break;} case 2: {sprintf(droit, "KeyValuePartialInformation "); break;} case 3: {sprintf(droit, "KeyValueFullInformationAlign64 "); break;} case 4: {sprintf(droit, "KeyValuePartialInformationAlign64 "); break;} case 5: {sprintf(droit, "MaxKeyValueInfoClass "); break;} default: break; } RtlUnicodeStringToAnsiString(&key_ansi, key, TRUE); // bool = 1; WriteInLog(droit,process_uni.pid, process_uni.name, process_uni.ppid , key_ansi.Buffer ,security_sbject , "system_u:object_r:registry_t", "registry",0,0); if(key) ExFreePoolWithTag(key,1); } } } __except(EXCEPTION_EXECUTE_HANDLER) { ntStatus=GetExceptionCode(); DbgPrint("Exception : %x\n", ntStatus); } break; } case RegNtQueryKey: { PREG_QUERY_KEY_INFORMATION pInfo = (PREG_QUERY_KEY_INFORMATION) Argument2; __try{ ntStatus = ObQueryNameString(pInfo->Object, (POBJECT_NAME_INFORMATION)key, 0, &ReturnLength); key = (PUNICODE_STRING)ExAllocatePoolWithTag(NonPagedPool, ReturnLength, 1); if (ntStatus == STATUS_INFO_LENGTH_MISMATCH) { if (key) { ntStatus = ObQueryNameString(pInfo->Object, (POBJECT_NAME_INFORMATION)key, ReturnLength, &ReturnLength); process_uni = GetProcessInfo(); if(process_uni.pid == 4) return STATUS_SUCCESS; else GetSecurityContextSubjectReg(process_uni.name,security_sbject); switch(pInfo->KeyInformationClass) { case 0: {sprintf(droit, "KeyBasicInformation "); break;} case 1: {sprintf(droit, "KeyNodeInformation "); break;} case 2: {sprintf(droit, "KeyFullInformation "); break;} case 3: {sprintf(droit, "KeyNameInformation "); break;} case 4: {sprintf(droit, "KeyCachedInformation "); break;} case 5: {sprintf(droit, "KeyFlagsInformation "); break;} case 6: {sprintf(droit, "KeyVirtualizationInformation "); break;} case 7: {sprintf(droit, "KeyHandleTagsInformation "); break;} case 8: {sprintf(droit, "MaxKeyInfoClass "); break;} default: break; } RtlUnicodeStringToAnsiString(&key_ansi, key, TRUE); // RtlUnicodeStringToAnsiString(&pathname_ansi, process_uni.pathname, TRUE); WriteInLog(droit,process_uni.pid, process_uni.name, process_uni.ppid , key_ansi.Buffer ,security_sbject , "system_u:object_r:registry_t", "registry",0,0); // bool = 1; // if(key) // ExFreePoolWithTag(key,1); } } } __except(EXCEPTION_EXECUTE_HANDLER) { ntStatus=GetExceptionCode(); DbgPrint("Exception : %x\n", ntStatus); } break; } case RegNtPreOpenKeyEx: { PREG_CREATE_KEY_INFORMATION pInfo = (PREG_CREATE_KEY_INFORMATION) Argument2; __try{ process_uni = GetProcessInfo(); if(process_uni.pid == 4) return STATUS_SUCCESS; RtlUnicodeStringToAnsiString(&pathname_ansi, process_uni.pathname, TRUE); GetSecurityContextSubjectReg(process_uni.name,security_sbject); GetDroit(droit, pInfo); //sprintf(droit, "open_key_function %s", droit_temp); RtlUnicodeStringToAnsiString(&key_ansi, pInfo->CompleteName, TRUE); // bool = 1; WriteInLog(droit,process_uni.pid, process_uni.name, process_uni.ppid , key_ansi.Buffer ,security_sbject , "system_u:object_r:registry_t", "registry",0,0); } __except(EXCEPTION_EXECUTE_HANDLER) { ntStatus=GetExceptionCode(); DbgPrint("Exception : %x\n", ntStatus); } break; } default: { break; } } if(bool == 1) { WriteInLog(droit, process.pid, process.pathname, process.ppid , key_ansi.Buffer ,security_sbject , "system_u:object_r:registry_t", "registry", 0,0); } return STATUS_SUCCESS; }
NTSTATUS DrGetDevicePropertyInstallState( IN PDEVICE_OBJECT DeviceObject, IN ULONG BufferLength, OUT PVOID PropertyBuffer, OUT PULONG ResultLength ) { NTSTATUS status; HANDLE devparamRegKey; HANDLE devInstRegKey; UNICODE_STRING valueName; UCHAR keyValueBuffer[KVLEN_PARTIAL]; PKEY_VALUE_PARTIAL_INFORMATION keyValue; ULONG resultLength; PULONG configFlags; DEVICE_INSTALL_STATE deviceInstallState; PVOID Object; UCHAR ObjectNameBuffer[512]; POBJECT_NAME_INFORMATION ObjectNameInfo; OBJECT_ATTRIBUTES objectAttributes; // // init // devInstRegKey = NULL; devparamRegKey = NULL; keyValue = (PKEY_VALUE_PARTIAL_INFORMATION)keyValueBuffer; if(BufferLength < sizeof(DEVICE_INSTALL_STATE)) { return STATUS_INSUFFICIENT_RESOURCES; } // // open the device registry's parameter key // status = IoOpenDeviceRegistryKey( DeviceObject, PLUGPLAY_REGKEY_DEVICE, KEY_QUERY_VALUE|KEY_ENUMERATE_SUB_KEYS, &devparamRegKey ); if(!NT_SUCCESS(status)) { devInstRegKey = NULL; goto cleanup; } status = ObReferenceObjectByHandle( devparamRegKey, GENERIC_READ, NULL, KernelMode, &Object, NULL ); if(!NT_SUCCESS(status)) { goto cleanup; } ObjectNameInfo = (POBJECT_NAME_INFORMATION)ObjectNameBuffer; status = ObQueryNameString(Object, ObjectNameInfo, sizeof(ObjectNameBuffer), &resultLength ); ObDereferenceObject(Object); if(!NT_SUCCESS(status) || ObjectNameInfo->Name.Buffer == NULL) { goto cleanup; } KDPrint(1, ("Device parameter path: %ws. len=%d\n", ObjectNameInfo->Name.Buffer,ObjectNameInfo->Name.Length)); ASSERT(ObjectNameInfo->Name.Length < sizeof(ObjectNameBuffer) - 20); // trim down to the first parent. for(; ObjectNameInfo->Name.Length > 1; ObjectNameInfo->Name.Length-=sizeof(WCHAR) ) { if( ObjectNameInfo->Name.Buffer[ObjectNameInfo->Name.Length/sizeof(WCHAR) - 1] == '\\') { ObjectNameInfo->Name.Length-=sizeof(WCHAR); KDPrint(1, ("Trimed at the index %d\n", ObjectNameInfo->Name.Length)); break; } } KDPrint(1, ("Device parameter path: %ws. len=%d\n", ObjectNameInfo->Name.Buffer,ObjectNameInfo->Name.Length)); if(ObjectNameInfo->Name.Length <= 1) { goto cleanup; } // // Open device registry. // InitializeObjectAttributes( &objectAttributes, &ObjectNameInfo->Name, OBJ_CASE_INSENSITIVE|OBJ_KERNEL_HANDLE, NULL, NULL ); status = ZwOpenKey(&devInstRegKey, KEY_QUERY_VALUE|KEY_ENUMERATE_SUB_KEYS, &objectAttributes); if(!NT_SUCCESS(status)) { goto cleanup; } // // Query the value of CONFIGFLAGS // RtlInitUnicodeString(&valueName, REGSTR_VAL_CONFIGFLAGS); status = ZwQueryValueKey( devInstRegKey, &valueName, KeyValuePartialInformation, keyValue, KVLEN_PARTIAL, &resultLength ); if(!NT_SUCCESS(status)) { goto cleanup; } if(keyValue->Type != REG_DWORD) { goto cleanup; } if(keyValue->DataLength != sizeof(ULONG)) { goto cleanup; } // // determine deviceInstallState // // TODO: If the device object is root device, // always return InstallStateInstalled. // configFlags = (PULONG)keyValue->Data; if ((*configFlags) & CONFIGFLAG_REINSTALL) { deviceInstallState = InstallStateNeedsReinstall; } else if ((*configFlags) & CONFIGFLAG_FAILEDINSTALL) { deviceInstallState = InstallStateFailedInstall; } else if ((*configFlags) & CONFIGFLAG_FINISH_INSTALL) { deviceInstallState = InstallStateFinishInstall; } else { deviceInstallState = InstallStateInstalled; } // // set the result // (*(PDEVICE_INSTALL_STATE)PropertyBuffer) = deviceInstallState; *ResultLength = sizeof(DEVICE_INSTALL_STATE); cleanup: if(devInstRegKey) ZwClose(devInstRegKey); if(devparamRegKey) ZwClose(devparamRegKey); return status; }
PUNICODE_STRING GingkoGetFileName( IN PFILE_OBJECT FileObject, IN NTSTATUS CreateStatus, IN OUT PGET_NAME_CONTROL NameControl ) { POBJECT_NAME_INFORMATION nameInfo; NTSTATUS status; ULONG size; ULONG bufferSize; ULONG InitSize = sizeof(OBJECT_NAME_INFORMATION) + 512 * sizeof(WCHAR); if( NameControl == NULL ) { return NULL; } // // Mark we have not allocated the buffer // NameControl->AllocatedBuffer = ExAllocatePoolWithTag( NonPagedPool, InitSize, GINGKO_POOL_TAG ); // // Use the small buffer in the structure (that will handle most cases) // for the name // if( NameControl->AllocatedBuffer == NULL ) { return NULL; } RtlZeroMemory( NameControl->AllocatedBuffer, InitSize ); nameInfo = (POBJECT_NAME_INFORMATION)NameControl->AllocatedBuffer; bufferSize = InitSize; nameInfo->Name.Length = 0; nameInfo->Name.MaximumLength = (USHORT)InitSize - sizeof(OBJECT_NAME_INFORMATION); // // If the open succeeded, get the name of the file, if it // failed, get the name of the device. // status = ObQueryNameString( FileObject , nameInfo, (USHORT)InitSize - sizeof(OBJECT_NAME_INFORMATION), &size ); // // See if the buffer was to small // if (status == STATUS_INFO_LENGTH_MISMATCH) { // // The buffer was too small, allocate one big enough // if( NameControl->AllocatedBuffer != NULL ) { ExFreePoolWithTag( NameControl->AllocatedBuffer, GINGKO_POOL_TAG ); } bufferSize = sizeof(OBJECT_NAME_INFORMATION) + size + sizeof(WCHAR); NameControl->AllocatedBuffer = ExAllocatePoolWithTag( NonPagedPool, bufferSize, GINGKO_POOL_TAG ); if (NULL == NameControl->AllocatedBuffer) { // // Failed allocating a buffer, return an empty string for the name // return NULL; } // // Set the allocated buffer and get the name again // nameInfo = (POBJECT_NAME_INFORMATION)NameControl->AllocatedBuffer; nameInfo->Name.Length = 0; nameInfo->Name.MaximumLength = (USHORT)bufferSize - sizeof(OBJECT_NAME_INFORMATION); status = ObQueryNameString( FileObject, nameInfo, (USHORT)bufferSize - sizeof(OBJECT_NAME_INFORMATION), &size ); } return &nameInfo->Name; }
VOID IopErrorLogThread( IN PVOID StartContext ) /*++ Routine Description: This is the main loop for the I/O error log thread which executes in the system process context. This routine is started when the system is initialized. Arguments: StartContext - Startup context; not used. Return Value: None. --*/ { PERROR_LOG_ENTRY errorLogEntry; UNICODE_STRING nameString; PLIST_ENTRY listEntry; PIO_ERROR_LOG_MESSAGE errorMessage; NTSTATUS status; PELF_PORT_MSG portMessage; PCHAR objectName; ULONG messageLength; ULONG driverNameLength; ULONG deviceNameLength; ULONG objectNameLength; ULONG remainingLength; ULONG stringLength; CHAR nameBuffer[IO_ERROR_NAME_LENGTH+sizeof( OBJECT_NAME_INFORMATION )]; PDRIVER_OBJECT driverObject; POBJECT_NAME_INFORMATION nameInformation; PIO_ERROR_LOG_PACKET errorData; PWSTR string; PAGED_CODE(); UNREFERENCED_PARAMETER( StartContext ); // // Check to see whether a connection has been made to the error log // port. If the port is not connected return. // if (!IopErrorLogConnectPort()) { // // The port could not be connected. A timer was started that will // try again later. // return; } // // Allocate and zero the port message structure, include space for the // name of the device and driver. // messageLength = IO_ERROR_LOG_MESSAGE_LENGTH; portMessage = ExAllocatePool(PagedPool, messageLength); if (portMessage == NULL) { // // The message buffer could not be allocated. Request that // the error log thread routine be called again later. // IopErrorLogQueueRequest(); return; } RtlZeroMemory( portMessage, sizeof( *portMessage ) ); portMessage->MessageType = IO_ERROR_LOG; errorMessage = &portMessage->u.IoErrorLogMessage; nameInformation = (PVOID) &nameBuffer; // // Now enter the main loop for this thread. This thread performs the // following operations: // // 1) If a connection has been made to the error log port, dequeue a // packet from the queue head and attempt to send it to the port. // // 2) If the send works, loop sending packets until there are no more // packets; otherwise, indicate that the connection has been broken, // cleanup, place the packet back onto the head of the queue and // return. // // 3) After all the packets are sent clear the pending variable and // return. // for (;;) { // // Loop dequeueing packets from the queue head and attempt to send // each to the port. // // If the send works, continue looping until there are no more packets. // Otherwise, indicate that the connection has been broken, cleanup, // place the packet back onto the head of the queue, and start from the // top of the loop again. // if (!(listEntry = IopErrorLogGetEntry())) { break; } errorLogEntry = CONTAINING_RECORD( listEntry, ERROR_LOG_ENTRY, ListEntry ); // // The size of errorLogEntry is ERROR_LOG_ENTRY + // IO_ERROR_LOG_PACKET + (Extra Dump data). The size of the // initial message length should be IO_ERROR_LOG_MESSAGE + // (Extra Dump data), since IO_ERROR_LOG_MESSAGE contains an // IO_ERROR_LOG_PACKET. Using the above calculations set the // message length. // messageLength = sizeof( IO_ERROR_LOG_MESSAGE ) - sizeof( ERROR_LOG_ENTRY ) - sizeof( IO_ERROR_LOG_PACKET ) + errorLogEntry->Size; errorData = (PIO_ERROR_LOG_PACKET) (errorLogEntry + 1); // // Copy the error log packet and the extra data to the message. // RtlMoveMemory( &errorMessage->EntryData, errorData, errorLogEntry->Size - sizeof( ERROR_LOG_ENTRY ) ); errorMessage->TimeStamp = errorLogEntry->TimeStamp; errorMessage->Type = IO_TYPE_ERROR_MESSAGE; // // Add the driver and device name string. These strings go // before the error log strings. Just write over the current // strings and they will be recopied later. // if (errorData->NumberOfStrings != 0) { // // Start the driver and device strings where the current // strings start. // objectName = (PCHAR) (&errorMessage->EntryData) + errorData->StringOffset; } else { // // Put the driver and device strings at the end of the // data. // objectName = (PCHAR) errorMessage + messageLength; } // // Make sure the driver offset starts on an even bountry. // objectName = (PCHAR) ((ULONG_PTR) (objectName + sizeof(WCHAR) - 1) & ~(ULONG_PTR)(sizeof(WCHAR) - 1)); errorMessage->DriverNameOffset = (ULONG)(objectName - (PCHAR) errorMessage); remainingLength = (ULONG)((PCHAR) portMessage + IO_ERROR_LOG_MESSAGE_LENGTH - objectName); // // Calculate the length of the driver name and // the device name. If the driver object has a name then get // it from there; otherwise try to query the device object. // driverObject = errorLogEntry->DriverObject; driverNameLength = 0; if (driverObject != NULL) { if (driverObject->DriverName.Buffer != NULL) { nameString.Buffer = driverObject->DriverName.Buffer; driverNameLength = driverObject->DriverName.Length; } if (driverNameLength == 0) { // // Try to query the driver object for a name. // status = ObQueryNameString( driverObject, nameInformation, IO_ERROR_NAME_LENGTH + sizeof( OBJECT_NAME_INFORMATION ), &objectNameLength ); if (!NT_SUCCESS( status ) || !nameInformation->Name.Length) { // // No driver name was available. // driverNameLength = 0; } else { nameString = nameInformation->Name; } } } else { // // If no driver object, this message must be from the // kernel. We need to point the eventlog service to // an event message file containing ntstatus messages, // ie, ntdll, we do this by claiming this event is an // application popup. // nameString.Buffer = L"Application Popup"; driverNameLength = wcslen(nameString.Buffer) * sizeof(WCHAR); } if (driverNameLength != 0 ) { // // Pick out the module name. // string = nameString.Buffer + (driverNameLength / sizeof(WCHAR)); driverNameLength = sizeof(WCHAR); string--; while (*string != L'\\' && string != nameString.Buffer) { string--; driverNameLength += sizeof(WCHAR); } if (*string == L'\\') { string++; driverNameLength -= sizeof(WCHAR); } // // Ensure there is enough room for the driver name. // Save space for 3 NULLs one for the driver name, // one for the device name and one for strings. // if (driverNameLength > remainingLength - (3 * sizeof(WCHAR))) { driverNameLength = remainingLength - (3 * sizeof(WCHAR)); } RtlMoveMemory( objectName, string, driverNameLength ); } // // Add a null after the driver name even if there is no // driver name. // *((PWSTR) (objectName + driverNameLength)) = L'\0'; driverNameLength += sizeof(WCHAR); // // Determine where the next string goes. // objectName += driverNameLength; remainingLength -= driverNameLength; errorMessage->EntryData.StringOffset = (USHORT)(objectName - (PCHAR) errorMessage); if (errorLogEntry->DeviceObject != NULL) { status = ObQueryNameString( errorLogEntry->DeviceObject, nameInformation, IO_ERROR_NAME_LENGTH + sizeof( OBJECT_NAME_INFORMATION ) - driverNameLength, &objectNameLength ); if (!NT_SUCCESS( status ) || !nameInformation->Name.Length) { // // No device name was available. Add a Null string. // nameInformation->Name.Length = 0; nameInformation->Name.Buffer = L"\0"; } // // No device name was available. Add a Null string. // Always add a device name string so that the // insertion string counts are correct. // } else { // // No device name was available. Add a Null string. // Always add a device name string so that the // insertion string counts are correct. // nameInformation->Name.Length = 0; nameInformation->Name.Buffer = L"\0"; } deviceNameLength = nameInformation->Name.Length; // // Ensure there is enough room for the device name. // Save space for a NULL. // if (deviceNameLength > remainingLength - (2 * sizeof(WCHAR))) { deviceNameLength = remainingLength - (2 * sizeof(WCHAR)); } RtlMoveMemory( objectName, nameInformation->Name.Buffer, deviceNameLength ); // // Add a null after the device name even if there is no // device name. // *((PWSTR) (objectName + deviceNameLength)) = L'\0'; deviceNameLength += sizeof(WCHAR); // // Update the string count for the device object. // errorMessage->EntryData.NumberOfStrings++; objectName += deviceNameLength; remainingLength -= deviceNameLength; if (errorData->NumberOfStrings) { stringLength = errorLogEntry->Size - sizeof( ERROR_LOG_ENTRY ) - errorData->StringOffset; // // Ensure there is enough room for the strings. // Save space for a NULL. // if (stringLength > remainingLength - sizeof(WCHAR)) { messageLength -= stringLength - remainingLength; stringLength = remainingLength - sizeof(WCHAR); } // // Copy the strings to the end of the message. // RtlMoveMemory( objectName, (PCHAR) errorData + errorData->StringOffset, stringLength ); // // Add a null after the strings // // *((PWSTR) (objectName + stringLength)) = L'\0'; } // // Update the message length. // errorMessage->DriverNameLength = (USHORT) driverNameLength; messageLength += deviceNameLength + driverNameLength; errorMessage->Size = (USHORT) messageLength; messageLength += FIELD_OFFSET ( ELF_PORT_MSG, u ) - FIELD_OFFSET (ELF_PORT_MSG, MessageType); portMessage->PortMessage.u1.s1.TotalLength = (USHORT) (sizeof( PORT_MESSAGE ) + messageLength); portMessage->PortMessage.u1.s1.DataLength = (USHORT) (messageLength); status = NtRequestPort( ErrorLogPort, (PPORT_MESSAGE) portMessage ); if (!NT_SUCCESS( status )) { // // The send failed. Place the packet back onto the head of // the error log queue, forget the current connection since // it no longer works, and close the handle to the port. // Set a timer up for another attempt later. // Finally, exit the loop since there is no connection // to do any work on. // NtClose( ErrorLogPort ); IopErrorLogRequeueEntry( &errorLogEntry->ListEntry ); IopErrorLogQueueRequest(); break; } else { // // The send worked fine. Free the packet and the update // the allocation count. // ExInterlockedAddUlong( &IopErrorLogAllocation, (ULONG) ( -errorLogEntry->Size ), &IopErrorLogAllocationLock ); // // Dereference the object pointers now that the name has been // captured. // if (errorLogEntry->DeviceObject != NULL) { ObDereferenceObject( errorLogEntry->DeviceObject ); } if (driverObject != NULL) { ObDereferenceObject( errorLogEntry->DriverObject ); } ExFreePool( errorLogEntry ); } // if } // for // // Finally, free the message buffer and return. // ExFreePool(portMessage); }
VOID NTAPI IopLogWorker(IN PVOID Parameter) { PELF_API_MSG Message; PIO_ERROR_LOG_MESSAGE ErrorMessage; PLIST_ENTRY ListEntry; PERROR_LOG_ENTRY LogEntry; PIO_ERROR_LOG_PACKET Packet; PCHAR StringBuffer; ULONG RemainingLength; PDRIVER_OBJECT DriverObject; ULONG DriverNameLength = 0, DeviceNameLength; UNICODE_STRING DriverNameString; NTSTATUS Status; UCHAR Buffer[256]; POBJECT_NAME_INFORMATION ObjectNameInfo = (POBJECT_NAME_INFORMATION)&Buffer; POBJECT_NAME_INFORMATION PoolObjectNameInfo = NULL; ULONG ReturnedLength, MessageLength; PWCHAR p; ULONG ExtraStringLength; PAGED_CODE(); /* Connect to the port */ if (!IopConnectLogPort()) return; /* Allocate the message */ Message = ExAllocatePool(PagedPool, IO_ERROR_LOG_MESSAGE_LENGTH); if (!Message) { /* Couldn't allocate, try again */ IopRestartLogWorker(); return; } /* Copy the message */ RtlZeroMemory(Message, sizeof(ELF_API_MSG)); /* Get the actual I/O Structure */ ErrorMessage = &Message->IoErrorMessage; /* Start loop */ while (TRUE) { /* Get an entry */ ListEntry = IopGetErrorLogEntry(); if (!ListEntry) break; LogEntry = CONTAINING_RECORD(ListEntry, ERROR_LOG_ENTRY, ListEntry); /* Get pointer to the log packet */ Packet = (PIO_ERROR_LOG_PACKET)((ULONG_PTR)LogEntry + sizeof(ERROR_LOG_ENTRY)); /* Calculate the total length of the message only */ MessageLength = sizeof(IO_ERROR_LOG_MESSAGE) - sizeof(ERROR_LOG_ENTRY) - sizeof(IO_ERROR_LOG_PACKET) + LogEntry->Size; /* Copy the packet */ RtlCopyMemory(&ErrorMessage->EntryData, Packet, LogEntry->Size - sizeof(ERROR_LOG_ENTRY)); /* Set the timestamp and time */ ErrorMessage->TimeStamp = LogEntry->TimeStamp; ErrorMessage->Type = IO_TYPE_ERROR_MESSAGE; /* Check if this message has any strings */ if (Packet->NumberOfStrings) { /* String buffer is after the current strings */ StringBuffer = (PCHAR)&ErrorMessage->EntryData + Packet->StringOffset; } else { /* Otherwise, string buffer is at the end */ StringBuffer = (PCHAR)ErrorMessage + MessageLength; } /* Align the buffer */ StringBuffer = ALIGN_UP_POINTER(StringBuffer, WCHAR); /* Set the offset for the driver's name to the current buffer */ ErrorMessage->DriverNameOffset = (ULONG)(StringBuffer - (PCHAR)ErrorMessage); /* Check how much space we have left for the device string */ RemainingLength = (ULONG)((ULONG_PTR)Message + IO_ERROR_LOG_MESSAGE_LENGTH - (ULONG_PTR)StringBuffer); /* Now check if there is a driver object */ DriverObject = LogEntry->DriverObject; if (DriverObject) { /* Check if the driver has a name */ if (DriverObject->DriverName.Buffer) { /* Use its name */ DriverNameString.Buffer = DriverObject->DriverName.Buffer; DriverNameLength = DriverObject->DriverName.Length; } else DriverNameString.Buffer = NULL; /* Check if there isn't a valid name*/ if (!DriverNameLength) { /* Query the name directly */ Status = ObQueryNameString(DriverObject, ObjectNameInfo, sizeof(Buffer), &ReturnedLength); if (!(NT_SUCCESS(Status)) || !(ObjectNameInfo->Name.Length)) { /* We don't have a name */ DriverNameLength = 0; } } } else { /* Use default name */ DriverNameString.Buffer = L"Application Popup"; DriverNameLength = (ULONG)wcslen(DriverNameString.Buffer) * sizeof(WCHAR); } /* Check if we have a driver name by here */ if (DriverNameLength) { /* Skip to the end of the driver's name */ p = &DriverNameString.Buffer[DriverNameLength / sizeof(WCHAR)]; /* Now we'll walk backwards and assume the minimum size */ DriverNameLength = sizeof(WCHAR); p--; while ((*p != L'\\') && (p != DriverNameString.Buffer)) { /* No backslash found, keep going */ p--; DriverNameLength += sizeof(WCHAR); } /* Now we probably hit the backslash itself, skip past it */ if (*p == L'\\') { p++; DriverNameLength -= sizeof(WCHAR); } /* * Now make sure that the driver name fits in our buffer, minus 3 * NULL chars, and copy the name in our string buffer */ DriverNameLength = min(DriverNameLength, RemainingLength - 3 * sizeof(UNICODE_NULL)); RtlCopyMemory(StringBuffer, p, DriverNameLength); } /* Null-terminate the driver name */ *((PWSTR)(StringBuffer + DriverNameLength)) = L'\0'; DriverNameLength += sizeof(WCHAR); /* Go to the next string buffer position */ StringBuffer += DriverNameLength; RemainingLength -= DriverNameLength; /* Update the string offset and check if we have a device object */ ErrorMessage->EntryData.StringOffset = (USHORT) ((ULONG_PTR)StringBuffer - (ULONG_PTR)ErrorMessage); if (LogEntry->DeviceObject) { /* We do, query its name */ Status = ObQueryNameString(LogEntry->DeviceObject, ObjectNameInfo, sizeof(Buffer), &ReturnedLength); if (!NT_SUCCESS(Status) || (ObjectNameInfo->Name.Length == 0)) { /* Setup an empty name */ ObjectNameInfo->Name.Length = 0; ObjectNameInfo->Name.Buffer = L""; /* Check if we failed because our buffer wasn't large enough */ if (Status == STATUS_INFO_LENGTH_MISMATCH) { /* Then we'll allocate one... we really want this name! */ PoolObjectNameInfo = ExAllocatePoolWithTag(PagedPool, ReturnedLength, TAG_IO); if (PoolObjectNameInfo) { /* Query it again */ ObjectNameInfo = PoolObjectNameInfo; Status = ObQueryNameString(LogEntry->DeviceObject, ObjectNameInfo, ReturnedLength, &ReturnedLength); if (NT_SUCCESS(Status)) { /* Success, update the information */ ObjectNameInfo->Name.Length = 100 - (USHORT)DriverNameLength; } } } } } else { /* No device object, setup an empty name */ ObjectNameInfo->Name.Length = 0; ObjectNameInfo->Name.Buffer = L""; } /* * Now make sure that the device name fits in our buffer, minus 2 * NULL chars, and copy the name in our string buffer */ DeviceNameLength = min(ObjectNameInfo->Name.Length, RemainingLength - 2 * sizeof(UNICODE_NULL)); RtlCopyMemory(StringBuffer, ObjectNameInfo->Name.Buffer, DeviceNameLength); /* Null-terminate the device name */ *((PWSTR)(StringBuffer + DeviceNameLength)) = L'\0'; DeviceNameLength += sizeof(WCHAR); /* Free the buffer if we had one */ if (PoolObjectNameInfo) { ExFreePool(PoolObjectNameInfo); PoolObjectNameInfo = NULL; ObjectNameInfo = (POBJECT_NAME_INFORMATION)&Buffer; } /* Go to the next string buffer position */ ErrorMessage->EntryData.NumberOfStrings++; StringBuffer += DeviceNameLength; RemainingLength -= DeviceNameLength; /* Check if we have any extra strings */ if (Packet->NumberOfStrings) { /* Find out the size of the extra strings */ ExtraStringLength = LogEntry->Size - sizeof(ERROR_LOG_ENTRY) - Packet->StringOffset; /* Make sure that the extra strings fit in our buffer */ if (ExtraStringLength > (RemainingLength - sizeof(UNICODE_NULL))) { /* They wouldn't, so set normalize the length */ MessageLength -= ExtraStringLength - RemainingLength; ExtraStringLength = RemainingLength - sizeof(UNICODE_NULL); } /* Now copy the extra strings */ RtlCopyMemory(StringBuffer, (PCHAR)Packet + Packet->StringOffset, ExtraStringLength); /* Null-terminate them */ *((PWSTR)(StringBuffer + ExtraStringLength)) = L'\0'; } /* Set the driver name length */ ErrorMessage->DriverNameLength = (USHORT)DriverNameLength; /* Update the message length to include the device and driver names */ MessageLength += DeviceNameLength + DriverNameLength; ErrorMessage->Size = (USHORT)MessageLength; /* Now update it again, internally, for the size of the actual LPC */ MessageLength += (FIELD_OFFSET(ELF_API_MSG, IoErrorMessage) - FIELD_OFFSET(ELF_API_MSG, Unknown[0])); /* Set the total and data lengths */ Message->h.u1.s1.TotalLength = (USHORT)(sizeof(PORT_MESSAGE) + MessageLength); Message->h.u1.s1.DataLength = (USHORT)(MessageLength); /* Send the message */ Status = NtRequestPort(IopLogPort, (PPORT_MESSAGE)Message); if (!NT_SUCCESS(Status)) { /* Requeue log message and restart the worker */ ExInterlockedInsertTailList(&IopErrorLogListHead, &LogEntry->ListEntry, &IopLogListLock); IopLogWorkerRunning = FALSE; IopRestartLogWorker(); break; } /* Dereference the device object */ if (LogEntry->DeviceObject) ObDereferenceObject(LogEntry->DeviceObject); if (DriverObject) ObDereferenceObject(LogEntry->DriverObject); /* Update size */ InterlockedExchangeAdd(&IopTotalLogSize, -(LONG)(LogEntry->Size - sizeof(ERROR_LOG_ENTRY))); } /* Free the LPC Message */ ExFreePool(Message); }
NTSTATUS NewNtDeviceIoControlFile( __in HANDLE FileHandle, __in_opt HANDLE Event, __in_opt PIO_APC_ROUTINE ApcRoutine, __in_opt PVOID ApcContext, __out PIO_STATUS_BLOCK IoStatusBlock, __in ULONG IoControlCode, __in_opt PVOID InputBuffer, __in ULONG InputBufferLength, __out_opt PVOID OutputBuffer, __in ULONG OutputBufferLength ) { NTSTATUS retour,ntStatus; PFILE_OBJECT fileObject = NULL; ULONG retLen, ret; UNICODE_STRING *path_str = NULL; UNICODE_STRING afd;//=NULL; WCHAR deviceafd[] = L"\\Device\\Afd"; PAFD_SEND_INFO pAfdTcpInfo = InputBuffer; PAFD_SEND_INFO_UDP pAfdUdpSendtoInfo = InputBuffer; PAFD_RECV_INFO_UDP pAfdUdpRecvFromInfo = InputBuffer; ULONG dwLen = 0; PCHAR pBuf = NULL; int i=0, pid=0; ProcessInformation process; char buffer_net[2000]; char prot[10]; IO_STATUS_BLOCK iostatus; LARGE_INTEGER time; ULONG ppid = 0; PCHAR toto; UCHAR *name; PUNICODE_STRING temp_unicode, addr=NULL; ANSI_STRING ansi; PEPROCESS pep; TDI_REQUEST_QUERY_INFORMATION Request; char Address[128]; //Request = TDI_QUERY_ADDRESS_INFO; KeQuerySystemTime(&time); RtlZeroMemory(&buffer_net, sizeof(buffer_net)); RtlZeroMemory(&prot, sizeof(prot)); // NTDEVICEIOCONTROLFILE NtDeviceIoControlFile = Zdicf.NtFunc; RtlInitUnicodeString (&afd, deviceafd); retour = ((NTDEVICEIOCONTROLFILE) (OldNtDeviceIoControlFile)) (FileHandle, Event, ApcRoutine, ApcContext, IoStatusBlock, IoControlCode, InputBuffer, InputBufferLength, OutputBuffer, OutputBufferLength); if(IoControlCode != AFD_SEND && IoControlCode != AFD_RECV && IoControlCode != AFD_SENDTO && IoControlCode != AFD_RECVFROM) return retour; // ZwDeviceIoControlFile(FileHandle, // NULL,NULL, NULL, // &iostatus, // IOCTL_TDI_QUERY_INFORMATION, // TDI_QUERY_ADDRESS_INFO, 0,//sizeof(TDI_QUERY_ADDRESS_INFO), // &Address, sizeof(Address)); pid = (LONG)PsGetCurrentProcessId(); if(pid == (int)UserLandID) return retour; PsLookupProcessByProcessId((HANDLE)pid,&pep); toto = (PCHAR) pep; ppid = *((ULONG*)(toto+0x140)); // On recupere les 16 premiers bits du nom du process name = PsGetProcessImageFileName(pep); if(ExGetPreviousMode() == UserMode) { if(FileHandle != NULL) { ObReferenceObjectByHandle(FileHandle, 0, 0, KernelMode, &fileObject, NULL); if (fileObject) { ntStatus = ObQueryNameString(fileObject, (POBJECT_NAME_INFORMATION)path_str, 0, &retLen); path_str = (PUNICODE_STRING)ExAllocatePoolWithTag(NonPagedPool, retLen, 0); if (ntStatus == STATUS_INFO_LENGTH_MISMATCH) { if (path_str) { ntStatus = ObQueryNameString(fileObject, (POBJECT_NAME_INFORMATION)path_str, retLen, &retLen); if(RtlCompareUnicodeString(path_str,&afd,TRUE) == 0) { trace_net++; switch(IoControlCode) { case AFD_SEND: sprintf(prot,"tcp"); break; case AFD_RECV: sprintf(prot,"tcp"); break; case AFD_SENDTO: sprintf(prot,"udp"); break; case AFD_RECVFROM: sprintf(prot,"udp"); break; default: sprintf(prot,"not"); } // if(strcmp(prot, "udp") == 0) // { // DbgPrint("Taiele de l'address : %i \n", pAfdUdpSendtoInfo->SizeOfRemoteAddress); // temp_unicode = (PUNICODE_STRING)ExAllocatePoolWithTag(NonPagedPool, pAfdUdpSendtoInfo->SizeOfRemoteAddress, 0); // temp_unicode = (PUNICODE_STRING) pAfdUdpSendtoInfo->RemoteAddress; // DbgPrint("address : %wZ \n", &temp_unicode); //RtlCopyUnicodeString( addr, temp_unicode); //DbgPrint("addr 1 :%wZ\n" , addr); // } if(InputBufferLength > 0) sprintf(buffer_net, "audit(%I64d,%i) pid=%i name=%s ppid=%i { send } size=%i prot=%s return=%x endoftrace", time.QuadPart, trace_net,pid, name,ppid, InputBufferLength, prot, retour); if(OutputBufferLength > 0) sprintf(buffer_net, "audit(%I64d,%i) pid=%i name=%s ppid=%i { recv } size=%i prot=%s return=%x endoftrace", time.QuadPart, trace_net,pid, name, ppid, OutputBufferLength, prot, retour); //DbgPrint("%wZ \n", path_str); ZwWriteFile(handlenet, NULL, NULL, NULL, &iostatus, buffer_net, strlen(buffer_net), 0, NULL); ZwFlushBuffersFile(handlenet, &iostatus); } if(path_str) ExFreePoolWithTag(path_str, 0); } } ObDereferenceObject(fileObject); } } } // if(fileObject != NULL) // ObDereferenceObject(fileObject); return retour; }
NTSTATUS DiskDevDispatch(IN PDEVICE_OBJECT HookDevice,IN PIRP Irp) { PIO_STACK_LOCATION currentIrpStack=IoGetCurrentIrpStackLocation(Irp); ULONG ioControlCode; VERDICT Verdict; NTSTATUS ntStatus = STATUS_SUCCESS; PDISK_DEV_LIST DevEntry; ULONG Function; ANSI_STRING fullPathName; BOOLEAN FPNAllocated=FALSE; ULONG actualLen; PCHAR Action; ULONG ParamVal = 0; LARGE_INTEGER ByteOffset; POBJECT_NAME_INFORMATION DevName=NULL; KIRQL CurrIrql; BOOLEAN bInvisible; ULONG SectorSize = 0; ULONG DataLength = 0; ULONG ReqDataSize; PVOID RequestData; PSINGLE_PARAM pSingleParam; PFILTER_EVENT_PARAM pParam; ByteOffset.LowPart = 0; ByteOffset.HighPart = 0; fullPathName.Buffer=NULL; CurrIrql = KeGetCurrentIrql(); if (CurrIrql < DISPATCH_LEVEL) { ReqDataSize = sizeof(FILTER_EVENT_PARAM) + sizeof(SINGLE_PARAM) + MAXPATHLEN + 1 + sizeof(SINGLE_PARAM) + sizeof(ULONG) + sizeof(SINGLE_PARAM) + sizeof(LARGE_INTEGER); ReqDataSize += sizeof (SINGLE_PARAM) + __SID_LENGTH; RequestData = ExAllocatePoolWithTag(NonPagedPool, ReqDataSize, 'RboS'); pParam = (PFILTER_EVENT_PARAM)RequestData; if (pParam == NULL) { DbPrint(DC_DISK,DL_ERROR, ("Allocate buffer in DiskDevDispatch for RequestData failed\n")); } else { FILTER_PARAM_COMMONINIT(pParam, FLTTYPE_DISK, 0, 0, PreProcessing, 3); pSingleParam = (PSINGLE_PARAM) pParam->Params; // pParam->ProcName[0] = 0; // GetProcName(pParam->ProcName,NULL);//Irp???? if(CurrIrql<DISPATCH_LEVEL) { if(HookDevice->Flags & DO_DEVICE_HAS_NAME) { if(DevName = ExAllocatePoolWithTag(NonPagedPool,MAXPATHLEN*sizeof(WCHAR),'DSeB')) { if(NT_SUCCESS(ObQueryNameString(HookDevice,DevName,MAXPATHLEN*sizeof(WCHAR),&actualLen))) { if(fullPathName.Buffer = ExAllocatePoolWithTag(NonPagedPool,MAXPATHLEN,'DSeB')) { FPNAllocated=TRUE; fullPathName.Length=0; fullPathName.MaximumLength=MAXPATHLEN; RtlUnicodeStringToAnsiString(&fullPathName,&DevName->Name,FALSE); } } } } else { if(fullPathName.Buffer=ExAllocatePoolWithTag(NonPagedPool,MAXPATHLEN,'DSeB')) { FPNAllocated=TRUE; fullPathName.Length=10; fullPathName.MaximumLength=MAXPATHLEN; sprintf(fullPathName.Buffer,">%08x<",HookDevice); } } } pParam->FunctionMj = currentIrpStack->MajorFunction; if(currentIrpStack->MajorFunction == IRP_MJ_DEVICE_CONTROL || currentIrpStack->MajorFunction == IRP_MJ_INTERNAL_DEVICE_CONTROL) { ioControlCode = IoGetFunctionCodeFromCtlCode(currentIrpStack->Parameters.DeviceIoControl.IoControlCode);//(currentIrpStack->Parameters.DeviceIoControl.IoControlCode & 0x1ffc)>>2; if(ioControlCode > sizeof(NTDiskDeviceIOCTLName)/sizeof(PVOID)) { DbPrint(DC_DISK,DL_SPAM, ("!!! Disk_IOCTL 0x%x(0x%x) %s\n", currentIrpStack->Parameters.DeviceIoControl.IoControlCode, ioControlCode, fullPathName.Buffer == NULL ? UnknownStr : fullPathName.Buffer)); ioControlCode=0; } pParam->FunctionMi = ioControlCode; } else if(currentIrpStack->MajorFunction==IRP_MJ_READ || currentIrpStack->MajorFunction==IRP_MJ_WRITE) { SectorSize = currentIrpStack->DeviceObject->SectorSize == 0 ? 512 : currentIrpStack->DeviceObject->SectorSize; ParamVal=(ULONG)(*(__int64*)(¤tIrpStack->Parameters.Read.ByteOffset)/SectorSize); ByteOffset = currentIrpStack->Parameters.Read.ByteOffset; DataLength = currentIrpStack->Parameters.Read.Length; DbPrint(DC_DISK,DL_SPAM, ("%s %s Sec=%u Len=%u\n", NTMajorFunctionName[currentIrpStack->MajorFunction], fullPathName.Buffer == NULL ? UnknownStr : fullPathName.Buffer, ParamVal, DataLength)); pParam->FunctionMi = currentIrpStack->MinorFunction; } else pParam->FunctionMi = currentIrpStack->MinorFunction; #ifdef __DBG__ Action=ExAllocatePoolWithTag(NonPagedPool,MY_PAGE_SIZE,'DSeB'); if(Action) { DbPrint(DC_DISK,DL_INFO, ("%s %s (IRQL=%d)\n", NTGetFunctionStr(Action, pParam->HookID, pParam->FunctionMj, pParam->FunctionMi), fullPathName.Buffer == NULL ? UnknownStr : fullPathName.Buffer, CurrIrql)); ExFreePool(Action); } #endif //__DBG__ #ifdef __DBG__ // if(IoIsOperationSynchronous(Irp)==FALSE) // DbPrint(DC_DISK,DL_NOTIFY,("^^^^^^^^^ Async operation !!!!!!!!!\n")); #endif //__DBG__ if (IsNeedFilterEventAsyncChk(pParam->HookID, pParam->FunctionMj, pParam->FunctionMi,Irp, &bInvisible) == TRUE) { SINGLE_PARAM_INIT_NONE(pSingleParam, _PARAM_OBJECT_URL); sprintf(pSingleParam->ParamValue, "%s", fullPathName.Buffer); //сюда имя девайса pSingleParam->ParamSize = strlen(pSingleParam->ParamValue) + 1; SINGLE_PARAM_SHIFT(pSingleParam); SINGLE_PARAM_INIT_LARGEINTEGER(pSingleParam, _PARAM_OBJECT_BYTEOFFSET, ByteOffset); //+ ---------------------------------------------------------------------------------------- SINGLE_PARAM_SHIFT(pSingleParam); SINGLE_PARAM_INIT_ULONG(pSingleParam, _PARAM_OBJECT_DATALEN, DataLength); // ----------------------------------------------------------------------------------------- // reserve place for sid SINGLE_PARAM_SHIFT(pSingleParam); SINGLE_PARAM_INIT_SID(pSingleParam); pParam->ParamsCount++; // end reserve place for sid // ----------------------------------------------------------------------------------------- Verdict = FilterEvent(pParam, NULL); if(!_PASS_VERDICT(Verdict)) { if(Verdict == Verdict_Kill) { DbPrint(DC_DISK,DL_NOTIFY, ("Kill %s\n", pParam->ProcName)); KillCurrentProcess(); } else if(Verdict == Verdict_Discard) { DbPrint(DC_DISK,DL_NOTIFY, ("Discard disk operation\n"/*, pSingleParam->ParamValue*/)); } ntStatus = STATUS_ACCESS_DENIED; } } ExFreePool(RequestData); } } if (ntStatus != STATUS_ACCESS_DENIED) { DevEntry=DiskDevList; while(DevEntry) { if(DevEntry->Drv==HookDevice->DriverObject) break; DevEntry=DevEntry->Next; } if(DevEntry) ntStatus=(DevEntry->DiskDevDispArray[currentIrpStack->MajorFunction])(HookDevice,Irp); else { DbPrint(DC_DISK,DL_WARNING, ("!!! DiskDevDispatch. Device 0x%x (Drv=0x%x) not found in hooked list\n",HookDevice,HookDevice->DriverObject)); ntStatus=Irp->IoStatus.Status=STATUS_NO_SUCH_DEVICE; Irp->IoStatus.Information=0; IoCompleteRequest(Irp,IO_NO_INCREMENT); } } if (DevName != NULL) ExFreePool(DevName); if (fullPathName.Buffer != NULL) ExFreePool(fullPathName.Buffer); return ntStatus; }
/*++ * @name IoRegisterDeviceInterface * @implemented * * Registers a device interface class, if it has not been previously registered, * and creates a new instance of the interface class, which a driver can * subsequently enable for use by applications or other system components. * Documented in WDK. * * @param PhysicalDeviceObject * Points to an optional PDO that narrows the search to only the * device interfaces of the device represented by the PDO * * @param InterfaceClassGuid * Points to a class GUID specifying the device interface class * * @param ReferenceString * Optional parameter, pointing to a unicode string. For a full * description of this rather rarely used param (usually drivers * pass NULL here) see WDK * * @param SymbolicLinkName * Pointer to the resulting unicode string * * @return Usual NTSTATUS * * @remarks Must be called at IRQL = PASSIVE_LEVEL in the context of a * system thread * *--*/ NTSTATUS NTAPI IoRegisterDeviceInterface(IN PDEVICE_OBJECT PhysicalDeviceObject, IN CONST GUID *InterfaceClassGuid, IN PUNICODE_STRING ReferenceString OPTIONAL, OUT PUNICODE_STRING SymbolicLinkName) { PUNICODE_STRING InstancePath; UNICODE_STRING GuidString; UNICODE_STRING SubKeyName; UNICODE_STRING InterfaceKeyName; UNICODE_STRING BaseKeyName; UCHAR PdoNameInfoBuffer[sizeof(OBJECT_NAME_INFORMATION) + (256 * sizeof(WCHAR))]; POBJECT_NAME_INFORMATION PdoNameInfo = (POBJECT_NAME_INFORMATION)PdoNameInfoBuffer; UNICODE_STRING DeviceInstance = RTL_CONSTANT_STRING(L"DeviceInstance"); UNICODE_STRING SymbolicLink = RTL_CONSTANT_STRING(L"SymbolicLink"); HANDLE ClassKey; HANDLE InterfaceKey; HANDLE SubKey; ULONG StartIndex; OBJECT_ATTRIBUTES ObjectAttributes; ULONG i; NTSTATUS Status, SymLinkStatus; PEXTENDED_DEVOBJ_EXTENSION DeviceObjectExtension; ASSERT_IRQL_EQUAL(PASSIVE_LEVEL); DPRINT("IoRegisterDeviceInterface(): PDO %p, RefString: %wZ\n", PhysicalDeviceObject, ReferenceString); /* Parameters must pass three border of checks */ DeviceObjectExtension = (PEXTENDED_DEVOBJ_EXTENSION)PhysicalDeviceObject->DeviceObjectExtension; /* 1st level: Presence of a Device Node */ if (DeviceObjectExtension->DeviceNode == NULL) { DPRINT("PhysicalDeviceObject 0x%p doesn't have a DeviceNode\n", PhysicalDeviceObject); return STATUS_INVALID_DEVICE_REQUEST; } /* 2nd level: Presence of an non-zero length InstancePath */ if (DeviceObjectExtension->DeviceNode->InstancePath.Length == 0) { DPRINT("PhysicalDeviceObject 0x%p's DOE has zero-length InstancePath\n", PhysicalDeviceObject); return STATUS_INVALID_DEVICE_REQUEST; } /* 3rd level: Optional, based on WDK documentation */ if (ReferenceString != NULL) { /* Reference string must not contain path-separator symbols */ for (i = 0; i < ReferenceString->Length / sizeof(WCHAR); i++) { if ((ReferenceString->Buffer[i] == '\\') || (ReferenceString->Buffer[i] == '/')) return STATUS_INVALID_DEVICE_REQUEST; } } Status = RtlStringFromGUID(InterfaceClassGuid, &GuidString); if (!NT_SUCCESS(Status)) { DPRINT("RtlStringFromGUID() failed with status 0x%08lx\n", Status); return Status; } /* Create Pdo name: \Device\xxxxxxxx (unnamed device) */ Status = ObQueryNameString( PhysicalDeviceObject, PdoNameInfo, sizeof(PdoNameInfoBuffer), &i); if (!NT_SUCCESS(Status)) { DPRINT("ObQueryNameString() failed with status 0x%08lx\n", Status); return Status; } ASSERT(PdoNameInfo->Name.Length); /* Create base key name for this interface: HKLM\SYSTEM\CurrentControlSet\Control\DeviceClasses\{GUID} */ ASSERT(((PEXTENDED_DEVOBJ_EXTENSION)PhysicalDeviceObject->DeviceObjectExtension)->DeviceNode); InstancePath = &((PEXTENDED_DEVOBJ_EXTENSION)PhysicalDeviceObject->DeviceObjectExtension)->DeviceNode->InstancePath; BaseKeyName.Length = (USHORT)wcslen(BaseKeyString) * sizeof(WCHAR); BaseKeyName.MaximumLength = BaseKeyName.Length + GuidString.Length; BaseKeyName.Buffer = ExAllocatePool( PagedPool, BaseKeyName.MaximumLength); if (!BaseKeyName.Buffer) { DPRINT("ExAllocatePool() failed\n"); return STATUS_INSUFFICIENT_RESOURCES; } wcscpy(BaseKeyName.Buffer, BaseKeyString); RtlAppendUnicodeStringToString(&BaseKeyName, &GuidString); /* Create BaseKeyName key in registry */ InitializeObjectAttributes( &ObjectAttributes, &BaseKeyName, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE | OBJ_OPENIF, NULL, /* RootDirectory */ NULL); /* SecurityDescriptor */ Status = ZwCreateKey( &ClassKey, KEY_WRITE, &ObjectAttributes, 0, /* TileIndex */ NULL, /* Class */ REG_OPTION_VOLATILE, NULL); /* Disposition */ if (!NT_SUCCESS(Status)) { DPRINT("ZwCreateKey() failed with status 0x%08lx\n", Status); ExFreePool(BaseKeyName.Buffer); return Status; } /* Create key name for this interface: ##?#ACPI#PNP0501#1#{GUID} */ InterfaceKeyName.Length = 0; InterfaceKeyName.MaximumLength = 4 * sizeof(WCHAR) + /* 4 = size of ##?# */ InstancePath->Length + sizeof(WCHAR) + /* 1 = size of # */ GuidString.Length; InterfaceKeyName.Buffer = ExAllocatePool( PagedPool, InterfaceKeyName.MaximumLength); if (!InterfaceKeyName.Buffer) { DPRINT("ExAllocatePool() failed\n"); return STATUS_INSUFFICIENT_RESOURCES; } RtlAppendUnicodeToString(&InterfaceKeyName, L"##?#"); StartIndex = InterfaceKeyName.Length / sizeof(WCHAR); RtlAppendUnicodeStringToString(&InterfaceKeyName, InstancePath); for (i = 0; i < InstancePath->Length / sizeof(WCHAR); i++) { if (InterfaceKeyName.Buffer[StartIndex + i] == '\\') InterfaceKeyName.Buffer[StartIndex + i] = '#'; } RtlAppendUnicodeToString(&InterfaceKeyName, L"#"); RtlAppendUnicodeStringToString(&InterfaceKeyName, &GuidString); /* Create the interface key in registry */ InitializeObjectAttributes( &ObjectAttributes, &InterfaceKeyName, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE | OBJ_OPENIF, ClassKey, NULL); /* SecurityDescriptor */ Status = ZwCreateKey( &InterfaceKey, KEY_WRITE, &ObjectAttributes, 0, /* TileIndex */ NULL, /* Class */ REG_OPTION_VOLATILE, NULL); /* Disposition */ if (!NT_SUCCESS(Status)) { DPRINT("ZwCreateKey() failed with status 0x%08lx\n", Status); ZwClose(ClassKey); ExFreePool(BaseKeyName.Buffer); return Status; } /* Write DeviceInstance entry. Value is InstancePath */ Status = ZwSetValueKey( InterfaceKey, &DeviceInstance, 0, /* TileIndex */ REG_SZ, InstancePath->Buffer, InstancePath->Length); if (!NT_SUCCESS(Status)) { DPRINT("ZwSetValueKey() failed with status 0x%08lx\n", Status); ZwClose(InterfaceKey); ZwClose(ClassKey); ExFreePool(InterfaceKeyName.Buffer); ExFreePool(BaseKeyName.Buffer); return Status; } /* Create subkey. Name is #ReferenceString */ SubKeyName.Length = 0; SubKeyName.MaximumLength = sizeof(WCHAR); if (ReferenceString && ReferenceString->Length) SubKeyName.MaximumLength += ReferenceString->Length; SubKeyName.Buffer = ExAllocatePool( PagedPool, SubKeyName.MaximumLength); if (!SubKeyName.Buffer) { DPRINT("ExAllocatePool() failed\n"); ZwClose(InterfaceKey); ZwClose(ClassKey); ExFreePool(InterfaceKeyName.Buffer); ExFreePool(BaseKeyName.Buffer); return STATUS_INSUFFICIENT_RESOURCES; } RtlAppendUnicodeToString(&SubKeyName, L"#"); if (ReferenceString && ReferenceString->Length) RtlAppendUnicodeStringToString(&SubKeyName, ReferenceString); /* Create SubKeyName key in registry */ InitializeObjectAttributes( &ObjectAttributes, &SubKeyName, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, InterfaceKey, /* RootDirectory */ NULL); /* SecurityDescriptor */ Status = ZwCreateKey( &SubKey, KEY_WRITE, &ObjectAttributes, 0, /* TileIndex */ NULL, /* Class */ REG_OPTION_VOLATILE, NULL); /* Disposition */ if (!NT_SUCCESS(Status)) { DPRINT("ZwCreateKey() failed with status 0x%08lx\n", Status); ZwClose(InterfaceKey); ZwClose(ClassKey); ExFreePool(InterfaceKeyName.Buffer); ExFreePool(BaseKeyName.Buffer); return Status; } /* Create symbolic link name: \??\ACPI#PNP0501#1#{GUID}\ReferenceString */ SymbolicLinkName->Length = 0; SymbolicLinkName->MaximumLength = SymbolicLinkName->Length + 4 * sizeof(WCHAR) /* 4 = size of \??\ */ + InstancePath->Length + sizeof(WCHAR) /* 1 = size of # */ + GuidString.Length + sizeof(WCHAR); /* final NULL */ if (ReferenceString && ReferenceString->Length) SymbolicLinkName->MaximumLength += sizeof(WCHAR) + ReferenceString->Length; SymbolicLinkName->Buffer = ExAllocatePool( PagedPool, SymbolicLinkName->MaximumLength); if (!SymbolicLinkName->Buffer) { DPRINT("ExAllocatePool() failed\n"); ZwClose(SubKey); ZwClose(InterfaceKey); ZwClose(ClassKey); ExFreePool(InterfaceKeyName.Buffer); ExFreePool(SubKeyName.Buffer); ExFreePool(BaseKeyName.Buffer); return STATUS_INSUFFICIENT_RESOURCES; } RtlAppendUnicodeToString(SymbolicLinkName, L"\\??\\"); StartIndex = SymbolicLinkName->Length / sizeof(WCHAR); RtlAppendUnicodeStringToString(SymbolicLinkName, InstancePath); for (i = 0; i < InstancePath->Length / sizeof(WCHAR); i++) { if (SymbolicLinkName->Buffer[StartIndex + i] == '\\') SymbolicLinkName->Buffer[StartIndex + i] = '#'; } RtlAppendUnicodeToString(SymbolicLinkName, L"#"); RtlAppendUnicodeStringToString(SymbolicLinkName, &GuidString); SymbolicLinkName->Buffer[SymbolicLinkName->Length/sizeof(WCHAR)] = L'\0'; /* Create symbolic link */ DPRINT("IoRegisterDeviceInterface(): creating symbolic link %wZ -> %wZ\n", SymbolicLinkName, &PdoNameInfo->Name); SymLinkStatus = IoCreateSymbolicLink(SymbolicLinkName, &PdoNameInfo->Name); /* If the symbolic link already exists, return an informational success status */ if (SymLinkStatus == STATUS_OBJECT_NAME_COLLISION) { /* HACK: Delete the existing symbolic link and update it to the new PDO name */ IoDeleteSymbolicLink(SymbolicLinkName); IoCreateSymbolicLink(SymbolicLinkName, &PdoNameInfo->Name); SymLinkStatus = STATUS_OBJECT_NAME_EXISTS; } if (!NT_SUCCESS(SymLinkStatus)) { DPRINT1("IoCreateSymbolicLink() failed with status 0x%08lx\n", SymLinkStatus); ZwClose(SubKey); ZwClose(InterfaceKey); ZwClose(ClassKey); ExFreePool(SubKeyName.Buffer); ExFreePool(InterfaceKeyName.Buffer); ExFreePool(BaseKeyName.Buffer); ExFreePool(SymbolicLinkName->Buffer); return SymLinkStatus; } if (ReferenceString && ReferenceString->Length) { RtlAppendUnicodeToString(SymbolicLinkName, L"\\"); RtlAppendUnicodeStringToString(SymbolicLinkName, ReferenceString); } SymbolicLinkName->Buffer[SymbolicLinkName->Length/sizeof(WCHAR)] = L'\0'; /* Write symbolic link name in registry */ SymbolicLinkName->Buffer[1] = '\\'; Status = ZwSetValueKey( SubKey, &SymbolicLink, 0, /* TileIndex */ REG_SZ, SymbolicLinkName->Buffer, SymbolicLinkName->Length); if (!NT_SUCCESS(Status)) { DPRINT1("ZwSetValueKey() failed with status 0x%08lx\n", Status); ExFreePool(SymbolicLinkName->Buffer); } else { SymbolicLinkName->Buffer[1] = '?'; } ZwClose(SubKey); ZwClose(InterfaceKey); ZwClose(ClassKey); ExFreePool(SubKeyName.Buffer); ExFreePool(InterfaceKeyName.Buffer); ExFreePool(BaseKeyName.Buffer); return NT_SUCCESS(Status) ? SymLinkStatus : Status; }
/* * Retrieve the full pathname (including files and registry keys) for a * given handle. This method is from "Undocumented Windows NT". */ BOOLEAN PathFromHandle (HANDLE hKey, PUNICODE_STRING lpszSubKeyVal, PCHAR fullname) { PVOID pKey = NULL; ANSI_STRING keyname; PCHAR tmpname; PUNICODE_STRING fullUniName; ULONG actualLen; if(!fullname) return FALSE; /* Allocate a temporary buffer */ tmpname = ExAllocatePoolWithTag (PagedPool, MAXPATHLEN, HELPER_POOL_TAG); if (tmpname == NULL) /* Not enough memory */ return FALSE; *fullname = *tmpname = '\0'; /* * Translate the hKey into a pointer to check whether it is a valid * handle. */ if (NT_SUCCESS (ObReferenceObjectByHandle (hKey, 0, NULL, KernelMode, &pKey, NULL)) && pKey != NULL) { fullUniName = ExAllocatePoolWithTag (PagedPool, MAXPATHLEN * 2 + 2 * sizeof(ULONG), HELPER_POOL_TAG); if (fullUniName == NULL) { /* Not enough memory */ ObDereferenceObject (pKey); ExFreePool (tmpname); return FALSE; } fullUniName->MaximumLength = MAXPATHLEN*2; if (NT_SUCCESS (ObQueryNameString (pKey, fullUniName, MAXPATHLEN, &actualLen ))) { if (NT_SUCCESS (RtlUnicodeStringToAnsiString ( &keyname, fullUniName, TRUE))) { if(*keyname.Buffer != '\0') { if (*keyname.Buffer != '\\') strcpy (tmpname, "\\"); else strcpy (tmpname, ""); strncat (tmpname, keyname.Buffer, min( keyname.Length, MAXPATHLEN - 2 )); } RtlFreeAnsiString (&keyname); } } ObDereferenceObject (pKey); ExFreePool (fullUniName); } /* Append subkey and value if they are there */ if (lpszSubKeyVal != NULL) { keyname.Buffer = NULL; if (NT_SUCCESS (RtlUnicodeStringToAnsiString (&keyname, lpszSubKeyVal, TRUE))) { if (*keyname.Buffer != '\0') { size_t iLen = MAXPATHLEN - (strlen(tmpname) - 1); strcat(tmpname, "\\"); strncat(tmpname, keyname.Buffer, min(keyname.Length, iLen)); } RtlFreeAnsiString (&keyname); } } strcpy (fullname, tmpname); ExFreePool (tmpname); return TRUE; }
ULONG GetRegFullPath( HANDLE hKey, PVOID pRootObject, PUNICODE_STRING pSubKey, PNAME_BUFFER pRegBuffer ) { NTSTATUS Status = STATUS_SUCCESS; PVOID pKey = NULL; POBJECT_NAME_INFORMATION pObjectName = NULL; ULONG ulTempLen=0, ulRet=0, ulLength=0; if(KeGetCurrentIrql() >= DISPATCH_LEVEL) { return 0; } if(!pRegBuffer || !pRegBuffer->pBuffer) { return 0; } if(hKey) { if(((ULONG_PTR)hKey>0) || (ExGetPreviousMode() == KernelMode)) { ObReferenceObjectByHandle( hKey, 0, NULL, KernelMode, &pKey, NULL); } } else if(pRootObject) { pKey = pRootObject; ObReferenceObject( pKey ); } else { return 0; } if(!pKey) return 0; KeEnterCriticalRegion(); pObjectName = (POBJECT_NAME_INFORMATION)ExAllocatePoolWithTag( NonPagedPool, MAX_POOL_LEN, MALWFIND_NAME_TAG ); if(!pObjectName) { KeLeaveCriticalRegion(); return 0; } RtlZeroMemory( pObjectName, MAX_POOL_LEN ); pObjectName->Name.Length = 0; pObjectName->Name.MaximumLength = (MAX_POOL_LEN >> 1); Status = ObQueryNameString( pKey, pObjectName, MAX_POOL_LEN, &ulRet ); if(!NT_SUCCESS( Status )) { if(pObjectName) { ExFreePoolWithTag( pObjectName, MALWFIND_NAME_TAG ); pObjectName = NULL; } KeLeaveCriticalRegion(); return 0; } ObDereferenceObject( pKey ); ulLength += pObjectName->Name.Length; Status = RtlStringCchCatNW( pRegBuffer->pBuffer, pRegBuffer->ulMaxLength, pObjectName->Name.Buffer, pObjectName->Name.Length ); if(!NT_SUCCESS( Status )) { if(pObjectName) { ExFreePoolWithTag( pObjectName, MALWFIND_NAME_TAG ); pObjectName = NULL; } KeLeaveCriticalRegion(); return 0; } if(pSubKey && pSubKey->Buffer && pSubKey->Length) { ulLength += sizeof(WCHAR); ulTempLen = sizeof(WCHAR); Status = RtlStringCchCatNW( pRegBuffer->pBuffer, pRegBuffer->ulMaxLength, L"\\", ulTempLen ); ulLength += pSubKey->Length; Status = RtlStringCchCatNW( pRegBuffer->pBuffer, pRegBuffer->ulMaxLength, pSubKey->Buffer, pSubKey->Length ); } if(pObjectName) { ExFreePoolWithTag( pObjectName, MALWFIND_NAME_TAG ); pObjectName = NULL; } KeLeaveCriticalRegion(); return ulLength; }
NTSTATUS GetAllDiskObjects() /*++ Routine Description: Enumeration all disk devices Arguments: None Return Value: None --*/ { NTSTATUS Status; PDRIVER_OBJECT pDiskObject; PDEVICE_OBJECT pDeviceObjectTemp; UNICODE_STRING DestinationString; DWORD dwDeviceNumber; DWORD dwRetLength; POBJECT_NAME_INFORMATION pNameBuffer; WCHAR *pNameTemp; PDISK_OBJ pDisk; PDISK_GEOMETRY pDiskGeometry; BOOLEAN bIsFound = FALSE; PDEVICE_EXTENSION pDevExtn = (PDEVICE_EXTENSION)gp_DevObj->DeviceExtension; /* All Disk Objects are created by disk.sys driver*/ RtlInitUnicodeString(&DestinationString, L"\\Driver\\Disk"); // Not a documented function in DDK, see import definition in sector.h if (ObReferenceObjectByName(&DestinationString, 64, 0, 0, *IoDriverObjectType, KernelMode, 0, &pDiskObject) >= 0) { pDeviceObjectTemp = pDiskObject->DeviceObject; dwDeviceNumber = 0; if (pDeviceObjectTemp) { pDiskGeometry = ExAllocatePool(NonPagedPool, sizeof(DISK_GEOMETRY)); if (!pDiskGeometry) { return STATUS_INSUFFICIENT_RESOURCES; } do { //Each time memset the geometry structure to zero memset(pDiskGeometry, 0x00, sizeof(DISK_GEOMETRY)); // DeviceType 7 corresponds to FILE_DISK_DEVICE Type Device Object and // It should have name too that's why Flags is check for 0x40 (DO_DEVICE_HAS_NAME ) //DbgPrint("DeviceType: %d", pDeviceObjectTemp->DeviceType); if (pDeviceObjectTemp->DeviceType == 7 && (pDeviceObjectTemp->Flags & 0x40)) { ObQueryNameString(pDeviceObjectTemp, NULL, 0, &dwRetLength); pNameBuffer = (POBJECT_NAME_INFORMATION) ExAllocatePoolWithTag(PagedPool, dwRetLength, ' sFI'); if (!pNameBuffer) { ExFreePool(pDiskGeometry); return STATUS_INSUFFICIENT_RESOURCES; } if (ObQueryNameString(pDeviceObjectTemp, pNameBuffer, dwRetLength, &dwRetLength) == STATUS_SUCCESS && pNameBuffer->Name.Buffer) { //DbgPrint("pNameBuffer->Name.Buffer: %ws", pNameBuffer->Name.Buffer); pDisk = ExAllocatePool(PagedPool, sizeof(DISK_OBJ)); if (!pDisk) { ExFreePool(pDiskGeometry); ExFreePool(pNameBuffer); return STATUS_INSUFFICIENT_RESOURCES; } for (pNameTemp = pNameBuffer->Name.Buffer + wcslen(pNameBuffer->Name.Buffer); pNameTemp > pNameBuffer->Name.Buffer; pNameTemp--) { //DbgPrint("pNameTemp: %ws", pNameTemp); if (!_wcsnicmp(pNameTemp, L"\\DR", 3)) { pDisk->bIsRawDiskObj = TRUE; bIsFound = TRUE; break; } else if (!_wcsnicmp(pNameTemp, L"\\DP(", 4)) { pDisk->bIsRawDiskObj = FALSE; bIsFound = TRUE; break; } } if (bIsFound) { pDisk->dwDiskOrdinal = (USHORT)pNameBuffer-> Name.Buffer[wcslen(pNameBuffer->Name.Buffer)-1] - (USHORT) L'0'; pDisk->pDiskDevObj = pDeviceObjectTemp; ExInterlockedInsertTailList(&pDevExtn->list_head, &pDisk->list, &pDevExtn->list_lock); Status = GetGeometry(pDisk->pDiskDevObj, pDiskGeometry); if (!NT_SUCCESS(Status)) { pDisk->bGeometryFound = FALSE; } else { pDisk->bGeometryFound = TRUE; pDisk->ulSectorSize = pDiskGeometry->BytesPerSector; } } //end of if (bIsFound) }//end of if (ObQueryNameString ...) ExFreePoolWithTag(pNameBuffer, 0); }//end of if (pDeviceObjectTemp->DeviceType == 7 ...) pDeviceObjectTemp = pDeviceObjectTemp->NextDevice; } while (pDeviceObjectTemp); // end of while ExFreePool(pDiskGeometry); //Free pDiskGeometry } } return STATUS_SUCCESS; }
NTSTATUS RegistryCallback( _In_ PVOID CallbackContext, _In_opt_ PVOID Argument1, _In_opt_ PVOID Argument2 ) { REG_NOTIFY_CLASS Operation = (REG_NOTIFY_CLASS)(ULONG_PTR)Argument1; ULONG_PTR arg2= (ULONG_PTR)Argument2; switch (Operation) { case RegNtPreCreateKeyEx: { PREG_CREATE_KEY_INFORMATION CallbackData = (PREG_CREATE_KEY_INFORMATION)arg2; if (CallbackData->CompleteName->Length == 0 || *CallbackData->CompleteName->Buffer != OBJ_NAME_PATH_SEPARATOR) { SendRegistryOperationToUserland(REG_PRE_CREATE, CallbackData->CompleteName); DbgPrint("RegNtPreCreateKeyEx %wZ", CallbackData->CompleteName); } } break; case RegNtPreOpenKeyEx: break; { PREG_OPEN_KEY_INFORMATION CallbackData = (PREG_OPEN_KEY_INFORMATION)arg2; if (CallbackData->CompleteName->Length == 0 || *CallbackData->CompleteName->Buffer != OBJ_NAME_PATH_SEPARATOR) { //Get the name of the rootObject where the stuff is done. ULONG allocatedSTRSize = 1024 * sizeof(UNICODE_STRING); PUNICODE_STRING root_name = ExAllocatePoolWithTag(NonPagedPool, 1024 * sizeof(UNICODE_STRING), SPY_TAG); ULONG returnedLength; //CAll obQueryNAmeString. NTSTATUS obQueryStatus = ObQueryNameString(CallbackData->RootObject , (POBJECT_NAME_INFORMATION)root_name , allocatedSTRSize , &returnedLength); if (obQueryStatus == STATUS_SUCCESS) { if (root_name != NULL) { ULONG newSize = CallbackData->CompleteName->Length + root_name->Length + 1/*bonus for the backslash*/; if (newSize < allocatedSTRSize) { //Add the backslash RtlUnicodeStringCat(root_name, "\\"); //Add at the end of the stuff the complete name. RtlUnicodeStringCat(root_name, CallbackData->CompleteName); } SendRegistryOperationToUserland(REG_PRE_OPEN, root_name); DbgPrint("RegNtPreOpenKeyEx: %wZ", root_name); } else DbgPrint("RegNtPreOpenKeyEx NAME %wZ || ROOT NOT PRESENT!", CallbackData->CompleteName, root_name); } else { DbgPrint("RegNtPreOpenKeyEx -> Unable to recover the object name."); } //Free the AllocatedPool if (root_name != NULL) ExFreePoolWithTag(root_name, SPY_TAG); } } break; case RegNtDeleteKey: { PREG_DELETE_KEY_INFORMATION CallbackData = (PREG_DELETE_KEY_INFORMATION)arg2; //In this case use the ObQueryNameString //TODO -> Determine if Paged should work here. ULONG allocatedSTRSize = 1024 * sizeof(UNICODE_STRING); PUNICODE_STRING object_name = ExAllocatePoolWithTag(NonPagedPool, 1024 * sizeof(UNICODE_STRING), SPY_TAG); ULONG returnedLength; //CAll obQueryNAmeString. NTSTATUS obQueryStatus = ObQueryNameString(CallbackData->Object , (POBJECT_NAME_INFORMATION)object_name , allocatedSTRSize , &returnedLength); if (obQueryStatus == STATUS_SUCCESS) { DbgPrint("RegNtDeleteKey -> %wZ", object_name); SendRegistryOperationToUserland(REG_DELETE_KEY, object_name); } else { DbgPrint("RegNtDeleteKey -> Unable to recover the object name."); } //Free the AllocatedPool if (object_name != NULL) ExFreePoolWithTag(object_name, SPY_TAG); } break; case RegNtDeleteValueKey: { PREG_DELETE_VALUE_KEY_INFORMATION CallbackData = (PREG_DELETE_VALUE_KEY_INFORMATION)arg2; //In this case use the ObQueryNameString //TODO -> Determine if Paged should work here. ULONG allocatedSTRSize = 1024 * sizeof(UNICODE_STRING); PUNICODE_STRING object_name = ExAllocatePoolWithTag(NonPagedPool, 1024 * sizeof(UNICODE_STRING), SPY_TAG); ULONG returnedLength; //CAll obQueryNAmeString. NTSTATUS obQueryStatus = ObQueryNameString(CallbackData->Object , (POBJECT_NAME_INFORMATION)object_name , allocatedSTRSize , &returnedLength); if (obQueryStatus == STATUS_SUCCESS) { DbgPrint("RegNtDeleteValueKey -> %wZ", object_name); SendRegistryOperationToUserland(REG_DELETE_VALUE, object_name); } else { DbgPrint("RegNtDeleteValueKey -> Unable to recover the object name."); } //Free the AllocatedPool if (object_name != NULL) ExFreePoolWithTag(object_name, SPY_TAG); } break; case RegNtSetValueKey: { PREG_SET_VALUE_KEY_INFORMATION CallbackData = (PREG_SET_VALUE_KEY_INFORMATION)arg2; //In this case use the ObQueryNameString //TODO -> Determine if Paged should work here. ULONG allocatedSTRSize = 1024 * sizeof(UNICODE_STRING); PUNICODE_STRING root_name = ExAllocatePoolWithTag(NonPagedPool, 1024 * sizeof(UNICODE_STRING), SPY_TAG); ULONG returnedLength; //CAll obQueryNAmeString. NTSTATUS obQueryStatus = ObQueryNameString(CallbackData->Object , (POBJECT_NAME_INFORMATION)root_name , allocatedSTRSize , &returnedLength); if (obQueryStatus == STATUS_SUCCESS) { ULONG newSize = CallbackData->ValueName->Length + root_name->Length + 1; if (newSize < allocatedSTRSize) { RtlUnicodeStringCat(root_name, "\\"); RtlUnicodeStringCat(root_name, CallbackData->ValueName); //Use CallbackData->Data and DataSize to detect wich is the new data to modify SendRegistryOperationToUserland(REG_SET_VALUE, root_name); DbgPrint("RegNtSetValueKey -> %wZ", root_name); } } else { DbgPrint("RegNtSetValueKey -> Unable to recover the object name."); } //Free the AllocatedPool if (root_name != NULL) ExFreePoolWithTag(root_name, SPY_TAG); } break; } return STATUS_SUCCESS; }
NTSTATUS NTAPI SeInitializeProcessAuditName(IN PFILE_OBJECT FileObject, IN BOOLEAN DoAudit, OUT POBJECT_NAME_INFORMATION *AuditInfo) { OBJECT_NAME_INFORMATION LocalNameInfo; POBJECT_NAME_INFORMATION ObjectNameInfo = NULL; ULONG ReturnLength = 8; NTSTATUS Status; PAGED_CODE(); ASSERT(AuditInfo); /* Check if we should do auditing */ if (DoAudit) { /* FIXME: TODO */ } /* Now query the name */ Status = ObQueryNameString(FileObject, &LocalNameInfo, sizeof(LocalNameInfo), &ReturnLength); if (((Status == STATUS_BUFFER_OVERFLOW) || (Status == STATUS_BUFFER_TOO_SMALL) || (Status == STATUS_INFO_LENGTH_MISMATCH)) && (ReturnLength != sizeof(LocalNameInfo))) { /* Allocate required size */ ObjectNameInfo = ExAllocatePoolWithTag(NonPagedPool, ReturnLength, TAG_SEPA); if (ObjectNameInfo) { /* Query the name again */ Status = ObQueryNameString(FileObject, ObjectNameInfo, ReturnLength, &ReturnLength); } } /* Check if we got here due to failure */ if ((ObjectNameInfo) && (!(NT_SUCCESS(Status)) || (ReturnLength == sizeof(LocalNameInfo)))) { /* First, free any buffer we might've allocated */ ASSERT(FALSE); if (ObjectNameInfo) ExFreePool(ObjectNameInfo); /* Now allocate a temporary one */ ReturnLength = sizeof(OBJECT_NAME_INFORMATION); ObjectNameInfo = ExAllocatePoolWithTag(NonPagedPool, sizeof(OBJECT_NAME_INFORMATION), TAG_SEPA); if (ObjectNameInfo) { /* Clear it */ RtlZeroMemory(ObjectNameInfo, ReturnLength); Status = STATUS_SUCCESS; } } /* Check if memory allocation failed */ if (!ObjectNameInfo) Status = STATUS_NO_MEMORY; /* Return the audit name */ *AuditInfo = ObjectNameInfo; /* Return status */ return Status; }
BOOLEAN GetRegistryObjectCompleteName( PUNICODE_STRING pRegistryPath, PUNICODE_STRING pPartialRegistryPath, PVOID pRegistryObject ) { NTSTATUS status; BOOLEAN bFoundCompleteName = FALSE; ULONG ulReturLength; PUNICODE_STRING pObjectName = NULL; if ((!MmIsAddressValid(pRegistryObject)) || (pRegistryObject == NULL)) { return FALSE; } /* 如果 pPartialRegistryPath 不为 NULL,且符合绝对路径规则,则直接返回给外部使用*/ if (pPartialRegistryPath != NULL && pPartialRegistryPath->Length >= 4) { if ((((pPartialRegistryPath->Buffer[0] == '\\') || (pPartialRegistryPath->Buffer[0] == '%')) || ((pPartialRegistryPath->Buffer[0] == 'T') && (pPartialRegistryPath->Buffer[1] == 'R') && (pPartialRegistryPath->Buffer[2] == 'Y') && (pPartialRegistryPath->Buffer[3] == '\\')))) { RtlCopyUnicodeString(pRegistryPath, pPartialRegistryPath); bFoundCompleteName = TRUE; } } /* 如果不符合绝对路径规则,则查询 pRegistryObject 对应的注册表对象和 pPartialRegistryPath 拼接 */ if (!bFoundCompleteName) { status = ObQueryNameString(pRegistryObject, NULL, 0, &ulReturLength); if (status == STATUS_INFO_LENGTH_MISMATCH) { pObjectName = ExAllocatePoolWithTag(NonPagedPool, ulReturLength, MEM_TAG); status = ObQueryNameString(pRegistryObject, (POBJECT_NAME_INFORMATION)pObjectName, ulReturLength, &ulReturLength); if (NT_SUCCESS(status)) { /* 将查询到的注册表对象拷贝到传出参数中 */ RtlCopyUnicodeString(pRegistryPath, pObjectName); /* 如果 pPartialRegistryPath 不为 NULL,则是新建的项名 */ /* 如果为 NULL,则是删除项名,不用拷贝到路径后面。*/ if (NULL != pPartialRegistryPath) { status = RtlUnicodeStringCatString(pRegistryPath, L"\\"); if (!NT_SUCCESS(status)) { KdPrint(("Failed to call RtlUnicodeStringCatString, error code = 0x%08X\r\n", status)); } RtlUnicodeStringCat(pRegistryPath, pPartialRegistryPath); if (!NT_SUCCESS(status)) { KdPrint(("Failed to call RtlUnicodeStringCat, error code = 0x%08X\r\n", status)); } } bFoundCompleteName = TRUE; } ExFreePoolWithTag(pObjectName, MEM_TAG); } } return bFoundCompleteName; }
int handle_fobject(PFILE_OBJECT fobject, PUCHAR obuffer) { ULONG length; ANSI_STRING astring; PUCHAR fname, cur_pointer; PFILE_OBJECT related_fobject; UCHAR status; fname=obuffer+12; status=0; if(fobject->DeviceObject!=NULL) { if(NT_SUCCESS(ObQueryNameString(fobject->DeviceObject, (POBJECT_NAME_INFORMATION)fname,out_size-20,&length))) { if(NT_SUCCESS(RtlUnicodeStringToAnsiString(&astring, (PUNICODE_STRING)fname,TRUE))) { *fname='\0'; strncpy(fname, astring.Buffer, astring.Length+1); status=1; fname+=astring.Length; *fname='\0'; RtlFreeAnsiString(&astring); } } } if((length=fobject->FileName.Length>>1)||(fobject->RelatedFileObject!=NULL)) { related_fobject=fobject->RelatedFileObject; if(length&&(fobject->FileName.Buffer[0]!='\\')) while(related_fobject!=NULL) { length+=related_fobject->FileName.Length>>1; related_fobject=related_fobject->RelatedFileObject; } if(length) { RtlUnicodeStringToAnsiString(&astring,&(fobject->FileName),TRUE); strncpy(cur_pointer=fname+(length-(fobject->FileName.Length>>1)), astring.Buffer,astring.Length+1); status=1; RtlFreeAnsiString(&astring); related_fobject=fobject->RelatedFileObject; if(fobject->FileName.Buffer[0]!='\\') while(related_fobject!=NULL) { *(cur_pointer-1)='\\'; cur_pointer-=(related_fobject->FileName.Length>>1);//+1; RtlUnicodeStringToAnsiString(&astring,&(related_fobject->FileName), TRUE); strncpy(cur_pointer, astring.Buffer, astring.Length+1); status=1; RtlFreeAnsiString(&astring); related_fobject=related_fobject->RelatedFileObject; } } } return(status?(fname-obuffer)+length:0); }
////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Description : // Registry callback. Logs any registry interaction performed by monitored processes. // Parameters : // See http://msdn.microsoft.com/en-us/library/windows/hardware/ff560903(v=vs.85).aspx // Return value : // See http://msdn.microsoft.com/en-us/library/windows/hardware/ff560903(v=vs.85).aspx // Process : // Checks the operation and logs the associated data. ////////////////////////////////////////////////////////////////////////////////////////////////////////////// NTSTATUS regCallback (PVOID CallbackContext, PVOID Argument1, PVOID Argument2) { NTSTATUS status, tmpCall; UNICODE_STRING full_data, test; PUNICODE_STRING tmp = NULL; PUNICODE_STRING valueName = NULL; PREG_SET_VALUE_KEY_INFORMATION arg = NULL; ULONG returnedLength = 0; PWCHAR pwBuf = NULL; PWCHAR tmp_data = NULL; ULONG pid = (ULONG)PsGetCurrentProcessId(); DWORD i = 0; if(!isProcessMonitoredByPid(pid) || ExGetPreviousMode() == KernelMode) return STATUS_SUCCESS; pwBuf = ExAllocatePoolWithTag(NonPagedPool, (MAXSIZE+1)*sizeof(WCHAR), BUFFER_TAG); if(pwBuf == NULL) return STATUS_SUCCESS; tmp = ExAllocatePoolWithTag(NonPagedPool, MAXSIZE*sizeof(WCHAR), TEMP_TAG); if(tmp == NULL) { ExFreePool(tmp); return STATUS_SUCCESS; } switch((REG_NOTIFY_CLASS)Argument1) { case RegNtPreDeleteKey: status = ObQueryNameString(((PREG_DELETE_KEY_INFORMATION)Argument2)->Object, (POBJECT_NAME_INFORMATION)tmp, MAXSIZE, &returnedLength); if(NT_SUCCESS(status)) { #ifdef DEBUG DbgPrint("call DeleteKey() \n"); #endif if(NT_SUCCESS(RtlStringCchPrintfW(pwBuf, MAXSIZE, L"1,0,s,SubKey->%wZ", tmp))) sendLogs(pid, L"REGISTRY_DELETE_KEY", pwBuf); else sendLogs(pid, L"REGISTRY_DELETE_KEY", L"1,0,s,SubKey->ERROR"); } else sendLogs(pid, L"REGISTRY_DELETE_KEY", L"0,-1,s,SubKey->ERROR"); break; case RegNtPreSetValueKey: arg = (PREG_SET_VALUE_KEY_INFORMATION)Argument2; status = ObQueryNameString(arg->Object, (POBJECT_NAME_INFORMATION)tmp, MAXSIZE, &returnedLength); if(NT_SUCCESS(status)) { #ifdef DEBUG DbgPrint("call SetValueKey() \n"); #endif switch(arg->Type) { case REG_SZ: tmpCall = RtlStringCchPrintfW(pwBuf, MAXSIZE, L"1,0,sss,SubKey->%wZ,ValueName->%wZ,Data->%ws", tmp, arg->ValueName, ((PWCHAR)arg->Data)); break; default : tmp_data = ExAllocatePoolWithTag(NonPagedPool, MAXSIZE, 'gnaA'); full_data.MaximumLength = MAXSIZE; full_data.Buffer = ExAllocatePoolWithTag(NonPagedPool, full_data.MaximumLength, 'baaH'); RtlZeroMemory(full_data.Buffer, full_data.MaximumLength); for(i=0; i<arg->DataSize; i++) { if(i==100) break; RtlStringCchPrintfW(tmp_data, MAXSIZE, L"\\x%02x", *((PWCHAR)arg->Data+i)); if(i==0) { RtlInitUnicodeString(&test, tmp_data); RtlCopyUnicodeString(&full_data, &test); } if(NT_SUCCESS(RtlAppendUnicodeToString(&full_data, tmp_data))) RtlZeroMemory(tmp_data, MAXSIZE); } tmpCall = RtlStringCchPrintfW(pwBuf, MAXSIZE, L"1,0,sss,SubKey->%wZ,ValueName->%wZ,Data->%wZ", tmp, arg->ValueName, &full_data); ExFreePool(full_data.Buffer); ExFreePool(tmp_data); break; } if(NT_SUCCESS(tmpCall)) sendLogs(pid, L"REGISTRY_VALUE_KEY_SET", pwBuf); else sendLogs(pid, L"REGISTRY_VALUE_KEY_SET", L"1,0,sss,SubKey->ERROR,ValueName->ERROR,Data->ERROR"); } else sendLogs(pid, L"REGISTRY_VALUE_KEY_SET", L"1,0,sss,SubKey->ERROR,ValueName->ERROR,Data->ERROR"); break; case RegNtPreDeleteValueKey: status = ObQueryNameString(((PREG_DELETE_VALUE_KEY_INFORMATION)Argument2)->Object, (POBJECT_NAME_INFORMATION)tmp, MAXSIZE, &returnedLength); if(NT_SUCCESS(status)) { #ifdef DEBUG DbgPrint("call DeleteValueKey() !\n"); #endif if(NT_SUCCESS(RtlStringCchPrintfW(pwBuf, MAXSIZE, L"1,0,ss,SubKey->%wZ,ValueName->%wZ", tmp, ((PREG_DELETE_VALUE_KEY_INFORMATION)Argument2)->ValueName))) sendLogs(pid, L"REGISTRY_VALUE_KEY_DELETE", pwBuf); else sendLogs(pid, L"REGISTRY_VALUE_KEY_DELETE", L"1,0,ss,SubKey->ERROR,ValueName->ERROR"); } else sendLogs(pid, L"REGISTRY_VALUE_KEY_DELETE", L"1,0,ss,SubKey->ERROR,ValueName->ERROR"); break; case RegNtPreRenameKey: status = ObQueryNameString(((PREG_RENAME_KEY_INFORMATION)Argument2)->Object, (POBJECT_NAME_INFORMATION)tmp, MAXSIZE, &returnedLength); if(NT_SUCCESS(status)) { #ifdef DEBUG DbgPrint("call RenameKey() !\n"); #endif if(NT_SUCCESS(RtlStringCchPrintfW(pwBuf, MAXSIZE, L"1,0,ss,SubKey->%wZ,NewName->%wZ", tmp, ((PREG_RENAME_KEY_INFORMATION)Argument2)->NewName))) sendLogs(pid, L"REGISTRY_KEY_RENAME", pwBuf); else sendLogs(pid, L"REGISTRY_KEY_RENAME", L"1,0,ss,SubKey->ERROR,NewName->ERROR"); } else sendLogs(pid, L"REGISTRY_KEY_RENAME", L"1,0,ss,SubKey->ERROR,NewName->ERROR"); break; case RegNtPreEnumerateKey: status = ObQueryNameString(((PREG_ENUMERATE_KEY_INFORMATION)Argument2)->Object, (POBJECT_NAME_INFORMATION)tmp, MAXSIZE, &returnedLength); if(NT_SUCCESS(status)) { #ifdef DEBUG DbgPrint("call EnumerateKey() !\n"); #endif if(NT_SUCCESS(RtlStringCchPrintfW(pwBuf, MAXSIZE, L"1,0,s,SubKey->%wZ", tmp))) sendLogs(pid, L"REGISTRY_ENUMERATE_KEY", pwBuf); else sendLogs(pid, L"REGISTRY_ENUMERATE_KEY", L"1,0,s,SubKey->ERROR"); } else sendLogs(pid, L"REGISTRY_ENUMERATE_KEY", L"1,0,s,SubKey->ERROR"); break; case RegNtPreEnumerateValueKey: status = ObQueryNameString(((PREG_ENUMERATE_VALUE_KEY_INFORMATION)Argument2)->Object, (POBJECT_NAME_INFORMATION)tmp, MAXSIZE, &returnedLength); if(NT_SUCCESS(status)) { #ifdef DEBUG DbgPrint("call EnumerateValueKey() !\n"); #endif if(NT_SUCCESS(RtlStringCchPrintfW(pwBuf, MAXSIZE, L"1,0,s,SubKey->%wZ", tmp))) sendLogs(pid, L"REGISTRY_ENUMERATE_VALUE_KEY", pwBuf); else sendLogs(pid, L"REGISTRY_ENUMERATE_VALUE_KEY", L"1,0,s,SubKey->ERROR"); } else sendLogs(pid, L"REGISTRY_ENUMERATE_VALUE_KEY", L"1,0,s,SubKey->ERROR"); break; case RegNtPreQueryKey: status = ObQueryNameString(((PREG_QUERY_KEY_INFORMATION)Argument2)->Object, (POBJECT_NAME_INFORMATION)tmp, MAXSIZE, &returnedLength); if(NT_SUCCESS(status)) { #ifdef DEBUG DbgPrint("call QueryKey()! \n"); #endif if(NT_SUCCESS(RtlStringCchPrintfW(pwBuf, MAXSIZE, L"1,0,s,SubKey->%wZ", tmp))) sendLogs(pid, L"REGISTRY_QUERY_KEY", pwBuf); else sendLogs(pid, L"REGISTRY_QUERY_KEY", L"1,0,s,SubKey->ERROR"); } else sendLogs(pid, L"REGISTRY_QUERY_KEY", L"1,0,s,SubKey->ERROR"); break; case RegNtPreQueryValueKey: status = ObQueryNameString(((PREG_QUERY_VALUE_KEY_INFORMATION)Argument2)->Object, (POBJECT_NAME_INFORMATION)tmp, MAXSIZE, &returnedLength); if(NT_SUCCESS(status)) { #ifdef DEBUG DbgPrint("call QueryValueKey() !\n"); #endif if(NT_SUCCESS(RtlStringCchPrintfW(pwBuf, MAXSIZE, L"1,0,ss,SubKey->%wZ,ValueName->%wZ", tmp, ((PREG_QUERY_VALUE_KEY_INFORMATION)Argument2)->ValueName))) sendLogs(pid, L"REGISTRY_QUERY_VALUE_KEY", pwBuf); else sendLogs(pid, L"REGISTRY_QUERY_VALUE_KEY", L"1,0,ss,SubKey->ERROR,ValueName->ERROR"); } else sendLogs(pid, L"REGISTRY_QUERY_VALUE_KEY", L"1,0,ss,SubKey->ERROR,ValueName->ERROR"); break; case RegNtPreCreateKey: #ifdef DEBUG DbgPrint("call CreateKey() !\n"); #endif if(NT_SUCCESS(RtlStringCchPrintfW(pwBuf, MAXSIZE, L"1,0,s,SubKey->%wZ", ((PREG_PRE_CREATE_KEY_INFORMATION)Argument2)->CompleteName))) sendLogs(pid,L"REGISTRY_CREATE_KEY", pwBuf); else sendLogs(pid, L"REGISTRY_CREATE_KEY", L"1,0,s,SubKey->ERROR"); break; case RegNtPreCreateKeyEx: #ifdef DEBUG DbgPrint("call CreateKeyEx() !\n"); #endif if(NT_SUCCESS(RtlStringCchPrintfW(pwBuf, MAXSIZE, L"1,0,s,SubKey->%wZ", ((PREG_PRE_CREATE_KEY_INFORMATION)Argument2)->CompleteName))) sendLogs(pid,L"REGISTRY_CREATE_KEY", pwBuf); else sendLogs(pid, L"REGISTRY_CREATE_KEY", L"1,0,s,SubKey->ERROR"); break; case RegNtPreOpenKey: #ifdef DEBUG DbgPrint("call OpenKey() !\n"); #endif if(((PREG_OPEN_KEY_INFORMATION)Argument2)->CompleteName->Buffer != NULL) { if(!_wcsicmp(((PREG_OPEN_KEY_INFORMATION)Argument2)->CompleteName->Buffer, L"SOFTWARE\\Oracle\\VirtualBox Guest Additions") || !_wcsicmp(((PREG_OPEN_KEY_INFORMATION)Argument2)->CompleteName->Buffer, L"SOFTWARE\\VMware, Inc.\\VMware Tools")) { if(NT_SUCCESS(RtlStringCchPrintfW(pwBuf, MAXSIZE, L"0,0,s,SubKey->%wZ", ((PREG_OPEN_KEY_INFORMATION)Argument2)->CompleteName))) sendLogs(pid,L"REGISTRY_OPEN_KEY", pwBuf); return STATUS_OBJECT_NAME_NOT_FOUND; } if(NT_SUCCESS(RtlStringCchPrintfW(pwBuf, MAXSIZE, L"1,0,s,SubKey->%wZ", ((PREG_OPEN_KEY_INFORMATION)Argument2)->CompleteName))) sendLogs(pid,L"REGISTRY_OPEN_KEY", pwBuf); else sendLogs(pid, L"REGISTRY_OPEN_KEY", L"1,0,s,SubKey->ERROR"); } else sendLogs(pid, L"REGISTRY_OPEN_KEY", L"1,0,s,SubKey->ERROR"); break; case RegNtPreOpenKeyEx: #ifdef DEBUG DbgPrint("call OpenKeyEx() !\n"); #endif if(((PREG_OPEN_KEY_INFORMATION)Argument2)->CompleteName->Buffer != NULL) { if(!_wcsicmp(((PREG_OPEN_KEY_INFORMATION)Argument2)->CompleteName->Buffer, L"SOFTWARE\\Oracle\\VirtualBox Guest Additions") || !_wcsicmp(((PREG_OPEN_KEY_INFORMATION)Argument2)->CompleteName->Buffer, L"SOFTWARE\\VMware, Inc.\\VMware Tools")) { if(NT_SUCCESS(RtlStringCchPrintfW(pwBuf, MAXSIZE, L"0,0,s,SubKey->%wZ", ((PREG_OPEN_KEY_INFORMATION)Argument2)->CompleteName))) sendLogs(pid,L"REGISTRY_OPEN_KEY", pwBuf); return STATUS_OBJECT_NAME_NOT_FOUND; } if(NT_SUCCESS(RtlStringCchPrintfW(pwBuf, MAXSIZE, L"1,0,s,SubKey->%wZ", ((PREG_OPEN_KEY_INFORMATION)Argument2)->CompleteName))) sendLogs(pid,L"REGISTRY_OPEN_KEY", pwBuf); else sendLogs(pid, L"REGISTRY_OPEN_KEY", L"1,0,s,SubKey->ERROR"); } else sendLogs(pid, L"REGISTRY_OPEN_KEY", L"1,0,s,SubKey->ERROR"); break; default: break; } ExFreePool(tmp); ExFreePool(pwBuf); return STATUS_SUCCESS; }
VOID drbdlockCallbackFunc( IN PVOID Context, IN PVOID Argument1, IN PVOID Argument2 ) /*++ Routine Description: This routine is called whenever other driver notifies drbdlock's callback object. Arguments: Context - not used. Argument1 - Pointer to the DRBDLOCK_VOLUME_CONTROL data structure containing volume information to be (un)blocked. Argument2 - not used. Return Value: None. --*/ { UNREFERENCED_PARAMETER(Context); UNREFERENCED_PARAMETER(Argument2); PDRBDLOCK_VOLUME_CONTROL pVolumeControl = (PDRBDLOCK_VOLUME_CONTROL)Argument1; PDEVICE_OBJECT pVolObj = NULL; NTSTATUS status = STATUS_UNSUCCESSFUL; ULONG ulSize = 0; POBJECT_NAME_INFORMATION pNameInfo = NULL; if (pVolumeControl == NULL) { // invalid parameter. drbdlock_print_log("pVolumeControl is NULL\n"); return; } status = ConvertVolume(&pVolumeControl->volume, &pVolObj); if (!NT_SUCCESS(status)) { drbdlock_print_log("ConvertVolume failed, status : 0x%x\n", status); return; } if (STATUS_INFO_LENGTH_MISMATCH == ObQueryNameString(pVolObj, NULL, 0, &ulSize)) { pNameInfo = (POBJECT_NAME_INFORMATION)ExAllocatePool(NonPagedPool, ulSize); if (pNameInfo) { status = ObQueryNameString(pVolObj, pNameInfo, ulSize, &ulSize); if (!NT_SUCCESS(status)) { ulSize = 0; } } } if (pVolumeControl->bBlock) { if (AddProtectedVolume(pVolObj)) { drbdlock_print_log("volume(%ws) has been added as protected\n", ulSize? pNameInfo->Name.Buffer : L"NULL"); } else { drbdlock_print_log("volume(%ws) add failed\n", ulSize ? pNameInfo->Name.Buffer : L"NULL"); } } else { if (DeleteProtectedVolume(pVolObj)) { drbdlock_print_log("volume(%ws) has been deleted from protected volume list\n", ulSize ? pNameInfo->Name.Buffer : L"NULL"); } else { drbdlock_print_log("volume(%ws) delete failed\n", ulSize ? pNameInfo->Name.Buffer : L"NULL"); } } }