From 0a26c7c5d2fa75fe0cdd58db9516e2280e7d2237 Mon Sep 17 00:00:00 2001 From: Victor Perevertkin Date: Wed, 10 Mar 2021 16:43:59 +0300 Subject: [PATCH] [SDK:DDK] Implement the Auxiliary Kernel-Mode Library And uncomment the code in KMDF which uses it --- sdk/include/ddk/aux_klib.h | 94 +++++++ sdk/lib/drivers/CMakeLists.txt | 1 + sdk/lib/drivers/aux_klib/CMakeLists.txt | 4 + sdk/lib/drivers/aux_klib/aux_klib.c | 228 ++++++++++++++++ sdk/lib/drivers/wdf/CMakeLists.txt | 2 +- .../wdf/kmdf/src/core/fxbugcheckcallback.cpp | 252 +++++++++--------- 6 files changed, 452 insertions(+), 129 deletions(-) create mode 100644 sdk/include/ddk/aux_klib.h create mode 100644 sdk/lib/drivers/aux_klib/CMakeLists.txt create mode 100644 sdk/lib/drivers/aux_klib/aux_klib.c diff --git a/sdk/include/ddk/aux_klib.h b/sdk/include/ddk/aux_klib.h new file mode 100644 index 00000000000..edbcf06ef6b --- /dev/null +++ b/sdk/include/ddk/aux_klib.h @@ -0,0 +1,94 @@ +/* + * aux_klib.h + * + * Auxiliary Kernel-Mode Library + * + * Contributors: + * Victor Perevertkin + * + * THIS SOFTWARE IS NOT COPYRIGHTED + * + * This source code is offered for use in the public domain. You may + * use, modify or distribute it freely. + * + * This code is distributed in the hope that it will be useful but + * WITHOUT ANY WARRANTY. ALL WARRANTIES, EXPRESS OR IMPLIED ARE HEREBY + * DISCLAIMED. This includes but is not limited to warranties of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + */ + +#pragma once + +#ifndef PIMAGE_EXPORT_DIRECTORY +#include +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +#define AUX_KLIB_MODULE_PATH_LEN 0x100 + +typedef struct _AUX_MODULE_BASIC_INFO { + PVOID ImageBase; +} AUX_MODULE_BASIC_INFO, *PAUX_MODULE_BASIC_INFO; + +typedef struct _AUX_MODULE_EXTENDED_INFO { + AUX_MODULE_BASIC_INFO BasicInfo; + ULONG ImageSize; + USHORT FileNameOffset; + CHAR FullPathName[AUX_KLIB_MODULE_PATH_LEN]; +} AUX_MODULE_EXTENDED_INFO, *PAUX_MODULE_EXTENDED_INFO; + +typedef struct _KBUGCHECK_DATA { + ULONG BugCheckDataSize; + ULONG BugCheckCode; + ULONG_PTR Parameter1; + ULONG_PTR Parameter2; + ULONG_PTR Parameter3; + ULONG_PTR Parameter4; +} KBUGCHECK_DATA, *PKBUGCHECK_DATA; + +NTSTATUS +NTAPI +AuxKlibInitialize(VOID); + +_IRQL_requires_max_(PASSIVE_LEVEL) +NTSTATUS +NTAPI +AuxKlibQueryModuleInformation( + _Inout_ PULONG InformationLength, + _In_ ULONG SizePerModule, + _Out_writes_bytes_opt_(*InformationLength) PAUX_MODULE_EXTENDED_INFO ModuleInfo); + +NTSTATUS +AuxKlibGetBugCheckData( + _Inout_ PKBUGCHECK_DATA BugCheckData); + +PIMAGE_EXPORT_DIRECTORY +AuxKlibGetImageExportDirectory( + _In_ PVOID ImageBase); + +_IRQL_requires_max_(PASSIVE_LEVEL) +NTSTATUS +NTAPI +AuxKlibEnumerateSystemFirmwareTables ( + _In_ ULONG FirmwareTableProviderSignature, + _Out_writes_bytes_to_opt_(BufferLength, *ReturnLength) PVOID FirmwareTableBuffer, + _In_ ULONG BufferLength, + _Out_opt_ PULONG ReturnLength); + +_IRQL_requires_max_(PASSIVE_LEVEL) +NTSTATUS +NTAPI +AuxKlibGetSystemFirmwareTable ( + _In_ ULONG FirmwareTableProviderSignature, + _In_ ULONG FirmwareTableID, + _Out_writes_bytes_to_opt_(BufferLength, *ReturnLength) PVOID FirmwareTableBuffer, + _In_ ULONG BufferLength, + _Out_opt_ PULONG ReturnLength); + +#ifdef __cplusplus +} +#endif diff --git a/sdk/lib/drivers/CMakeLists.txt b/sdk/lib/drivers/CMakeLists.txt index e20501a0cf0..cbbbf2efb58 100644 --- a/sdk/lib/drivers/CMakeLists.txt +++ b/sdk/lib/drivers/CMakeLists.txt @@ -1,5 +1,6 @@ add_subdirectory(arbiter) +add_subdirectory(aux_klib) add_subdirectory(chew) add_subdirectory(copysup) add_subdirectory(csq) diff --git a/sdk/lib/drivers/aux_klib/CMakeLists.txt b/sdk/lib/drivers/aux_klib/CMakeLists.txt new file mode 100644 index 00000000000..222245ec42b --- /dev/null +++ b/sdk/lib/drivers/aux_klib/CMakeLists.txt @@ -0,0 +1,4 @@ + +add_library(aux_klib aux_klib.c) +target_link_libraries(aux_klib ${PSEH_LIB}) +add_importlibs(aux_klib ntoskrnl) diff --git a/sdk/lib/drivers/aux_klib/aux_klib.c b/sdk/lib/drivers/aux_klib/aux_klib.c new file mode 100644 index 00000000000..c0b74a37b50 --- /dev/null +++ b/sdk/lib/drivers/aux_klib/aux_klib.c @@ -0,0 +1,228 @@ +/* + * PROJECT: ReactOS SDK: Auxiliary Kernel-Mode Library + * LICENSE: BSD-2-Clause-Views (https://spdx.org/licenses/BSD-2-Clause-Views) + * PURPOSE: Main source file + * COPYRIGHT: Copyright 2019-2020 Max Korostil + * Copyright 2021 Victor Perevertkin + */ + +#include +#include +#include +#include +#include + +#define TAG_AUXK 'AuxK' + +typedef NTSTATUS (NTAPI *PFN_RTLQUERYMODULEINFORMATION)(PULONG, ULONG, PVOID); + +PFN_RTLQUERYMODULEINFORMATION pfnRtlQueryModuleInformation; +LONG gKlibInitialized = 0; + + +CODE_SEG("PAGE") +NTSTATUS +NTAPI +AuxKlibInitialize(VOID) +{ + RTL_OSVERSIONINFOW osVersion; + UNICODE_STRING strRtlQueryModuleInformation = RTL_CONSTANT_STRING(L"RtlQueryModuleInformation"); + + PAGED_CODE(); + + if (!gKlibInitialized) + { + RtlGetVersion(&osVersion); + if (osVersion.dwMajorVersion >= 5) + { + pfnRtlQueryModuleInformation = MmGetSystemRoutineAddress(&strRtlQueryModuleInformation); + InterlockedExchange(&gKlibInitialized, 1); + } + else + { + return STATUS_NOT_SUPPORTED; + } + } + + return STATUS_SUCCESS; +} + +CODE_SEG("PAGE") +NTSTATUS +NTAPI +AuxKlibQueryModuleInformation( + _In_ PULONG InformationLength, + _In_ ULONG SizePerModule, + _Inout_ PAUX_MODULE_EXTENDED_INFO ModuleInfo) +{ + NTSTATUS status; + + PAGED_CODE(); + + if (gKlibInitialized != 1) + { + return STATUS_UNSUCCESSFUL; + } + + // if we have the function exported from the kernel, use it + if (pfnRtlQueryModuleInformation != NULL) + { + return pfnRtlQueryModuleInformation(InformationLength, SizePerModule, ModuleInfo); + } + + if (SizePerModule != sizeof(AUX_MODULE_BASIC_INFO) && + SizePerModule != sizeof(AUX_MODULE_EXTENDED_INFO)) + { + return STATUS_INVALID_PARAMETER_2; + } + + if ((ULONG_PTR)ModuleInfo & (TYPE_ALIGNMENT(AUX_MODULE_EXTENDED_INFO) - 1)) + { + return STATUS_INVALID_PARAMETER_3; + } + + // first call the function with a place for only 1 module + RTL_PROCESS_MODULES processModulesMinimal; + PRTL_PROCESS_MODULES processModules = &processModulesMinimal; + ULONG sysInfoLength = sizeof(processModulesMinimal); + ULONG resultLength; + + // loop until we have a large-enough buffer for all modules + do + { + status = ZwQuerySystemInformation(SystemModuleInformation, + processModules, + sysInfoLength, + &resultLength); + + if (status == STATUS_INFO_LENGTH_MISMATCH) + { + // free the old buffer if it's not the first one + if (processModules != &processModulesMinimal) + { + ExFreePoolWithTag(processModules, TAG_AUXK); + } + + _SEH2_TRY + { + // allocate the new one + processModules = ExAllocatePoolWithQuotaTag(PagedPool, resultLength, TAG_AUXK); + } + _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) + { + _SEH2_YIELD(return _SEH2_GetExceptionCode()); + } + _SEH2_END; + + if (!processModules) + { + return STATUS_INSUFFICIENT_RESOURCES; + } + sysInfoLength = resultLength; + } + + } while (status == STATUS_INFO_LENGTH_MISMATCH); + + if (!NT_SUCCESS(status)) + { + goto Cleanup; + } + + ULONG modulesSize; + status = RtlULongMult(SizePerModule, processModules->NumberOfModules, &modulesSize); + if (!NT_SUCCESS(status)) + { + goto Cleanup; + } + + if (ModuleInfo == NULL) + { + ASSERT(status == STATUS_SUCCESS); + *InformationLength = modulesSize; + goto Cleanup; + } + + if (*InformationLength < modulesSize) + { + status = STATUS_BUFFER_TOO_SMALL; + *InformationLength = modulesSize; + goto Cleanup; + } + + // copy the information to the input array + for (UINT32 i = 0; i < processModules->NumberOfModules; i++) + { + ModuleInfo[i].BasicInfo.ImageBase = processModules->Modules[i].ImageBase; + + if (SizePerModule == sizeof(AUX_MODULE_EXTENDED_INFO)) + { + ModuleInfo[i].ImageSize = processModules->Modules[i].ImageSize; + ModuleInfo[i].FileNameOffset = processModules->Modules[i].OffsetToFileName; + RtlCopyMemory(&ModuleInfo[i].FullPathName, + processModules->Modules[i].FullPathName, + sizeof(processModules->Modules[i].FullPathName)); + } + } + +Cleanup: + // don't accidentally free the stack buffer + if (processModules != NULL && processModules != &processModulesMinimal) + { + ExFreePoolWithTag(processModules, TAG_AUXK); + } + + return status; +} + +NTSTATUS +AuxKlibGetBugCheckData( + _Inout_ PKBUGCHECK_DATA BugCheckData) +{ + if (BugCheckData->BugCheckDataSize != sizeof(*BugCheckData)) + { + return STATUS_INFO_LENGTH_MISMATCH; + } + + BugCheckData->BugCheckCode = KiBugCheckData[0]; + BugCheckData->Parameter1 = KiBugCheckData[1]; + BugCheckData->Parameter2 = KiBugCheckData[2]; + BugCheckData->Parameter3 = KiBugCheckData[3]; + BugCheckData->Parameter4 = KiBugCheckData[4]; + + return STATUS_SUCCESS; +} + +PIMAGE_EXPORT_DIRECTORY +AuxKlibGetImageExportDirectory( + _In_ PVOID ImageBase) +{ + ULONG size; + return RtlImageDirectoryEntryToData(ImageBase, TRUE, IMAGE_DIRECTORY_ENTRY_EXPORT, &size); +} + +_IRQL_requires_max_(PASSIVE_LEVEL) +CODE_SEG("PAGE") +NTSTATUS +NTAPI +AuxKlibEnumerateSystemFirmwareTables ( + _In_ ULONG FirmwareTableProviderSignature, + _Out_writes_bytes_to_opt_(BufferLength, *ReturnLength) PVOID FirmwareTableBuffer, + _In_ ULONG BufferLength, + _Out_opt_ PULONG ReturnLength) +{ + return STATUS_NOT_IMPLEMENTED; +} + +_IRQL_requires_max_(PASSIVE_LEVEL) +CODE_SEG("PAGE") +NTSTATUS +NTAPI +AuxKlibGetSystemFirmwareTable ( + _In_ ULONG FirmwareTableProviderSignature, + _In_ ULONG FirmwareTableID, + _Out_writes_bytes_to_opt_(BufferLength, *ReturnLength) PVOID FirmwareTableBuffer, + _In_ ULONG BufferLength, + _Out_opt_ PULONG ReturnLength) +{ + return STATUS_NOT_IMPLEMENTED; +} diff --git a/sdk/lib/drivers/wdf/CMakeLists.txt b/sdk/lib/drivers/wdf/CMakeLists.txt index cfb47188138..1210764d036 100644 --- a/sdk/lib/drivers/wdf/CMakeLists.txt +++ b/sdk/lib/drivers/wdf/CMakeLists.txt @@ -208,7 +208,7 @@ target_include_directories(wdf01000 shared/irphandlers/pnp/km # pnpprivkm.hpp ) -target_link_libraries(wdf01000 ntoskrnl_vista ${PSEH_LIB}) +target_link_libraries(wdf01000 aux_klib ntoskrnl_vista ${PSEH_LIB}) if(GCC) target_compile_options(wdf01000 diff --git a/sdk/lib/drivers/wdf/kmdf/src/core/fxbugcheckcallback.cpp b/sdk/lib/drivers/wdf/kmdf/src/core/fxbugcheckcallback.cpp index d164d682a05..b8fabb12203 100644 --- a/sdk/lib/drivers/wdf/kmdf/src/core/fxbugcheckcallback.cpp +++ b/sdk/lib/drivers/wdf/kmdf/src/core/fxbugcheckcallback.cpp @@ -25,7 +25,7 @@ Revision History: #include "fxldr.h" #include "fxbugcheck.h" -// #include +#include // // Disable warnings of features used by the standard headers @@ -125,104 +125,102 @@ FxpGetImageBase( __out PULONG ImageSize ) { -// NTSTATUS status = STATUS_UNSUCCESSFUL; -// ULONG modulesSize = 0; -// AUX_MODULE_EXTENDED_INFO* modules = NULL; -// AUX_MODULE_EXTENDED_INFO* module; -// PVOID addressInImage = NULL; -// ULONG numberOfModules; -// ULONG i; + NTSTATUS status = STATUS_UNSUCCESSFUL; + ULONG modulesSize = 0; + AUX_MODULE_EXTENDED_INFO* modules = NULL; + AUX_MODULE_EXTENDED_INFO* module; + PVOID addressInImage = NULL; + ULONG numberOfModules; + ULONG i; -// // -// // Basic validation. -// // -// if (NULL == DriverObject || NULL == ImageBase || NULL == ImageSize) { -// status = STATUS_INVALID_PARAMETER; -// goto exit; -// } + // + // Basic validation. + // + if (NULL == DriverObject || NULL == ImageBase || NULL == ImageSize) { + status = STATUS_INVALID_PARAMETER; + goto exit; + } -// // -// // Get the address of a well known entry in the Image. -// // -// addressInImage = (PVOID) DriverObject->DriverStart; -// ASSERT(addressInImage != NULL); + // + // Get the address of a well known entry in the Image. + // + addressInImage = (PVOID) DriverObject->DriverStart; + ASSERT(addressInImage != NULL); -// // -// // Initialize the AUX Kernel Library. -// // -// status = AuxKlibInitialize(); -// if (!NT_SUCCESS(status)) { -// goto exit; -// } + // + // Initialize the AUX Kernel Library. + // + status = AuxKlibInitialize(); + if (!NT_SUCCESS(status)) { + goto exit; + } -// // -// // Get size of area needed for loaded modules. -// // -// status = AuxKlibQueryModuleInformation(&modulesSize, -// sizeof(AUX_MODULE_EXTENDED_INFO), -// NULL); + // + // Get size of area needed for loaded modules. + // + status = AuxKlibQueryModuleInformation(&modulesSize, + sizeof(AUX_MODULE_EXTENDED_INFO), + NULL); -// if (!NT_SUCCESS(status) || (0 == modulesSize)) { -// goto exit; -// } + if (!NT_SUCCESS(status) || (0 == modulesSize)) { + goto exit; + } -// numberOfModules = modulesSize / sizeof(AUX_MODULE_EXTENDED_INFO); + numberOfModules = modulesSize / sizeof(AUX_MODULE_EXTENDED_INFO); -// // -// // Allocate returned-sized memory for the modules area. -// // -// modules = (AUX_MODULE_EXTENDED_INFO*) ExAllocatePoolWithTag(PagedPool, -// modulesSize, -// '30LW'); -// if (NULL == modules) { -// status = STATUS_INSUFFICIENT_RESOURCES; -// goto exit; -// } + // + // Allocate returned-sized memory for the modules area. + // + modules = (AUX_MODULE_EXTENDED_INFO*) ExAllocatePoolWithTag(PagedPool, + modulesSize, + '30LW'); + if (NULL == modules) { + status = STATUS_INSUFFICIENT_RESOURCES; + goto exit; + } -// // -// // Request the modules array be filled with module information. -// // -// status = AuxKlibQueryModuleInformation(&modulesSize, -// sizeof(AUX_MODULE_EXTENDED_INFO), -// modules); + // + // Request the modules array be filled with module information. + // + status = AuxKlibQueryModuleInformation(&modulesSize, + sizeof(AUX_MODULE_EXTENDED_INFO), + modules); -// if (!NT_SUCCESS(status)) { -// goto exit; -// } + if (!NT_SUCCESS(status)) { + goto exit; + } -// // -// // Traverse list, searching for the well known address in Image for which the -// // module's Image Base Address is in its range. -// // -// module = modules; + // + // Traverse list, searching for the well known address in Image for which the + // module's Image Base Address is in its range. + // + module = modules; -// for (i=0; i < numberOfModules; i++) { + for (i=0; i < numberOfModules; i++) { -// if (addressInImage >= module->BasicInfo.ImageBase && -// addressInImage < WDF_PTR_ADD_OFFSET(module->BasicInfo.ImageBase, -// module->ImageSize)) { + if (addressInImage >= module->BasicInfo.ImageBase && + addressInImage < WDF_PTR_ADD_OFFSET(module->BasicInfo.ImageBase, + module->ImageSize)) { -// *ImageBase = module->BasicInfo.ImageBase; -// *ImageSize = module->ImageSize; + *ImageBase = module->BasicInfo.ImageBase; + *ImageSize = module->ImageSize; -// status = STATUS_SUCCESS; -// goto exit; -// } -// module++; -// } + status = STATUS_SUCCESS; + goto exit; + } + module++; + } -// status = STATUS_NOT_FOUND; + status = STATUS_NOT_FOUND; -// exit: +exit: -// if (modules != NULL) { -// ExFreePool(modules); -// modules = NULL; -// } + if (modules != NULL) { + ExFreePool(modules); + modules = NULL; + } -// return status; - ROSWDFNOTIMPLEMENTED; - return STATUS_NOT_IMPLEMENTED; + return status; } _Must_inspect_result_ @@ -248,61 +246,59 @@ Return Value: --*/ { - // PVOID codeAddr = NULL; - // BOOLEAN found = FALSE; - // KBUGCHECK_DATA bugCheckData = {0}; + PVOID codeAddr = NULL; + BOOLEAN found = FALSE; + KBUGCHECK_DATA bugCheckData = {0}; - // if (FxDriverGlobals->FxForceLogsInMiniDump) { - // return TRUE; - // } + if (FxDriverGlobals->FxForceLogsInMiniDump) { + return TRUE; + } - // // - // // Retrieve the bugcheck parameters. - // // - // bugCheckData.BugCheckDataSize = sizeof(KBUGCHECK_DATA); - // AuxKlibGetBugCheckData(&bugCheckData); + // + // Retrieve the bugcheck parameters. + // + bugCheckData.BugCheckDataSize = sizeof(KBUGCHECK_DATA); + AuxKlibGetBugCheckData(&bugCheckData); - // // - // // Check whether the code address that caused the bugcheck is from this wdf - // // driver. - // // - // switch (bugCheckData.BugCheckCode) { + // + // Check whether the code address that caused the bugcheck is from this wdf + // driver. + // + switch (bugCheckData.BugCheckCode) { - // case KERNEL_APC_PENDING_DURING_EXIT: // 0x20 - // codeAddr = (PVOID)bugCheckData.Parameter1; - // found = FxpIsAddressKnownToWdf(codeAddr, FxDriverGlobals); - // break; + case KERNEL_APC_PENDING_DURING_EXIT: // 0x20 + codeAddr = (PVOID)bugCheckData.Parameter1; + found = FxpIsAddressKnownToWdf(codeAddr, FxDriverGlobals); + break; - // case KMODE_EXCEPTION_NOT_HANDLED: // 0x1E - // case SYSTEM_THREAD_EXCEPTION_NOT_HANDLED: // 0x7E - // case KERNEL_MODE_EXCEPTION_NOT_HANDLED: // 0x8E - // codeAddr = (PVOID)bugCheckData.Parameter2; - // found = FxpIsAddressKnownToWdf(codeAddr, FxDriverGlobals); - // break; + case KMODE_EXCEPTION_NOT_HANDLED: // 0x1E + case SYSTEM_THREAD_EXCEPTION_NOT_HANDLED: // 0x7E + case KERNEL_MODE_EXCEPTION_NOT_HANDLED: // 0x8E + codeAddr = (PVOID)bugCheckData.Parameter2; + found = FxpIsAddressKnownToWdf(codeAddr, FxDriverGlobals); + break; - // case PAGE_FAULT_IN_NONPAGED_AREA: // 0x50 - // codeAddr = (PVOID)bugCheckData.Parameter3; - // found = FxpIsAddressKnownToWdf(codeAddr, FxDriverGlobals); - // break; + case PAGE_FAULT_IN_NONPAGED_AREA: // 0x50 + codeAddr = (PVOID)bugCheckData.Parameter3; + found = FxpIsAddressKnownToWdf(codeAddr, FxDriverGlobals); + break; - // case IRQL_NOT_LESS_OR_EQUAL: // 0xA - // case DRIVER_IRQL_NOT_LESS_OR_EQUAL: // 0xD1 - // codeAddr = (PVOID)bugCheckData.Parameter4; - // found = FxpIsAddressKnownToWdf(codeAddr, FxDriverGlobals); - // break; - // } + case IRQL_NOT_LESS_OR_EQUAL: // 0xA + case DRIVER_IRQL_NOT_LESS_OR_EQUAL: // 0xD1 + codeAddr = (PVOID)bugCheckData.Parameter4; + found = FxpIsAddressKnownToWdf(codeAddr, FxDriverGlobals); + break; + } - // // - // // If the code address was found in the wdf driver, then set the flag in the - // // driver globals to indicate that the IFR data has to be written to the - // // mini-dump. - // // - // if (found) { - // FxDriverGlobals->FxForceLogsInMiniDump = TRUE; - // } - // return found; - ROSWDFNOTIMPLEMENTED; - return FALSE; + // + // If the code address was found in the wdf driver, then set the flag in the + // driver globals to indicate that the IFR data has to be written to the + // mini-dump. + // + if (found) { + FxDriverGlobals->FxForceLogsInMiniDump = TRUE; + } + return found; } VOID