From 42c7f649f9e58eb73f7cfc93a5212e7cc2317a0a Mon Sep 17 00:00:00 2001 From: momo5502 Date: Sun, 3 Apr 2022 19:10:04 +0200 Subject: [PATCH] More irp implementation --- src/CMakeLists.txt | 1 + src/driver/CMakeLists.txt | 1 + src/driver/irp.cpp | 19 ++++++++- src/driver/memory.cpp | 12 ++++++ src/driver/memory.hpp | 2 + src/driver/nt_ext.hpp | 63 ++++++++++++++++++++++++++++ src/driver/process.cpp | 88 +++++++++++++++++++++++++++++++++++++++ src/driver/process.hpp | 46 ++++++++++++++++++++ src/runner/CMakeLists.txt | 4 ++ src/runner/main.cpp | 17 ++++++-- src/shared/CMakeLists.txt | 8 ++++ src/shared/irp_data.hpp | 14 +++++++ 12 files changed, 271 insertions(+), 4 deletions(-) create mode 100644 src/driver/process.cpp create mode 100644 src/driver/process.hpp create mode 100644 src/shared/CMakeLists.txt create mode 100644 src/shared/irp_data.hpp diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 7f1e256..3140a74 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,2 +1,3 @@ +add_subdirectory(shared) add_subdirectory(driver) add_subdirectory(runner) \ No newline at end of file diff --git a/src/driver/CMakeLists.txt b/src/driver/CMakeLists.txt index 1f8237e..29aca42 100644 --- a/src/driver/CMakeLists.txt +++ b/src/driver/CMakeLists.txt @@ -26,4 +26,5 @@ add_custom_command(TARGET driver target_link_libraries(driver vcrtl_driver ia32_doc + shared ) diff --git a/src/driver/irp.cpp b/src/driver/irp.cpp index b51e868..addde52 100644 --- a/src/driver/irp.cpp +++ b/src/driver/irp.cpp @@ -3,8 +3,9 @@ #include "logging.hpp" #include "exception.hpp" #include "string.hpp" +#include "memory.hpp" -#define HELLO_DRV_IOCTL CTL_CODE(FILE_DEVICE_UNKNOWN, 0x800, METHOD_NEITHER, FILE_ANY_ACCESS) +#include namespace { @@ -32,6 +33,19 @@ namespace return STATUS_SUCCESS; } + // TODO: This is vulnerable as fuck. Optimize! + void apply_hook(hook_request* request) + { + const auto address = reinterpret_cast(request->target_address); + const auto aligned_address = address & (PAGE_SIZE - 1); + const auto offset = address - aligned_address; + + uint8_t buffer[PAGE_SIZE * 2]{0}; + memory::query_process_physical_page(request->process_id, reinterpret_cast(address), buffer); + + debug_log("Data: %s\n", buffer + offset); + } + _Function_class_(DRIVER_DISPATCH) NTSTATUS io_ctl_handler( PDEVICE_OBJECT /*device_object*/, const PIRP irp) { @@ -51,6 +65,9 @@ namespace case HELLO_DRV_IOCTL: debug_log("Hello from the Driver!\n"); break; + case HOOK_DRV_IOCTL: + apply_hook(static_cast(irp_sp->Parameters.DeviceIoControl.Type3InputBuffer)); + break; default: debug_log("Invalid IOCTL Code: 0x%X\n", ioctr_code); irp->IoStatus.Status = STATUS_INVALID_DEVICE_REQUEST; diff --git a/src/driver/memory.cpp b/src/driver/memory.cpp index 37f3eaf..95b447f 100644 --- a/src/driver/memory.cpp +++ b/src/driver/memory.cpp @@ -1,6 +1,7 @@ #include "std_include.hpp" #include "memory.hpp" #include "string.hpp" +#include "process.hpp" namespace memory { @@ -103,4 +104,15 @@ namespace memory ExFreePool(memory); } } + + uint64_t query_process_physical_page(const uint32_t process_id, void* address, + uint8_t buffer[PAGE_SIZE]) + { + const auto process_handle = process::find_process_by_id(process_id); + + process::scoped_process_attacher attacher{process_handle}; + + memcpy(buffer, address, PAGE_SIZE); + return get_physical_address(address); + } } diff --git a/src/driver/memory.hpp b/src/driver/memory.hpp index 9eeda45..6f3f69e 100644 --- a/src/driver/memory.hpp +++ b/src/driver/memory.hpp @@ -27,4 +27,6 @@ namespace memory _IRQL_requires_max_(DISPATCH_LEVEL) void free_non_paged_memory(void* memory); + + uint64_t query_process_physical_page(uint32_t process_id, void* address, uint8_t buffer[PAGE_SIZE]); } diff --git a/src/driver/nt_ext.hpp b/src/driver/nt_ext.hpp index fa27da8..9cebaf7 100644 --- a/src/driver/nt_ext.hpp +++ b/src/driver/nt_ext.hpp @@ -4,6 +4,8 @@ extern "C" { #endif +// ---------------------------------------- + NTKERNELAPI _IRQL_requires_max_(APC_LEVEL) _IRQL_requires_min_(PASSIVE_LEVEL) @@ -14,6 +16,7 @@ KeGenericCallDpc( _In_opt_ PVOID Context ); +// ---------------------------------------- NTKERNELAPI _IRQL_requires_(DISPATCH_LEVEL) @@ -23,6 +26,8 @@ KeSignalCallDpcDone( _In_ PVOID SystemArgument1 ); +// ---------------------------------------- + NTKERNELAPI _IRQL_requires_(DISPATCH_LEVEL) _IRQL_requires_same_ @@ -31,6 +36,8 @@ KeSignalCallDpcSynchronize( _In_ PVOID SystemArgument2 ); +// ---------------------------------------- + #if (NTDDI_VERSION < NTDDI_WIN8) _Must_inspect_result_ _IRQL_requires_max_(DISPATCH_LEVEL) @@ -46,6 +53,8 @@ MmAllocateContiguousNodeMemory( ); #endif +// ---------------------------------------- + NTSYSAPI VOID NTAPI @@ -53,6 +62,60 @@ RtlCaptureContext( _Out_ PCONTEXT ContextRecord ); +// ---------------------------------------- + +typedef struct _KAPC_STATE +{ + LIST_ENTRY ApcListHead[MaximumMode]; + struct _KPROCESS* Process; + BOOLEAN KernelApcInProgress; + BOOLEAN KernelApcPending; + BOOLEAN UserApcPending; +} KAPC_STATE, *PKAPC_STATE, *PRKAPC_STATE; + +// ---------------------------------------- + +NTKERNELAPI +VOID +KeStackAttachProcess( + __inout PEPROCESS PROCESS, + __out PRKAPC_STATE ApcState +); + +// ---------------------------------------- + +NTKERNELAPI +VOID +KeUnstackDetachProcess( + __in PRKAPC_STATE ApcState +); + +// ---------------------------------------- + +NTKERNELAPI +NTSTATUS +PsLookupProcessByProcessId( + IN HANDLE ProcessId, + OUT PEPROCESS* Process +); + +// ---------------------------------------- + +NTKERNELAPI +PVOID +PsGetProcessSectionBaseAddress( + __in PEPROCESS Process +); + +// ---------------------------------------- + +NTKERNELAPI +PPEB +NTAPI +PsGetProcessPeb( + IN PEPROCESS Process +); + #ifdef __cplusplus } #endif diff --git a/src/driver/process.cpp b/src/driver/process.cpp new file mode 100644 index 0000000..9834b01 --- /dev/null +++ b/src/driver/process.cpp @@ -0,0 +1,88 @@ +#include "std_include.hpp" +#include "process.hpp" +#include "type_traits.hpp" +#include "exception.hpp" + +namespace process +{ + process_handle::process_handle(const PEPROCESS handle) + : handle_(handle) + { + } + + process_handle::~process_handle() + { + this->release(); + } + + process_handle::process_handle(process_handle&& obj) noexcept + : process_handle() + { + this->operator=(std::move(obj)); + } + + process_handle& process_handle::operator=(process_handle&& obj) noexcept + { + if (this != &obj) + { + this->release(); + this->handle_ = obj.handle_; + obj.handle_ = nullptr; + } + + return *this; + } + + process_handle::operator bool() const + { + return this->handle_ != nullptr; + } + + process_handle::operator PEPROCESS() const + { + return this->handle_; + } + + bool process_handle::is_alive() const + { + LARGE_INTEGER zero_time{}; + zero_time.QuadPart = 0; + + return KeWaitForSingleObject(this->handle_, Executive, KernelMode, FALSE, &zero_time) != STATUS_WAIT_0; + } + + void process_handle::release() + { + if (this->handle_) + { + ObDereferenceObject(this->handle_); + this->handle_ = nullptr; + } + } + + process_handle find_process_by_id(const uint32_t process_id) + { + PEPROCESS process{}; + if (PsLookupProcessByProcessId(HANDLE(process_id), &process) != STATUS_SUCCESS) + { + return {}; + } + + return process_handle{process}; + } + + scoped_process_attacher::scoped_process_attacher(const process_handle& process) + { + if (!process || !process.is_alive()) + { + throw std::runtime_error("Invalid process"); + } + + KeStackAttachProcess(process, &this->apc_state_); + } + + scoped_process_attacher::~scoped_process_attacher() + { + KeUnstackDetachProcess(&this->apc_state_); + } +} diff --git a/src/driver/process.hpp b/src/driver/process.hpp new file mode 100644 index 0000000..d3c335b --- /dev/null +++ b/src/driver/process.hpp @@ -0,0 +1,46 @@ +#pragma once + +namespace process +{ + class process_handle + { + public: + process_handle() = default; + process_handle(PEPROCESS handle); + ~process_handle(); + + process_handle(process_handle&& obj) noexcept; + process_handle& operator=(process_handle&& obj) noexcept; + + process_handle(const process_handle&) = delete; + process_handle& operator=(const process_handle&) = delete; + + operator bool() const; + operator PEPROCESS() const; + + bool is_alive() const; + + private: + PEPROCESS handle_{nullptr}; + + void release(); + }; + + process_handle find_process_by_id(uint32_t process_id); + + class scoped_process_attacher + { + public: + scoped_process_attacher(const process_handle& process); + ~scoped_process_attacher(); + + scoped_process_attacher(scoped_process_attacher&& obj) noexcept = delete; + scoped_process_attacher& operator=(scoped_process_attacher&& obj) noexcept = delete; + + scoped_process_attacher(const scoped_process_attacher&) = delete; + scoped_process_attacher& operator=(const scoped_process_attacher&) = delete; + + private: + KAPC_STATE apc_state_{}; + }; +} diff --git a/src/runner/CMakeLists.txt b/src/runner/CMakeLists.txt index 8fd0e62..dc2862b 100644 --- a/src/runner/CMakeLists.txt +++ b/src/runner/CMakeLists.txt @@ -13,3 +13,7 @@ target_precompile_headers(runner set_property(TARGET runner APPEND_STRING PROPERTY LINK_FLAGS " /MANIFESTUAC:\"level='requireAdministrator'\"") add_dependencies(runner driver) + +target_link_libraries(runner + shared +) \ No newline at end of file diff --git a/src/runner/main.cpp b/src/runner/main.cpp index 8599746..718152f 100644 --- a/src/runner/main.cpp +++ b/src/runner/main.cpp @@ -3,9 +3,9 @@ #include "driver.hpp" #include "driver_device.hpp" -#pragma comment(lib, "Shlwapi.lib") +#include -#define HELLO_DRV_IOCTL CTL_CODE(FILE_DEVICE_UNKNOWN, 0x800, METHOD_NEITHER, FILE_ANY_ACCESS) +#pragma comment(lib, "Shlwapi.lib") BOOL send_ioctl(HANDLE device, DWORD ioctl_code) { @@ -53,6 +53,17 @@ void unsafe_main(const int /*argc*/, char* /*argv*/[]) (void)driver_device.send(HELLO_DRV_IOCTL, input); MessageBoxA(0, "Service started!", 0, 0); + + hook_request hook_request{}; + hook_request.process_id = GetCurrentProcessId(); + hook_request.target_address = "My Message!"; + + input.assign(reinterpret_cast(&hook_request), + reinterpret_cast(&hook_request) + sizeof(hook_request)); + + (void)driver_device.send(HOOK_DRV_IOCTL, input); + + MessageBoxA(0, "Press ok to exit!", 0, 0); } int main(const int argc, char* argv[]) @@ -69,7 +80,7 @@ int main(const int argc, char* argv[]) } catch (...) { - printf("An unknown error occurd!\n"); + printf("An unknown error occured!\n"); return 1; } } diff --git a/src/shared/CMakeLists.txt b/src/shared/CMakeLists.txt new file mode 100644 index 0000000..3f7a28c --- /dev/null +++ b/src/shared/CMakeLists.txt @@ -0,0 +1,8 @@ +file(GLOB shared_sources ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp) +file(GLOB shared_headers ${CMAKE_CURRENT_SOURCE_DIR}/*.hpp) + +add_library(shared INTERFACE + ${shared_headers} +) + +target_include_directories(shared INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}) \ No newline at end of file diff --git a/src/shared/irp_data.hpp b/src/shared/irp_data.hpp new file mode 100644 index 0000000..782f0db --- /dev/null +++ b/src/shared/irp_data.hpp @@ -0,0 +1,14 @@ +#pragma once + +#define HELLO_DRV_IOCTL CTL_CODE(FILE_DEVICE_UNKNOWN, 0x800, METHOD_NEITHER, FILE_ANY_ACCESS) +#define HOOK_DRV_IOCTL CTL_CODE(FILE_DEVICE_UNKNOWN, 0x801, METHOD_NEITHER, FILE_ANY_ACCESS) + +static_assert(sizeof(void*) == 8); + +struct hook_request +{ + uint32_t process_id{}; + const void* target_address{}; + const void* source_data{}; + uint64_t source_data_size{}; +};