A forum for reverse engineering, OS internals and malware analysis 

Forum for discussion about kernel-mode development.
 #8940  by Tigzy
 Mon Oct 03, 2011 3:09 pm
Yet another! :D

I got my driver / device list.
I'm trying to get a DEVICE_OBJECT with the device name
Code: Select all
InitializeObjectAttributes( &attributes, &deviceUnicodeString, 0, 0, NULL );
status = ObOpenObjectByName( &attributes, *IoDeviceObjectType, KernelMode, NULL, 0x80000000, NULL, &handle );
if (!NT_SUCCESS(status))
{
	 DbgPrint("Error : %ws : 0x%x\n", name.Buffer, status);
	continue;
}
ObReferenceObjectByHandle( handle, FILE_ALL_ACCESS, NULL, KernelMode, &pDev, NULL );
ZwClose( handle );
It returns STATUS_OBJECT_TYPE_MISMATCH...

The 2 are defined the same way, but only IoDriverObjectType works...
Code: Select all
extern POBJECT_TYPE* IoDriverObjectType;
extern POBJECT_TYPE* IoDeviceObjectType;
 #8941  by Alex
 Mon Oct 03, 2011 4:48 pm
You can't use the same method for devices - just look at ObOpenObjectByName body (WRK). And here is an alternative method:
Code: Select all
PVOID ObGetObpRootDirectoryObject()
{
	NTSTATUS NtStatus = STATUS_UNSUCCESSFUL;
	HANDLE DirectoryHandle;

	OBJECT_ATTRIBUTES ObjectAttributes = {0};
	UNICODE_STRING DirectoryName;
	OBJECT_DIRECTORY *DirectoryObject = NULL;


	RtlInitUnicodeString(
						 &DirectoryName,
						 L"\\");

	ObjectAttributes.Length = sizeof(OBJECT_ATTRIBUTES);
	ObjectAttributes.ObjectName = &DirectoryName;
	ObjectAttributes.Attributes = OBJ_CASE_INSENSITIVE;

	NtStatus = ZwOpenDirectoryObject(
									 &DirectoryHandle,
									 0,
									 &ObjectAttributes);

	if(NT_SUCCESS(NtStatus))
	{
		NtStatus = ObReferenceObjectByHandle(
											 DirectoryHandle,
											 0,
											 NULL,
											 KernelMode,
											 &DirectoryObject,
											 NULL);
		if(NT_SUCCESS(NtStatus))
			ObfDereferenceObject(DirectoryObject);

		ZwClose(DirectoryHandle);
	}

	return DirectoryObject;
}


PVOID ObGetDosDevicesDirectory()
{
	NTSTATUS NtStatus = STATUS_UNSUCCESSFUL;

	PVOID ObpRootDirectoryObject = NULL;
	PVOID Object = NULL;

	OBJECT_HEADER *ObjectHeader = NULL;
	UNICODE_STRING ObjectName;


	ObpRootDirectoryObject = ObGetObpRootDirectoryObject();

	if(IsKernelAddressValid(ObpRootDirectoryObject))
	{
		ObjectHeader = OBJECT_TO_OBJECT_HEADER(ObpRootDirectoryObject);

		if(IsKernelAddressValid(ObjectHeader))
		{
			RtlInitUnicodeString(
								 &ObjectName,
								 L"\\GLOBAL??");

			NtStatus = ObReferenceObjectByName(
											   &ObjectName,              // ObjectName 
											   OBJ_CASE_INSENSITIVE,     // Attributes
											   NULL,                     // AccessState
											   0,                        // DesiredAccess
											   ObjectHeader->ObjectType, // ObjectType
											   KernelMode,               // AccessMode
											   NULL,					 // ParseContext
											   &Object);                 // Object

			if(NT_SUCCESS(NtStatus))
				ObDereferenceObject(Object);

			KdPrint((
					 "[i] ObpDosDevicesDirectoryObject - %.8X\n",
					 Object));
		}
	}

	return Object;
}


PVOID ObGetDeviceDirectory()
{
	NTSTATUS NtStatus = STATUS_UNSUCCESSFUL;

	PVOID ObpRootDirectoryObject = NULL;
	PVOID Object = NULL;

	OBJECT_HEADER *ObjectHeader = NULL;
	UNICODE_STRING ObjectName;


	ObpRootDirectoryObject = ObGetObpRootDirectoryObject();

	if(IsKernelAddressValid(ObpRootDirectoryObject))
	{
		ObjectHeader = OBJECT_TO_OBJECT_HEADER(ObpRootDirectoryObject);

		if(IsKernelAddressValid(ObjectHeader))
		{
			RtlInitUnicodeString(
								 &ObjectName,
								 L"\\Device");

			NtStatus = ObReferenceObjectByName(
											   &ObjectName,              // ObjectName 
											   OBJ_CASE_INSENSITIVE,     // Attributes
											   NULL,                     // AccessState
											   0,                        // DesiredAccess
											   ObjectHeader->ObjectType, // ObjectType
											   KernelMode,               // AccessMode
											   NULL,					 // ParseContext
											   &Object);                 // Object

			if(NT_SUCCESS(NtStatus))
				ObDereferenceObject(Object);

			KdPrint((
					 "[i] ObpDeviceDirectoryObject - %.8X\n",
					 Object));
		}
	}

	return Object;
}


NTSTATUS ObWalkDeviceDirectory()
{
	NTSTATUS NtStatus = STATUS_OBJECT_NAME_NOT_FOUND;

	ULONG Bucket;
	PVOID ObjectName = NULL;

	OBJECT_DIRECTORY *DirectoryObject = NULL;
	OBJECT_DIRECTORY_ENTRY *DirectoryEntry = NULL;
    OBJECT_DIRECTORY_ENTRY *TopDirectoryEntry = NULL;
    OBJECT_DIRECTORY_ENTRY *PreviousDirectoryEntry = NULL;

	OBJECT_HEADER *ObjectHeader = NULL;
	OBJECT_HEADER_NAME_INFO *ObjectNameInfo = NULL;


	DirectoryObject = ObGetDeviceDirectory();

	if(IsKernelAddressValid(DirectoryObject))
	{
		for(Bucket=0; Bucket<NUMBER_HASH_BUCKETS; Bucket++)
        {
            DirectoryEntry = DirectoryObject->HashBuckets[Bucket];

            if(IsKernelAddressValid(DirectoryEntry))
            {
                TopDirectoryEntry = DirectoryEntry;
                PreviousDirectoryEntry = DirectoryEntry;

                do
                {
                    ObjectHeader = OBJECT_TO_OBJECT_HEADER(TopDirectoryEntry->Object);

                    ObjectNameInfo = OBJECT_HEADER_TO_NAME_INFO(ObjectHeader);

					if(IsKernelAddressValid(ObjectNameInfo))
                    {
						if(IsKernelAddressValid(ObjectNameInfo->Name.Buffer) &&
						   ObjectNameInfo->Name.MaximumLength > 0)
						{
							ObjectName = ExAllocatePool(
														PagedPool,
														ObjectNameInfo->Name.MaximumLength +
														sizeof(WCHAR));

							if(ObjectName)
							{
								RtlZeroMemory(
											  ObjectName,
											  ObjectNameInfo->Name.MaximumLength +
											  sizeof(WCHAR));

								RtlMoveMemory(
											  ObjectName,
											  ObjectNameInfo->Name.Buffer,
											  ObjectNameInfo->Name.MaximumLength);

								KdPrint(("[i] DEVICE OBJECT - %.8X - %ws\n",
										TopDirectoryEntry->Object,
										ObjectName));

								ExFreePool(ObjectName);
							}
						}
					}

                    TopDirectoryEntry = TopDirectoryEntry->ChainLink;
                
                }
                while(IsKernelAddressValid(TopDirectoryEntry));
            }
        }
    }

	return NtStatus;
}
 #9134  by Tigzy
 Fri Oct 14, 2011 12:22 pm
Hello

with
Code: Select all
status = ObOpenObjectByName( &attributes, IoDeviceObjectType, KernelMode, NULL, 0x80000000, NULL, &handle );
I got an STATUS_OBJECT_TYPE_MISMATCH error

----

@Alex: I haven't got the IsKernelAddressValid function. It seems not to being an NT function

EDIT: removed the "star"
Last edited by Tigzy on Fri Oct 14, 2011 12:31 pm, edited 1 time in total.
 #9137  by Tigzy
 Fri Oct 14, 2011 12:35 pm
Maybe if I explain my aim you'll find a more evident way to do this...

I want to check IRP hooks.
My aim is to travel the DRIVER_OBJECT stack, and for each walk throught the DEVICE_OBJECT stack, checking if the IRPs are in the adress range of the driver.
simple as that.

I'm also checking for each DEVICE_OBJECt if the associated DRIVER_OBJECT is the same from where I'm coming.
 #9138  by r2nwcnydc
 Fri Oct 14, 2011 12:40 pm
Tigzy wrote: The 2 are defined the same way, but only IoDriverObjectType works...
Code: Select all
extern POBJECT_TYPE* IoDriverObjectType;
extern POBJECT_TYPE* IoDeviceObjectType;

I doubt it would make a difference but the prototypes should be:
Code: Select all
extern POBJECT_TYPE IoDriverObjectType;
extern POBJECT_TYPE IoDeviceObjectType;
 #9151  by r2nwcnydc
 Fri Oct 14, 2011 2:46 pm
I've been testing and I could not get ObOpenObjectByName to work for devices either. It seems there is an issue with a context pointer in IopParseDevice. If you are walking the device list for a driver, why not use ObOpenObjectByPointer instead? That one seems to work fine for devices.

Why do you want to get a handle to the device? Is it just so that you can reference the device object? If that is the case why not just use ObReferenceObjectByPointer?