diff --git a/src/driver/fortutl.c b/src/driver/fortutl.c index 1baa5be4..c43459cc 100644 --- a/src/driver/fortutl.c +++ b/src/driver/fortutl.c @@ -4,7 +4,9 @@ #define FORT_UTIL_POOL_TAG 'UwfF' -FORT_API NTSTATUS fort_reg_value(HANDLE regKey, PUNICODE_STRING valueName, PWSTR *outData) +#define FORT_MAX_FILE_SIZE (4 * 1024 * 1024) + +static NTSTATUS fort_reg_value(HANDLE regKey, PUNICODE_STRING valueName, PWSTR *outData) { NTSTATUS status; @@ -75,3 +77,65 @@ FORT_API NTSTATUS fort_driver_path(PDRIVER_OBJECT driver, PUNICODE_STRING regPat return status; } + +FORT_API NTSTATUS fort_file_read(HANDLE fileHandle, ULONG poolTag, PUCHAR *outData, DWORD *outSize) +{ + NTSTATUS status; + + // Get File Size + DWORD fileSize = 0; + { + IO_STATUS_BLOCK statusBlock; + FILE_STANDARD_INFORMATION fileInfo; + status = ZwQueryInformationFile( + fileHandle, &statusBlock, &fileInfo, sizeof(fileInfo), FileStandardInformation); + + if (!NT_SUCCESS(status)) + return status; + + if (fileInfo.EndOfFile.HighPart != 0 || fileInfo.EndOfFile.LowPart <= 0 + || fileInfo.EndOfFile.LowPart > FORT_MAX_FILE_SIZE) + return STATUS_FILE_NOT_SUPPORTED; + + fileSize = fileInfo.EndOfFile.LowPart; + } + + // Allocate Buffer + PUCHAR data = fort_mem_alloc(fileSize, poolTag); + if (data == NULL) + return STATUS_INSUFFICIENT_RESOURCES; + + // Read File + DWORD dataSize = 0; + do { + IO_STATUS_BLOCK statusBlock; + status = ZwReadFile(fileHandle, NULL, NULL, NULL, &statusBlock, data + dataSize, + fileSize - dataSize, NULL, NULL); + + if (!NT_SUCCESS(status) || statusBlock.Information == 0) { + fort_mem_free(data, poolTag); + return NT_SUCCESS(status) ? STATUS_FILE_NOT_AVAILABLE : status; + } + + dataSize += (DWORD) statusBlock.Information; + } while (dataSize < fileSize); + + *outData = data; + *outSize = dataSize; + + return status; +} + +FORT_API NTSTATUS fort_file_open(PCWSTR filePath, HANDLE *outHandle) +{ + UNICODE_STRING path; + RtlInitUnicodeString(&path, filePath); + + OBJECT_ATTRIBUTES fileAttr; + InitializeObjectAttributes( + &fileAttr, &path, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, NULL, NULL); + + IO_STATUS_BLOCK statusBlock; + return ZwOpenFile(outHandle, GENERIC_READ | SYNCHRONIZE, &fileAttr, &statusBlock, 0, + FILE_SYNCHRONOUS_IO_NONALERT); +} diff --git a/src/driver/fortutl.h b/src/driver/fortutl.h index 397be497..aebe71ee 100644 --- a/src/driver/fortutl.h +++ b/src/driver/fortutl.h @@ -7,10 +7,11 @@ extern "C" { #endif -FORT_API NTSTATUS fort_reg_value(HANDLE regKey, PUNICODE_STRING valueName, PWSTR *outData); - FORT_API NTSTATUS fort_driver_path(PDRIVER_OBJECT driver, PUNICODE_STRING regPath, PWSTR *outPath); +FORT_API NTSTATUS fort_file_read(HANDLE fileHandle, ULONG poolTag, PUCHAR *outData, DWORD *outSize); +FORT_API NTSTATUS fort_file_open(PCWSTR filePath, HANDLE *outHandle); + #ifdef __cplusplus } // extern "C" #endif diff --git a/src/driver/loader/fortdl.c b/src/driver/loader/fortdl.c index dffeb3ba..aa3a6299 100644 --- a/src/driver/loader/fortdl.c +++ b/src/driver/loader/fortdl.c @@ -4,9 +4,7 @@ #include "../fortutl.h" -#define FORTDL_MAX_FILE_SIZE (4 * 1024 * 1024) - -static NTSTATUS fortdl_load_image(PUCHAR data, DWORD dataSize) +static NTSTATUS fortdl_load_image(PUCHAR data, DWORD dataSize, PUCHAR *image) { NTSTATUS status; @@ -15,86 +13,6 @@ static NTSTATUS fortdl_load_image(PUCHAR data, DWORD dataSize) return STATUS_SUCCESS; } -static NTSTATUS fortdl_read_file(HANDLE fileHandle, PUCHAR *outData, DWORD *outSize) -{ - NTSTATUS status; - - // Get File Size - DWORD fileSize = 0; - { - IO_STATUS_BLOCK statusBlock; - FILE_STANDARD_INFORMATION fileInfo; - status = ZwQueryInformationFile( - fileHandle, &statusBlock, &fileInfo, sizeof(fileInfo), FileStandardInformation); - - if (!NT_SUCCESS(status)) - return status; - - if (fileInfo.EndOfFile.HighPart != 0 || fileInfo.EndOfFile.LowPart <= 0 - || fileInfo.EndOfFile.LowPart > FORTDL_MAX_FILE_SIZE) - return STATUS_FILE_NOT_SUPPORTED; - - fileSize = fileInfo.EndOfFile.LowPart; - } - - // Allocate Buffer - PUCHAR data = fortdl_alloc(fileSize); - if (data == NULL) - return STATUS_INSUFFICIENT_RESOURCES; - - // Read File - DWORD dataSize = 0; - do { - IO_STATUS_BLOCK statusBlock; - status = ZwReadFile(fileHandle, NULL, NULL, NULL, &statusBlock, data + dataSize, - fileSize - dataSize, NULL, NULL); - - if (!NT_SUCCESS(status) || statusBlock.Information == 0) { - fortdl_free(data); - return NT_SUCCESS(status) ? STATUS_FILE_NOT_AVAILABLE : status; - } - - dataSize += (DWORD) statusBlock.Information; - } while (dataSize < fileSize); - - *outData = data; - *outSize = dataSize; - - return status; -} - -static NTSTATUS fortdl_load_file(PCWSTR driverPath, PUCHAR *outData, DWORD *outSize) -{ - NTSTATUS status; - - DbgPrintEx( - DPFLTR_IHVNETWORK_ID, DPFLTR_ERROR_LEVEL, "FORT: Loader Load File: %w\n", driverPath); - - // Open File - HANDLE fileHandle; - { - UNICODE_STRING path; - RtlInitUnicodeString(&path, driverPath); - - OBJECT_ATTRIBUTES fileAttr; - InitializeObjectAttributes( - &fileAttr, &path, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, NULL, NULL); - - IO_STATUS_BLOCK statusBlock; - status = ZwOpenFile(&fileHandle, GENERIC_READ | SYNCHRONIZE, &fileAttr, &statusBlock, 0, - FILE_SYNCHRONOUS_IO_NONALERT); - if (!NT_SUCCESS(status)) - return status; - } - - // Read File - status = fortdl_read_file(fileHandle, outData, outSize); - - ZwClose(fileHandle); - - return status; -} - static void fortdl_init(PDRIVER_OBJECT driver, PVOID context, ULONG count) { NTSTATUS status; @@ -108,7 +26,20 @@ static void fortdl_init(PDRIVER_OBJECT driver, PVOID context, ULONG count) PUCHAR data = NULL; DWORD dataSize = 0; { - status = fortdl_load_file(context, &data, &dataSize); + HANDLE fileHandle; + status = fort_file_open(context, &fileHandle); + + DbgPrintEx(DPFLTR_IHVNETWORK_ID, DPFLTR_ERROR_LEVEL, + "FORT: Loader File Load: %w status=%d\n", (PCWSTR) context, status); + + if (NT_SUCCESS(status)) { + status = fort_file_read(fileHandle, FORT_LOADER_POOL_TAG, &data, &dataSize); + ZwClose(fileHandle); + } + + DbgPrintEx(DPFLTR_IHVNETWORK_ID, DPFLTR_ERROR_LEVEL, + "FORT: Loader File Read: %w status=%d size=%d\n", (PCWSTR) context, status, + dataSize); /* Free the allocated driver path */ ExFreePool(context); @@ -117,7 +48,7 @@ static void fortdl_init(PDRIVER_OBJECT driver, PVOID context, ULONG count) // Prepare the driver image PUCHAR image = NULL; if (NT_SUCCESS(status)) { - status = fortdl_load_image(data, dataSize); + status = fortdl_load_image(data, dataSize, &image); /* Free the allocated driver file data */ fortdl_free(data);