Exemple #1
0
NTSTATUS DriverEntry(PDRIVER_OBJECT driver, PUNICODE_STRING str)
{
	UNREFERENCED_PARAMETER(driver);
	UNREFERENCED_PARAMETER(str);
	dri = driver;
	driver->DriverUnload = unload;
	for (int i = 0; i < IRP_MJ_MAXIMUM_FUNCTION; i++)
	{
		driver->MajorFunction[i] = dispatch;
	}
	PFILE_OBJECT file;
	UNICODE_STRING tcpname;
	UNICODE_STRING udpname;
	UNICODE_STRING ipname;
	RtlInitUnicodeString(&tcpname, TCP);
	RtlInitUnicodeString(&udpname, UDP);
	RtlInitUnicodeString(&ipname, IP);
	IoGetDeviceObjectPointer(&udpname, FILE_ALL_ACCESS, &file, &udpreal);
	ObfDereferenceObject(file);
	IoGetDeviceObjectPointer(&tcpname, FILE_ALL_ACCESS, &file, &tcpreal);
	ObfDereferenceObject(file);
	IoGetDeviceObjectPointer(&ipname, FILE_ALL_ACCESS, &file, &ipreal);
	ObfDereferenceObject(file);
	attach(&tcpname, DEVTYPE_TCP);
	attach(&udpname, DEVTYPE_UDP);
	attach(&ipname, DEVTYPE_IP);
	return STATUS_SUCCESS;
}
Exemple #2
0
// Remembers a SYSTEM token and its owner name if applicable
_Use_decl_annotations_ static bool EopmonpCheckProcessToken(HANDLE pid,
                                                            void* context) {
  PAGED_CODE();
  UNREFERENCED_PARAMETER(context);

  const char* NTAPI PsGetProcessImageFileName(_In_ PEPROCESS Process);

  // Get EPROCESS
  PEPROCESS process = nullptr;
  auto status = PsLookupProcessByProcessId(pid, &process);
  if (!NT_SUCCESS(status)) {
    return true;
  }

  // Test if a process name of this pid matches with any of known system
  // processes.
  const auto process_name = PsGetProcessImageFileName(process);
  for (auto system_process_name : kEopmonpSystemProcessNames) {
    if (!RtlEqualMemory(process_name, system_process_name,
                        strlen(system_process_name) + 1)) {
      continue;
    }

    // System process found
    const auto token = PsReferencePrimaryToken(process);

    // Initialize g_eopmonp_offset_to_token if not yet
    if (!g_eopmonp_offset_to_token && !EopmonpInitTokenOffset(process, token)) {
      PsDereferencePrimaryToken(token);
      ObfDereferenceObject(process);
      return false;  // error. cannot continue
    }

    // PLACE TO IMPROVE:
    // EopMon updates a list of system processes' tokens and IDs only once,
    // while some of them like csrss.exe and winlogon.exe can be terminated and
    // re-launched when a use logout and logon to the system. One solution would
    // be installing process notification callback and maintain the latest
    // system process list.
    g_eopmonp_system_process_tokens->emplace_back(token, system_process_name);
    g_eopmonp_system_process_ids->push_back(pid);
    HYPERPLATFORM_LOG_INFO("System Token %p with PID=%Iu %s", token, pid,
                           system_process_name);

    PsDereferencePrimaryToken(token);
  }

  ObfDereferenceObject(process);
  return true;
}
Exemple #3
0
NTSTATUS OpenProcess(
					 IN ULONG uPID, 
					 OUT PHANDLE pHandle,
					 IN ACCESS_MASK DesiredAccess)  
{   
	NTSTATUS       rtStatus       = STATUS_SUCCESS;   
	PEPROCESS      pEProcess      = NULL;   
	HANDLE         hTagProcess    = NULL;   
	PULONG         uPsProcessType = 0;   
	UNICODE_STRING StrType;

	rtStatus = PsLookupProcessByProcessId((HANDLE)uPID, &pEProcess);   
	if (NT_SUCCESS(rtStatus))   
	{    
		RtlInitUnicodeString(&StrType, L"PsProcessType");   
		uPsProcessType = (PULONG)MmGetSystemRoutineAddress(&StrType);   
		if (uPsProcessType)   
		{   
			rtStatus = ObOpenObjectByPointer(pEProcess, 0, 0, DesiredAccess, (POBJECT_TYPE)*uPsProcessType, UserMode, &hTagProcess);   
			if (NT_SUCCESS(rtStatus))   
			{   
				*pHandle = hTagProcess;   
			}   
		}   
		ObfDereferenceObject(pEProcess);   
	}    
	return rtStatus;   
}   
NTSTATUS GetFilterDriverByDriverName(WCHAR *wzDriverName, PFILTER_DRIVER FilterDriverInfor, FILTER_TYPE Type)
{
	NTSTATUS Status = STATUS_UNSUCCESSFUL;
	UNICODE_STRING uniDriverName;
	PDRIVER_OBJECT DriverObject = NULL;
	POBJECT_TYPE DriverObjectType = *IoDriverObjectType;


	if (!DriverObjectType)
	{
		return Status;
	}

	RtlInitUnicodeString(&uniDriverName, wzDriverName);

	Status = ObReferenceObjectByName(
		&uniDriverName,
		OBJ_CASE_INSENSITIVE,
		NULL,
		0,
		DriverObjectType,
		KernelMode,
		NULL,
		(PVOID*)&DriverObject);

	if (NT_SUCCESS(Status) && DriverObject)
	{
		PDEVICE_OBJECT DeviceObject = NULL;

		for ( DeviceObject = DriverObject->DeviceObject;
			  DeviceObject;
			  DeviceObject = DeviceObject->NextDevice )
		{


			PDRIVER_OBJECT AttachedDriverObject = DeviceObject->DriverObject;
			PDEVICE_OBJECT AttachDeviceObject = NULL;

			for ( AttachDeviceObject = DeviceObject->AttachedDevice; 
				  AttachDeviceObject; 
				  AttachDeviceObject = AttachDeviceObject->AttachedDevice )
			{
				Status = AddFilterInfo( AttachDeviceObject, AttachedDriverObject, FilterDriverInfor, Type );
				AttachedDriverObject = AttachDeviceObject->DriverObject;
			}

		}

		ObfDereferenceObject(DriverObject);
	}

	return Status;
}
Exemple #5
0
// Gets a creation time of the process
_Use_decl_annotations_ static LONGLONG EopmonpGetProcessCreateTimeQuadPart(
    HANDLE pid) {
  PAGED_CODE();

  PEPROCESS process = nullptr;
  auto status = PsLookupProcessByProcessId(pid, &process);
  if (!NT_SUCCESS(status)) {
    return 0;
  }
  const auto create_time = PsGetProcessCreateTimeQuadPart(process);
  ObfDereferenceObject(process);
  return create_time;
}
Exemple #6
0
void testRoutine(_In_     PDEVICE_OBJECT pDeviceObject, _In_opt_ PVOID          pContext){
	UNREFERENCED_PARAMETER(pDeviceObject);
	UNREFERENCED_PARAMETER(pContext);
	PFILE_OBJECT pFileObj;
	PDEVICE_OBJECT pDevObj;
	NTSTATUS status = STATUS_UNSUCCESSFUL;

	if (!pContext){
		DbgPrint("pcontext null");
		return;
	}
	PMY_WORK_CONTEXT pWorkContext = (PMY_WORK_CONTEXT)pContext;
	status = IoGetDeviceObjectPointer(pWorkContext->pSymlink, 0, &pFileObj, &pDevObj);
	if (status){
		DbgPrint("failed to access devobj!%lX", status);
		return;
	}
	DbgPrint("not failed to access devobj!%lX", status);
	ObfDereferenceObject(pFileObj);
	ObfDereferenceObject(pDevObj);
	//return;
}
PCHAR GetProcessNameByProcessId(HANDLE ProcessId)
{
	NTSTATUS st = STATUS_UNSUCCESSFUL;
	PEPROCESS ProcessObj = NULL;
	PCHAR string = NULL;
	st = PsLookupProcessByProcessId(ProcessId, &ProcessObj);
	if (NT_SUCCESS(st))
	{
		string = PsGetProcessImageFileName(ProcessObj);
		ObfDereferenceObject(ProcessObj);
	}
	return string;
}
VOID
NTAPI
PopProcessShutDownLists(VOID)
{
    PPOP_SHUTDOWN_WAIT_ENTRY ShutDownWaitEntry;
    PWORK_QUEUE_ITEM WorkItem;
    PLIST_ENTRY ListEntry;

    /* First signal the shutdown event */
    KeSetEvent(&PopShutdownEvent, IO_NO_INCREMENT, FALSE);

    /* Acquire the shutdown list lock */
    KeAcquireGuardedMutex(&PopShutdownListMutex);

    /* Block any further attempts to register a shutdown event */
    PopShutdownListAvailable = FALSE;

    /* Release the list lock, since we are exclusively using the lists now */
    KeReleaseGuardedMutex(&PopShutdownListMutex);

    /* Process the shutdown queue */
    while (!IsListEmpty(&PopShutdownQueue))
    {
        /* Get the head entry */
        ListEntry = RemoveHeadList(&PopShutdownQueue);
        WorkItem = CONTAINING_RECORD(ListEntry, WORK_QUEUE_ITEM, List);

        /* Call the shutdown worker routine */
        WorkItem->WorkerRoutine(WorkItem->Parameter);
    }

    /* Now process the shutdown thread list */
    while (PopShutdownThreadList != NULL)
    {
        /* Get the top entry and remove it from the list */
        ShutDownWaitEntry = PopShutdownThreadList;
        PopShutdownThreadList = PopShutdownThreadList->NextEntry;

        /* Wait for the thread to finish and dereference it */
        KeWaitForSingleObject(ShutDownWaitEntry->Thread, 0, 0, 0, 0);
        ObfDereferenceObject(ShutDownWaitEntry->Thread);

        /* Finally free the entry */
        ExFreePoolWithTag(ShutDownWaitEntry, 0);
    }
}
Exemple #9
0
// Terminates a given process and wait for its completion.
_Use_decl_annotations_ static void EopmonpTerminateProcessWorkerRoutine(
    void* parameter) {
  PAGED_CODE();

  // HYPERPLATFORM_COMMON_DBG_BREAK();

  const auto context = reinterpret_cast<EopmonWorkQueueItem*>(parameter);
  const auto dodgy_pid = context->dodgy_pid;
  const auto system_process_name = context->system_process_name;

  const auto process_handle = EopmonpOpenProcess(dodgy_pid);
  if (!process_handle) {
    goto exit;
  }

  // Terminate it and wait
  auto status = EopmonpTerminateProcessTree(process_handle, dodgy_pid);
  if (status == STATUS_PROCESS_IS_TERMINATING) {
    goto exit_with_close;
  }

  // log stuff
  const auto process_path = EopmonpGetProcessPathByHandle(process_handle);
  if (!process_path) {
    HYPERPLATFORM_LOG_INFO(
        "Exploitation detected. Process %Iu has been killed. Stolen token from "
        "%s",
        dodgy_pid, system_process_name);
    goto exit_with_close;
  }

  PEPROCESS process = nullptr;
  status = PsLookupProcessByProcessId(dodgy_pid, &process);
  if (!NT_SUCCESS(status)) {
    HYPERPLATFORM_LOG_INFO(
        "Exploitation detected. Process %Iu has been killed. Stolen token from "
        "%s. Image= %wZ",
        dodgy_pid, system_process_name, process_path);
    ExFreePoolWithTag(process_path, kHyperPlatformCommonPoolTag);
    goto exit_with_close;
  }

  const auto token = PsReferencePrimaryToken(process);
  HYPERPLATFORM_LOG_INFO(
      "Exploitation detected. Process %Iu has been killed. Stolen token %p "
      "from %s. Image= %wZ",
      dodgy_pid, token, system_process_name, process_path);

  PsDereferencePrimaryToken(token);
  ObfDereferenceObject(process);
  ExFreePoolWithTag(process_path, kHyperPlatformCommonPoolTag);

exit_with_close:;
  ZwClose(process_handle);

  // Delete this PID from ones being marked as already queued
  for (auto& pid_being_killed : g_eopmonp_processes_being_killed) {
    if (pid_being_killed == dodgy_pid) {
      pid_being_killed = nullptr;
    }
  }

exit:;
  ExFreePoolWithTag(context, kHyperPlatformCommonPoolTag);
}
Exemple #10
0
NTSTATUS  KernelOpenFile(wchar_t *FileFullName, 
	PHANDLE FileHandle, 
	ACCESS_MASK DesiredAccess, 
	ULONG FileAttributes, 
	ULONG ShareAccess, 
	ULONG CreateDisposition, 
	ULONG CreateOptions)
{
	WCHAR SystemRootName[32]=L"\\SystemRoot";
	WCHAR *FileNodeName=NULL;
	UNICODE_STRING FilePath;
	PDEVICE_OBJECT RealDevice,DeviceObject;
	NTSTATUS status=STATUS_UNSUCCESSFUL;
	PFILE_OBJECT FileObject;

	FileNodeName = (WCHAR*)ExAllocatePool(NonPagedPool,260*2);
	if (FileNodeName==NULL)
	{
		return status;
	}
	RtlZeroMemory(FileNodeName,260*2);
	if (_wcsnicmp(FileFullName,SystemRootName,wcslen(SystemRootName)) == 0)
	{
		int Len;
		if(!GetWindowsRootName(FileNodeName))
		{
			ExFreePool(FileNodeName);
			return status;
		}
		Len=wcslen(SystemRootName);
		wcscat(FileNodeName,&FileFullName[Len]);
	}
	else
	{
		if (FileFullName[1]!=0x003A||FileFullName[2]!=0x005C)
		{
			return status;

		}
		wcscpy(FileNodeName,&FileFullName[2]);
	}

	if(!GetDeviceObjectFromFileFullName(FileFullName,&RealDevice,&DeviceObject))
	{
		ExFreePool(FileNodeName);
		return status;
	}
	RtlInitUnicodeString(&FilePath,FileNodeName);
	status = IrpCreateFile(&FilePath,DesiredAccess,FileAttributes,ShareAccess,CreateDisposition,CreateOptions,DeviceObject,RealDevice,&FileObject);
	if (!NT_SUCCESS(status))
	{
		ExFreePool(FileNodeName);
		return status;
	}
	status=ObOpenObjectByPointer(
		FileObject,
		OBJ_KERNEL_HANDLE,    //verifier下测试要指定OBJ_KERNEL_HANDLE
		0,
		DesiredAccess|0x100000,
		*IoFileObjectType,
		0,
		FileHandle);

	ObfDereferenceObject(FileObject);

	return status;
}
Exemple #11
0
BOOL GetDeviceObjectFromFileFullName(WCHAR *FileFullName,PDEVICE_OBJECT *RealDevice, PDEVICE_OBJECT *DeviceObject)
{
	WCHAR wRootName[32]={0};
	UNICODE_STRING RootName;
	OBJECT_ATTRIBUTES ObjectAttributes={0};
	NTSTATUS status;
	HANDLE hFile;
	IO_STATUS_BLOCK IoStatus;
	PFILE_OBJECT FileObject;

	if (FileFullName[0]==0x005C)
	{
		wcscpy(wRootName,L"\\SystemRoot");
	}
	else
	{
		wcscpy(wRootName,L"\\DosDevices\\*:\\");
		wRootName[12]=FileFullName[0];
	}
	RtlInitUnicodeString(&RootName,wRootName);

	InitializeObjectAttributes(&ObjectAttributes, &RootName,
		OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE, NULL, NULL);

	status = IoCreateFile(
		&hFile,
		SYNCHRONIZE,
		&ObjectAttributes,
		&IoStatus,
		0,
		FILE_ATTRIBUTE_NORMAL,
		FILE_SHARE_READ|FILE_SHARE_WRITE,
		FILE_OPEN,
		FILE_DIRECTORY_FILE|FILE_SYNCHRONOUS_IO_NONALERT,
		NULL,
		0,
		0,
		NULL,
		IO_NO_PARAMETER_CHECKING);

	if (!NT_SUCCESS(status))
	{
		return FALSE;
	}
	status=ObReferenceObjectByHandle(hFile,1,*IoFileObjectType,KernelMode,&FileObject,NULL);
	if (!NT_SUCCESS(status))
	{
		ZwClose(hFile);
		return FALSE;
	}
	if(!IoGetFileSystemVpbInfo(FileObject,DeviceObject,RealDevice))
	{
		ObfDereferenceObject(FileObject);
		ZwClose(hFile);
		return FALSE;

	}
	ObfDereferenceObject(FileObject);
	ZwClose(hFile);

	return TRUE;

}
Exemple #12
0
//----- (08000DCF) --------------------------------------------------------
NTSTATUS 
HookDispatch(
	PDRIVER_OBJECT	DriverObject, 
	ULONG			DiskIndex
	)
{
	PCONFIGURATION_INFORMATION	ConfigInfo;
	NTSTATUS					status;
	PIRP						Irp;
	CHAR						SourceString[64] = "";
	STRING						astr;
	UNICODE_STRING				ustr;
	PFILE_OBJECT				FileObject, FileObject1;
	PDEVICE_OBJECT				DeviceObject, DeviceObject1;
	PDRIVE_LAYOUT_INFORMATION	LayoutInfo;
	KEVENT						Event;
	IO_STATUS_BLOCK				iosb;
	OBJECT_ATTRIBUTES			oa;
	HANDLE						Handle;
	ULONG						i, j;

	ConfigInfo = IoGetConfigurationInformation();	

	for(i = DiskIndex; i < ConfigInfo->DiskCount; i++)
	{
		sprintf(SourceString, "\\Device\\Harddisk%d\\Partition0", i);

		RtlInitAnsiString(&astr, SourceString);
		RtlAnsiStringToUnicodeString(&ustr, &astr, TRUE);

		status = IoGetDeviceObjectPointer(&ustr, 0x80, &FileObject, &DeviceObject);

		RtlFreeUnicodeString(&ustr);

		if (!NT_SUCCESS(status))
		{			
			continue;
		}

		AddDeviceToHookEntry(FileObject->DeviceObject, i, 0);

		LayoutInfo = (PDRIVE_LAYOUT_INFORMATION)ExAllocatePool(0, 0x2000);
		if ( LayoutInfo )
		{
			KeInitializeEvent(&Event, NotificationEvent, FALSE);
			Irp = IoBuildDeviceIoControlRequest(IOCTL_DISK_GET_DRIVE_LAYOUT, DeviceObject, NULL, 0, LayoutInfo, 0x2000, FALSE, &Event, &iosb);
			if ( Irp )
			{				
				status = IoCallDriver(DeviceObject, Irp);
				if ( status == STATUS_PENDING )
				{
					KeWaitForSingleObject(&Event, Suspended, KernelMode, FALSE, NULL);
					status = iosb.Status;
				}
				if ( NT_SUCCESS(status) )
				{
					for(j = 1; j < LayoutInfo->PartitionCount; j++)
					{
						sprintf(SourceString, "\\Device\\Harddisk%d\\Partition%d", i, j);

						RtlInitAnsiString(&astr, SourceString);
						RtlAnsiStringToUnicodeString(&ustr, &astr, TRUE);

						status = IoGetDeviceObjectPointer(&ustr, 0x80, &FileObject1, &DeviceObject1);
						RtlFreeUnicodeString(&ustr);

						if (!NT_SUCCESS(status))
						{			
							continue;
						}

						AddDeviceToHookEntry(FileObject1->DeviceObject, i, j);

						ObfDereferenceObject(FileObject1);
					}
				}
			}

			ExFreePool(LayoutInfo);
		}

		ObfDereferenceObject(FileObject);
	}

	return status;
}
Exemple #13
0
		Thread::~Thread()
		{
			//! Remove any otherwise persistent references to this instance
			ObfDereferenceObject(system_thread_handle);
		}
Exemple #14
0
NTSTATUS 
ForceDelete(
			wchar_t *path
			)
{

	HANDLE fileHandle;
	NTSTATUS result;
	IO_STATUS_BLOCK ioBlock;
	DEVICE_OBJECT *device_object;
	void* object = NULL;
	OBJECT_ATTRIBUTES fileObject;
	wchar_t deviceName[14];
	UNICODE_STRING uDeviceName;
	UNICODE_STRING uPath;

	
	EPROCESS *eproc = IoGetCurrentProcess();
	//switch context to UserMode
	KeAttachProcess(eproc);
	
	//initialize file to delete variable
	g_fileToDelete = path;
	g_fileToDelete += 6; //take from \??\C:\example only \example
	

	//e.g "\??\C:\"
	memset(deviceName,0,sizeof(deviceName));
	wcsncpy(deviceName,path,7);
	uDeviceName.Buffer = deviceName;
	uDeviceName.Length = 14;
	//file path to unicode string
	RtlInitUnicodeString(&uPath,path);
	
	InitializeObjectAttributes(&fileObject,
								&uDeviceName,
								OBJ_CASE_INSENSITIVE,
								NULL,
								NULL);

	result = ZwOpenFile(&fileHandle,
						SYNCHRONIZE,
						&fileObject,
						&ioBlock,
						FILE_SHARE_READ,
						FILE_SYNCHRONOUS_IO_NONALERT|FILE_DIRECTORY_FILE);

	if(result != STATUS_SUCCESS)
	{
		DbgPrint("Some problems with open file ;[");
		goto _end;
	}

    if ( !ObReferenceObjectByHandle(fileHandle, 0, 0, 0, &object, 0) )
    {

      device_object = IoGetBaseFileSystemDeviceObject(object);
      ObfDereferenceObject(object);
    }
	
    ZwClose(fileHandle);	
	
	InitializeObjectAttributes(&fileObject,
							   &uPath,
							   OBJ_CASE_INSENSITIVE,
							   NULL,
							   NULL);

	result = IoCreateFileSpecifyDeviceObjectHint(
			   &fileHandle,
			   SYNCHRONIZE | FILE_WRITE_ATTRIBUTES | FILE_READ_ATTRIBUTES | FILE_READ_DATA, //0x100181 
			   &fileObject,
			   &ioBlock,
			   0,
			   0,
			   FILE_SHARE_READ | FILE_SHARE_WRITE |FILE_SHARE_DELETE, //FILE_SHARE_VALID_FLAGS,
			   FILE_OPEN,
			   FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT,//0x60,
			   0,
			   0,
			   CreateFileTypeNone,
			   0,
			   IO_IGNORE_SHARE_ACCESS_CHECK,
			   device_object);
	if(result != STATUS_SUCCESS)
	{
		DbgPrint("error in IoCreateFileSpecifyDeviceObjectHint");
		goto _end;
	}

	result = ObReferenceObjectByHandle(fileHandle, 0, 0, 0, &object, 0);

	if(result != STATUS_SUCCESS)
	{
		DbgPrint("error in ObReferenceObjectByHandle");
		ZwClose(fileHandle);
		goto _end;
	}
	/*
		METHOD 1
	*/
	((FILE_OBJECT*)object)->SectionObjectPointer->ImageSectionObject = 0;
	((FILE_OBJECT*)object)->DeleteAccess = 1;	
	 result = ZwDeleteFile(&fileObject);
	
	if(result != STATUS_SUCCESS)
	{
		DbgPrint("\n[+]error in ZwDeleteFile");
	}
	ObDereferenceObject(object);
	ZwClose(fileHandle);
	 
	result = ZwDeleteFile(&fileObject);
	if(result != STATUS_SUCCESS)
	{
		DbgPrint("\n[+]error in ZwDeleteFile");
		/*
			METHOD 2
		*/		
		r0_fileToDelete(path);
		
		/*
			METHOD 3
			If simple solutions did not help, try this one.
		*/
		hook_it(device_object)
	}
Exemple #15
0
NTSTATUS
NTAPI
PciQueryForPciBusInterface(IN PPCI_FDO_EXTENSION FdoExtension)
{
    PDEVICE_OBJECT AttachedDevice;
    IO_STATUS_BLOCK IoStatusBlock;
    KEVENT Event;
    NTSTATUS Status;
    PIRP Irp;
    PIO_STACK_LOCATION IoStackLocation;
    PPCI_BUS_INTERFACE_STANDARD PciInterface;
    PAGED_CODE();
    ASSERT(PCI_IS_ROOT_FDO(FdoExtension));

    /* Allocate space for the inteface */
    PciInterface = ExAllocatePoolWithTag(NonPagedPool,
                                         sizeof(PCI_BUS_INTERFACE_STANDARD),
                                         PCI_POOL_TAG);
    if (!PciInterface) return STATUS_INSUFFICIENT_RESOURCES;

    /* Get the device the PDO is attached to, should be the Root (ACPI) */
    AttachedDevice = IoGetAttachedDeviceReference(FdoExtension->PhysicalDeviceObject);

    /* Build an IRP for this request */
    KeInitializeEvent(&Event, SynchronizationEvent, FALSE);
    Irp = IoBuildSynchronousFsdRequest(IRP_MJ_PNP,
                                       AttachedDevice,
                                       NULL,
                                       0,
                                       NULL,
                                       &Event,
                                       &IoStatusBlock);
    if (Irp)
    {
        /* Initialize the default PnP response */
        Irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
        Irp->IoStatus.Information = 0;

        /* Make it a Query Interface IRP */
        IoStackLocation = IoGetNextIrpStackLocation(Irp);
        ASSERT(IoStackLocation->MajorFunction == IRP_MJ_PNP);
        IoStackLocation->MinorFunction = IRP_MN_QUERY_INTERFACE;
        IoStackLocation->Parameters.QueryInterface.InterfaceType = &GUID_PCI_BUS_INTERFACE_STANDARD;
        IoStackLocation->Parameters.QueryInterface.Size = sizeof(GUID_PCI_BUS_INTERFACE_STANDARD);
        IoStackLocation->Parameters.QueryInterface.Version = PCI_BUS_INTERFACE_STANDARD_VERSION;
        IoStackLocation->Parameters.QueryInterface.Interface = (PINTERFACE)PciInterface;
        IoStackLocation->Parameters.QueryInterface.InterfaceSpecificData = NULL;

        /* Send it to the root PDO */
        Status = IoCallDriver(AttachedDevice, Irp);
        if (Status == STATUS_PENDING)
        {
            /* Wait for completion */
            KeWaitForSingleObject(&Event,
                                  Executive,
                                  KernelMode,
                                  FALSE,
                                  NULL);
            Status = Irp->IoStatus.Status;
        }

        /* Check if an interface was returned */
        if (!NT_SUCCESS(Status))
        {
            /* No interface was returned by the root PDO */
            FdoExtension->PciBusInterface = NULL;
            ExFreePoolWithTag(PciInterface, 0);
        }
        else
        {
            /* An interface was returned, save it */
            FdoExtension->PciBusInterface = PciInterface;
        }

        /* Dereference the device object because we took a reference earlier */
        ObfDereferenceObject(AttachedDevice);
    }
    else
    {
        /* Failure path, dereference the device object and set failure code */
        if (AttachedDevice) ObfDereferenceObject(AttachedDevice);
        ExFreePoolWithTag(PciInterface, 0);
        Status = STATUS_INSUFFICIENT_RESOURCES;
    }

    /* Return status code to caller */
    return Status;
}