Skip to content

Commit

Permalink
Wed 29 Apr 2020 03:51:40 PM CEST
Browse files Browse the repository at this point in the history
  • Loading branch information
Samuel Tulach authored and Samuel Tulach committed Apr 29, 2020
1 parent 1317206 commit b216b24
Show file tree
Hide file tree
Showing 8 changed files with 286 additions and 225 deletions.
68 changes: 63 additions & 5 deletions client/efi-mapper/kdmapper/efi_driver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,13 @@ bool efi_driver::MemCopy(HANDLE device_handle, uint64_t destination, uint64_t so
MemoryCommand* cmd = new MemoryCommand();
cmd->operation = 0;
cmd->magic = COMMAND_MAGIC;
cmd->data1 = destination;
cmd->data2 = source;

uintptr_t data[10];
data[0] = destination;
data[1] = source;

memcpy(&cmd->data, &data[0], sizeof(data));

cmd->size = (int)size;

SendCommand(cmd);
Expand Down Expand Up @@ -82,8 +87,19 @@ uint64_t efi_driver::AllocatePool(HANDLE device_handle, nt::POOL_TYPE pool_type,

uint64_t allocated_pool = 0;

if (!CallKernelFunction(device_handle, &allocated_pool, kernel_ExAllocatePool, pool_type, size))
return 0;
MemoryCommand* cmd = new MemoryCommand();
cmd->operation = 1;
cmd->magic = COMMAND_MAGIC;

uintptr_t data[10];
data[0] = kernel_ExAllocatePool;
data[1] = pool_type;
data[2] = size;
data[3] = (uintptr_t)&allocated_pool;

memcpy(&cmd->data, &data[0], sizeof(data));

SendCommand(cmd);

return allocated_pool;
}
Expand All @@ -98,7 +114,19 @@ bool efi_driver::FreePool(HANDLE device_handle, uint64_t address)
if (!kernel_ExFreePool)
kernel_ExFreePool = GetKernelModuleExport(device_handle, utils::GetKernelModuleAddress("ntoskrnl.exe"), "ExFreePool");

return CallKernelFunction<void>(device_handle, nullptr, kernel_ExFreePool, address);
MemoryCommand* cmd = new MemoryCommand();
cmd->operation = 2;
cmd->magic = COMMAND_MAGIC;

uintptr_t data[10];
data[0] = kernel_ExFreePool;
data[1] = address;

memcpy(&cmd->data, &data[0], sizeof(data));

SendCommand(cmd);

return true; // yolo?
}

uint64_t efi_driver::GetKernelModuleExport(HANDLE device_handle, uint64_t kernel_module_base, const std::string & function_name)
Expand Down Expand Up @@ -193,6 +221,36 @@ bool efi_driver::GetNtGdiDdDDIReclaimAllocations2KernelInfo(HANDLE device_handle
return true;
}

bool efi_driver::GetNtGdiGetCOPPCompatibleOPMInformationInfo(HANDLE device_handle, uint64_t* out_kernel_function_ptr, uint8_t* out_kernel_original_bytes)
{
// 48ff2551d81f00 jmp cs:__imp_NtGdiGetCOPPCompatibleOPMInformation
// cccccccccc padding

static uint64_t kernel_function_ptr = 0;
static uint8_t kernel_original_jmp_bytes[12] = { 0 };

if (!kernel_function_ptr || kernel_original_jmp_bytes[0] == 0)
{
const uint64_t kernel_NtGdiGetCOPPCompatibleOPMInformation = GetKernelModuleExport(device_handle, utils::GetKernelModuleAddress("win32kfull.sys"), "NtGdiGetCOPPCompatibleOPMInformation");

if (!kernel_NtGdiGetCOPPCompatibleOPMInformation)
{
std::cout << "[-] Failed to get export win32kfull.NtGdiGetCOPPCompatibleOPMInformation" << std::endl;
return false;
}

kernel_function_ptr = kernel_NtGdiGetCOPPCompatibleOPMInformation;

if (!ReadMemory(device_handle, kernel_function_ptr, kernel_original_jmp_bytes, sizeof(kernel_original_jmp_bytes)))
return false;
}

*out_kernel_function_ptr = kernel_function_ptr;
memcpy(out_kernel_original_bytes, kernel_original_jmp_bytes, sizeof(kernel_original_jmp_bytes));

return true;
}

bool efi_driver::ClearMmUnloadedDrivers(HANDLE device_handle)
{
ULONG buffer_size = 0;
Expand Down
70 changes: 3 additions & 67 deletions client/efi-mapper/kdmapper/efi_driver.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,7 @@ namespace efi_driver
{
int magic;
int operation;
unsigned long long data1;
unsigned long long data2;
unsigned long long data[10];
int size;
} MemoryCommand;

Expand Down Expand Up @@ -45,69 +44,6 @@ namespace efi_driver
bool FreePool(HANDLE device_handle, uint64_t address);
uint64_t GetKernelModuleExport(HANDLE device_handle, uint64_t kernel_module_base, const std::string& function_name);
bool GetNtGdiDdDDIReclaimAllocations2KernelInfo(HANDLE device_handle, uint64_t* out_kernel_function_ptr, uint64_t* out_kernel_original_function_address);
bool GetNtGdiGetCOPPCompatibleOPMInformationInfo(HANDLE device_handle, uint64_t* out_kernel_function_ptr, uint8_t* out_kernel_original_bytes);
bool ClearMmUnloadedDrivers(HANDLE device_handle);

template<typename T, typename ...A>
bool CallKernelFunction(HANDLE device_handle, T* out_result, uint64_t kernel_function_address, const A ...arguments)
{
constexpr auto call_void = std::is_same_v<T, void>;

if constexpr (!call_void)
{
if (!out_result)
return false;
}
else
{
UNREFERENCED_PARAMETER(out_result);
}

if (!kernel_function_address)
return false;

// Setup function call

const auto NtGdiDdDDIReclaimAllocations2 = reinterpret_cast<void*>(GetProcAddress(LoadLibrary("gdi32full.dll"), "NtGdiDdDDIReclaimAllocations2"));

if (!NtGdiDdDDIReclaimAllocations2)
{
std::cout << "[-] Failed to get export gdi32full.NtGdiDdDDIReclaimAllocations2" << std::endl;
return false;
}

// Get function pointer (@win32kbase!gDxgkInterface table) used by NtGdiDdDDIReclaimAllocations2 and save the original address (dxgkrnl!DxgkReclaimAllocations2)

uint64_t kernel_function_ptr = 0;
uint64_t kernel_original_function_address = 0;

if (!GetNtGdiDdDDIReclaimAllocations2KernelInfo(device_handle, &kernel_function_ptr, &kernel_original_function_address))
return false;

// Overwrite the pointer with kernel_function_address

if (!WriteMemory(device_handle, kernel_function_ptr, &kernel_function_address, sizeof(kernel_function_address)))
return false;

// Call function

if constexpr (!call_void)
{
using FunctionFn = T(__stdcall*)(A...);
const auto Function = static_cast<FunctionFn>(NtGdiDdDDIReclaimAllocations2);

*out_result = Function(arguments...);
}
else
{
using FunctionFn = void(__stdcall*)(A...);
const auto Function = static_cast<FunctionFn>(NtGdiDdDDIReclaimAllocations2);

Function(arguments...);
}

// Restore the pointer

WriteMemory(device_handle, kernel_function_ptr, &kernel_original_function_address, sizeof(kernel_original_function_address));
return true;
}
}
}
19 changes: 12 additions & 7 deletions client/efi-mapper/kdmapper/kdmapper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -79,18 +79,23 @@ uint64_t kdmapper::MapDriver(HANDLE iqvw64e_device_handle, const std::string& dr

std::cout << "[<] Calling DriverEntry 0x" << reinterpret_cast<void*>(address_of_entry_point) << std::endl;

NTSTATUS status = 0;
long status = 0; // NTSTATUS

if (!efi_driver::CallKernelFunction(iqvw64e_device_handle, &status, address_of_entry_point))
{
std::cout << "[-] Failed to call driver entry" << std::endl;
break;
}
efi_driver::MemoryCommand* cmd = new efi_driver::MemoryCommand();
cmd->operation = 5;
cmd->magic = COMMAND_MAGIC;

uintptr_t data[10];
data[0] = address_of_entry_point;
data[1] = (uintptr_t)&status;

memcpy(&cmd->data, &data[0], sizeof(data));

efi_driver::SendCommand(cmd);

std::cout << "[+] DriverEntry returned 0x" << std::hex << std::setw(8) << std::setfill('0') << std::uppercase << status << std::nouppercase << std::dec << std::endl;

// Erase PE headers

efi_driver::SetMemory(iqvw64e_device_handle, kernel_image_base, 0, nt_headers->OptionalHeader.SizeOfHeaders);
return kernel_image_base;

Expand Down
Loading

0 comments on commit b216b24

Please sign in to comment.