pci enumeration!!

This commit is contained in:
lhodges1 2024-02-14 05:08:38 +11:00
parent bef7c8a3b5
commit e6bbb850f5
8 changed files with 316 additions and 0 deletions

View file

@ -236,6 +236,7 @@ typedef struct _ACTIVE_SESSION
#define INVALID_DRIVER_LIST_HEAD_POOL 'rwar'
#define INVALID_DRIVER_LIST_ENTRY_POOL 'gaah'
#define POOL_TAG_APC 'apcc'
#define POOL_TAG_HW 'hwhw'
#define POOL_TAG_DPC 'apcc'
#define SYSTEM_MODULES_POOL 'halb'
#define THREAD_DATA_POOL 'doof'

View file

@ -13,6 +13,7 @@
#include "apc.h"
#include "crypt.h"
#include "session.h"
#include "hw.h"
STATIC
VOID

View file

@ -254,6 +254,7 @@
<ClCompile Include="io.c" />
<ClCompile Include="list.c" />
<ClCompile Include="modules.c" />
<ClCompile Include="hw.c" />
<ClCompile Include="pool.c" />
<ClCompile Include="queue.c" />
<ClCompile Include="session.c" />
@ -266,6 +267,7 @@
<ClInclude Include="crypt.h" />
<ClInclude Include="driver.h" />
<ClInclude Include="hv.h" />
<ClInclude Include="hw.h" />
<ClInclude Include="ia32.h" />
<ClInclude Include="imports.h" />
<ClInclude Include="integrity.h" />

View file

@ -66,6 +66,9 @@
<ClCompile Include="session.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="hw.c">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="driver.h">
@ -119,6 +122,9 @@
<ClInclude Include="session.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="hw.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<MASM Include="arch.asm">

225
driver/hw.c Normal file
View file

@ -0,0 +1,225 @@
#include "hw.h"
#include "modules.h"
#define PCI_VENDOR_ID_OFFSET 0x00
/*
* Every PCI device has a set of registers commonly referred to as the PCI configuration space. In
* modern PCI-e devices an extended configuration space was implemented. These configuration spaces
* are mapped into main memory and this allows us to read/write to the registers.
*
* The configuration space consists of a standard header, containing information such as the
* DeviceID, VendorID, Status and so on. Below is the header schema including offsets.
*
* | Offset 0x00: Header Type
* | Offset 0x01: Multi-Function Device Indicator
* | Offset 0x02: Device ID (Low Byte)
* | Offset 0x03: Device ID (High Byte)
* | Offset 0x04: Status Register (16 bits)
* | Offset 0x06: Command Register (16 bits)
* | Offset 0x08: Class Code
* | Offset 0x09: Subclass Code
* | Offset 0x0A: Prog IF (Programming Interface)
* | Offset 0x0B: Revision ID
* | Offset 0x0C: BIST (Built-in Self-Test)
* | Offset 0x0D: Header Type (Secondary)
* | Offset 0x0E: Latency Timer
* | Offset 0x0F: Cache Line Size
* | Offset 0x10: Base Address Register 0 (BAR0) - 32 bits
* | Offset 0x14: Base Address Register 1 (BAR1) - 32 bits
* | Offset 0x18: Base Address Register 2 (BAR2) - 32 bits
* | Offset 0x1C: Base Address Register 3 (BAR3) - 32 bits
* | Offset 0x20: Base Address Register 4 (BAR4) - 32 bits
* | Offset 0x24: Base Address Register 5 (BAR5) - 32 bits
* | Offset 0x28: Cardbus CIS Pointer (for Cardbus bridges)
* | Offset 0x2C: Subsystem Vendor ID
* | Offset 0x2E: Subsystem ID
* | Offset 0x30: Expansion ROM Base Address
* | Offset 0x34: Reserved
* | Offset 0x38: Reserved
* | Offset 0x3C: Max_Lat (Maximum Latency)
* | Offset 0x3D: Min_Gnt (Minimum Grant)
* | Offset 0x3E: Interrupt Pin
* | Offset 0x3F: Interrupt Line
*
* We can use this to then query important information from PCI devices within the device tree. To
* keep up with modern windows kernel programming, we can make use of the IRP_MN_READ_CONFIG code,
* which as the name suggests, reads from a PCI devices configuration space.
*/
STATIC
NTSTATUS
QueryPciDeviceConfigurationSpace(_In_ PDEVICE_OBJECT DeviceObject,
_In_ UINT32 Offset,
_Out_ PVOID Buffer,
_In_ UINT32 BufferLength)
{
NTSTATUS status = STATUS_UNSUCCESSFUL;
KEVENT event = {0};
IO_STATUS_BLOCK io = {0};
PIRP irp = NULL;
PIO_STACK_LOCATION io_stack_location = NULL;
if (BufferLength == 0)
return STATUS_BUFFER_TOO_SMALL;
KeInitializeEvent(&event, NotificationEvent, FALSE);
irp = IoBuildSynchronousFsdRequest(IRP_MJ_PNP, DeviceObject, NULL, 0, NULL, &event, &io);
if (!irp)
{
DEBUG_ERROR("IoBuildSynchronousFsdRequest failed with no status.");
return STATUS_INSUFFICIENT_RESOURCES;
}
io_stack_location = IoGetNextIrpStackLocation(irp);
io_stack_location->MinorFunction = IRP_MN_READ_CONFIG;
io_stack_location->Parameters.ReadWriteConfig.WhichSpace = PCI_WHICHSPACE_CONFIG;
io_stack_location->Parameters.ReadWriteConfig.Offset = Offset;
io_stack_location->Parameters.ReadWriteConfig.Buffer = Buffer;
io_stack_location->Parameters.ReadWriteConfig.Length = BufferLength;
status = IoCallDriver(DeviceObject, irp);
if (status = STATUS_PENDING)
{
KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL);
status = io.Status;
}
if (!NT_SUCCESS(status))
{
DEBUG_ERROR("Failed to read configuration space with status %x", status);
return status;
}
return status;
}
/*
* NOTE: Caller is responsible for freeing the array.
*/
STATIC
NTSTATUS
EnumerateDriverObjectDeviceObjects(_In_ PDRIVER_OBJECT DriverObject,
_Out_ PDEVICE_OBJECT** DeviceObjectArray,
_Out_ PUINT32 ArrayEntries)
{
NTSTATUS status = STATUS_UNSUCCESSFUL;
UINT32 object_count = 0;
PDEVICE_OBJECT* buffer = NULL;
UINT32 buffer_size = 0;
*DeviceObjectArray = NULL;
status = IoEnumerateDeviceObjectList(DriverObject, NULL, 0, &object_count);
if (status != STATUS_BUFFER_TOO_SMALL)
{
DEBUG_ERROR("IoEnumerateDeviceObjectList failed with status %x", status);
return status;
}
buffer_size = object_count * sizeof(UINT64);
buffer = ExAllocatePool2(POOL_FLAG_NON_PAGED, buffer_size, POOL_TAG_HW);
if (!buffer)
return STATUS_INSUFFICIENT_RESOURCES;
status = IoEnumerateDeviceObjectList(DriverObject, buffer, buffer_size, &object_count);
if (!NT_SUCCESS(status))
{
DEBUG_ERROR("IoEnumerateDeviceObjectList failed with status %x", status);
ExFreePoolWithTag(buffer, POOL_TAG_HW);
return status;
}
DEBUG_VERBOSE("EnumerateDriverObjectDeviceObjects: Object Count: %lx", object_count);
*DeviceObjectArray = buffer;
*ArrayEntries = object_count;
return status;
}
/*
* WHile this isnt a perfect check to determine whether a DEVICE_OBJECT is indeed a PDO or FDO, this
* is Peters preferred method... hence it is now my preferred method... :smiling_imp:
*/
STATIC
BOOLEAN
IsDeviceObjectValidPdo(_In_ PDEVICE_OBJECT DeviceObject)
{
return DeviceObject->Flags & DO_BUS_ENUMERATED_DEVICE ? TRUE : FALSE;
}
/*
* Windows splits DEVICE_OBJECTS up into 2 categories:
*
* Physical Device Object (PDO)
* Function Device Object (FDO)
*
* A PDO represents each device that is connected to a physical bus. Each PDO has an associated
* DEVICE_NODE. An FDO represents the functionality of the device. Its how the system interacts with
* the device objects.
*
* More information can be found here:
* https://learn.microsoft.com/en-gb/windows-hardware/drivers/gettingstarted/device-nodes-and-device-stacks
*/
NTSTATUS
EnumeratePciDeviceObjects()
{
NTSTATUS status = STATUS_UNSUCCESSFUL;
UNICODE_STRING pci = RTL_CONSTANT_STRING(L"\\Driver\\pci");
PDRIVER_OBJECT pci_driver_object = NULL;
PDEVICE_OBJECT* pci_device_objects = NULL;
PDEVICE_OBJECT current_device = NULL;
UINT32 pci_device_objects_count = 0;
USHORT vendor_id = 0;
status = GetDriverObjectByDriverName(&pci, &pci_driver_object);
if (!NT_SUCCESS(status))
{
DEBUG_ERROR("GetDriverObjectByDriverName failed with status %x", status);
return status;
}
status = EnumerateDriverObjectDeviceObjects(
pci_driver_object, &pci_device_objects, &pci_device_objects_count);
if (!NT_SUCCESS(status))
{
DEBUG_ERROR("EnumerateDriverObjectDeviceObjects failed with status %x", status);
return status;
}
for (UINT32 index = 0; index < pci_device_objects_count; index++)
{
current_device = pci_device_objects[index];
/* make sure we have a valid PDO */
if (!IsDeviceObjectValidPdo(current_device))
continue;
status = QueryPciDeviceConfigurationSpace(
current_device, PCI_VENDOR_ID_OFFSET, &vendor_id, sizeof(USHORT));
if (!NT_SUCCESS(status))
{
DEBUG_ERROR("QueryPciDeviceConfigurationSpace failed with status %x",
status);
continue;
}
DEBUG_VERBOSE("Device: %llx, VendorID: %lx", current_device, vendor_id);
}
end:
if (pci_device_objects)
ExFreePoolWithTag(pci_device_objects, POOL_TAG_HW);
return status;
}

9
driver/hw.h Normal file
View file

@ -0,0 +1,9 @@
#ifndef HW_H
#define HW_H
#include "common.h"
NTSTATUS
EnumeratePciDeviceObjects();
#endif

View file

@ -466,6 +466,7 @@ GetSystemModuleInformation(_Out_ PSYSTEM_MODULES ModuleInformation)
return status;
}
/* TODO: this function needs to be rewritten. Infact, this entire file needs to be rewritten. */
STATIC
NTSTATUS
ValidateDriverObjects(_In_ PSYSTEM_MODULES SystemModules,
@ -1843,4 +1844,72 @@ end:
ImpExFreePoolWithTag(modules.address, SYSTEM_MODULES_POOL);
return status;
}
NTSTATUS
GetDriverObjectByDriverName(_In_ PUNICODE_STRING DriverName, _Out_ PDRIVER_OBJECT* DriverObject)
{
HANDLE handle = NULL;
OBJECT_ATTRIBUTES attributes = {0};
PVOID directory = {0};
UNICODE_STRING directory_name = {0};
NTSTATUS status = STATUS_UNSUCCESSFUL;
POBJECT_DIRECTORY directory_object = NULL;
*DriverObject = NULL;
ImpRtlInitUnicodeString(&directory_name, L"\\Driver");
InitializeObjectAttributes(&attributes, &directory_name, OBJ_CASE_INSENSITIVE, NULL, NULL);
status = ImpZwOpenDirectoryObject(&handle, DIRECTORY_ALL_ACCESS, &attributes);
if (!NT_SUCCESS(status))
{
DEBUG_ERROR("ZwOpenDirectoryObject failed with status %x", status);
return status;
}
status = ImpObReferenceObjectByHandle(
handle, DIRECTORY_ALL_ACCESS, NULL, KernelMode, &directory, NULL);
if (!NT_SUCCESS(status))
{
DEBUG_ERROR("ObReferenceObjectByHandle failed with status %x", status);
ImpZwClose(handle);
return status;
}
directory_object = (POBJECT_DIRECTORY)directory;
ImpExAcquirePushLockExclusiveEx(&directory_object->Lock, NULL);
for (INT index = 0; index < NUMBER_HASH_BUCKETS; index++)
{
POBJECT_DIRECTORY_ENTRY entry = directory_object->HashBuckets[index];
if (!entry)
continue;
POBJECT_DIRECTORY_ENTRY sub_entry = entry;
while (sub_entry)
{
PDRIVER_OBJECT current_driver = sub_entry->Object;
if (!RtlCompareUnicodeString(DriverName, &current_driver->DriverName, FALSE))
{
*DriverObject = current_driver;
goto end;
}
sub_entry = sub_entry->ChainLink;
}
}
end:
ImpExReleasePushLockExclusiveEx(&directory_object->Lock, 0);
ImpObDereferenceObject(directory);
ImpZwClose(handle);
return STATUS_SUCCESS;
}

View file

@ -77,4 +77,7 @@ ValidateHalDispatchTables();
PVOID
FindDriverBaseNoApi(_In_ PDRIVER_OBJECT DriverObject, _In_ PWCH Name);
NTSTATUS
GetDriverObjectByDriverName(_In_ PUNICODE_STRING DriverName, _Out_ PDRIVER_OBJECT* DriverObject);
#endif