updated project to use new PTM

master v1.1
_xeroxz 4 years ago
parent e176e250da
commit 2330acef93

@ -2,7 +2,7 @@
namespace nasa namespace nasa
{ {
injector_ctx::injector_ctx(nasa::mem_ctx* map_into, nasa::mem_ctx* map_from) injector_ctx::injector_ctx(ptm::ptm_ctx* map_into, ptm::ptm_ctx* map_from)
: :
map_into(map_into), map_into(map_into),
map_from(map_from), map_from(map_from),
@ -11,15 +11,14 @@ namespace nasa
injector_ctx::~injector_ctx() injector_ctx::~injector_ctx()
{ {
const auto pml4 = reinterpret_cast<ppml4e>( const auto pml4 =
reinterpret_cast<ppml4e>(
map_into->set_page( map_into->set_page(
map_into->get_dirbase())); map_into->dirbase));
// zero inserted pml4e's... // zero inserted pml4e's...
for (const auto [real_idx, inserted_idx] : pml4_index_map) for (const auto [real_idx, inserted_idx] : pml4_index_map)
pml4[inserted_idx] = pml4e{ NULL }; pml4[inserted_idx] = pml4e{ NULL };
while (!SwitchToThread());
} }
bool injector_ctx::init() const bool injector_ctx::init() const
@ -27,12 +26,12 @@ namespace nasa
const auto source_pml4 = const auto source_pml4 =
reinterpret_cast<ppml4e>( reinterpret_cast<ppml4e>(
map_from->set_page( map_from->set_page(
map_from->get_dirbase())); map_from->dirbase));
const auto target_pml4 = const auto target_pml4 =
reinterpret_cast<ppml4e>( reinterpret_cast<ppml4e>(
map_into->set_page( map_into->set_page(
map_into->get_dirbase())); map_into->dirbase));
std::vector<std::pair<std::uint8_t, pml4e>> present_pml4es; std::vector<std::pair<std::uint8_t, pml4e>> present_pml4es;
std::vector<std::uint8_t> empty_pml4es; std::vector<std::uint8_t> empty_pml4es;
@ -66,23 +65,23 @@ namespace nasa
virt_addr_t virt_addr{ reinterpret_cast<void*>(translate) }; virt_addr_t virt_addr{ reinterpret_cast<void*>(translate) };
try try
{ {
virt_addr.pml4_index = pml4_index_map.at(virt_addr.pml4_index); virt_addr.pml4_index =
pml4_index_map.at(virt_addr.pml4_index);
} }
catch (const std::out_of_range& e) catch (const std::out_of_range& e)
{ {
// the pml4e is not in the map so we need to go get it // the pml4e is not in the map so we need to go get it
// and put it inside of the map. also put it inside of // and put it inside of the map. also put it inside of
// map_into's pml4... // map_into's pml4...
const auto map_into_pml4 = const auto map_into_pml4 =
reinterpret_cast<ppml4e>( reinterpret_cast<ppml4e>(
map_into->set_page( map_into->set_page(
map_into->get_dirbase())); map_into->dirbase));
const auto map_from_pml4 = const auto map_from_pml4 =
reinterpret_cast<ppml4e>( reinterpret_cast<ppml4e>(
map_from->set_page( map_from->set_page(
map_from->get_dirbase())); map_from->dirbase));
const auto new_pml4e = const auto new_pml4e =
map_from_pml4[virt_addr.pml4_index]; map_from_pml4[virt_addr.pml4_index];
@ -98,6 +97,7 @@ namespace nasa
} }
} }
} }
return reinterpret_cast<std::uintptr_t>(virt_addr.value); return reinterpret_cast<std::uintptr_t>(virt_addr.value);
} }
} }

@ -1,22 +1,22 @@
#pragma once #pragma once
#include "../mem_ctx/mem_ctx.hpp" #include "../ptm_ctx/ptm_ctx.hpp"
namespace nasa namespace nasa
{ {
class injector_ctx class injector_ctx
{ {
public: public:
explicit injector_ctx(nasa::mem_ctx* map_into, nasa::mem_ctx* map_from); explicit injector_ctx(ptm::ptm_ctx* map_into, ptm::ptm_ctx* map_from);
~injector_ctx(); ~injector_ctx();
std::uintptr_t translate(std::uintptr_t) const; auto translate(std::uintptr_t) const -> std::uintptr_t;
bool init() const; auto init() const -> bool;
private: private:
// std::uint8_t is 2^8 = 256 which is the same amount // std::uint8_t is 2^8 = 256 which is the same amount
// of possible usermode pml4e's... // of possible usermode pml4e's...
// //
// also this is "real pml4e index" ---> "inserted pml4e index" // also this is "real pml4e index" ---> "inserted pml4e index"
mutable std::map<std::uint8_t, std::uint8_t> pml4_index_map; mutable std::map<std::uint8_t, std::uint8_t> pml4_index_map;
nasa::mem_ctx* map_into, *map_from; ptm::ptm_ctx* map_into, *map_from;
}; };
} }

@ -1,5 +1,5 @@
#include "vdm_ctx/vdm_ctx.hpp" #include "vdm_ctx/vdm_ctx.hpp"
#include "mem_ctx/mem_ctx.hpp" #include "ptm_ctx/ptm_ctx.hpp"
#include "injector_ctx/injector_ctx.hpp" #include "injector_ctx/injector_ctx.hpp"
#include "set_mgr/set_mgr.hpp" #include "set_mgr/set_mgr.hpp"
@ -33,7 +33,7 @@ int __cdecl main(int argc, char** argv)
}; };
vdm::vdm_ctx vdm(_read_phys, _write_phys); vdm::vdm_ctx vdm(_read_phys, _write_phys);
nasa::mem_ctx my_proc(vdm); ptm::ptm_ctx my_proc(&vdm);
const auto set_mgr_pethread = set_mgr::get_setmgr_pethread(vdm); const auto set_mgr_pethread = set_mgr::get_setmgr_pethread(vdm);
const auto result = set_mgr::stop_setmgr(vdm, set_mgr_pethread); const auto result = set_mgr::stop_setmgr(vdm, set_mgr_pethread);
@ -42,13 +42,15 @@ int __cdecl main(int argc, char** argv)
std::printf("[+] PsSuspendThread result -> 0x%x\n", result); std::printf("[+] PsSuspendThread result -> 0x%x\n", result);
// read physical memory via paging tables and not with the driver... // read physical memory via paging tables and not with the driver...
_read_phys = [&my_proc](void* addr, void* buffer, std::size_t size) -> bool _read_phys =
[&my_proc](void* addr, void* buffer, std::size_t size) -> bool
{ {
return my_proc.read_phys(buffer, addr, size); return my_proc.read_phys(buffer, addr, size);
}; };
// write physical memory via paging tables and not with the driver... // write physical memory via paging tables and not with the driver...
_write_phys = [&my_proc](void* addr, void* buffer, std::size_t size) -> bool _write_phys =
[&my_proc](void* addr, void* buffer, std::size_t size) -> bool
{ {
return my_proc.write_phys(buffer, addr, size); return my_proc.write_phys(buffer, addr, size);
}; };
@ -62,8 +64,8 @@ int __cdecl main(int argc, char** argv)
vdm.set_read(_read_phys); vdm.set_read(_read_phys);
vdm.set_write(_write_phys); vdm.set_write(_write_phys);
nasa::mem_ctx notepad_proc(vdm, std::atoi(argv[2])); ptm::ptm_ctx target_proc(&vdm, std::atoi(argv[2]));
nasa::injector_ctx injector(&my_proc, &notepad_proc); nasa::injector_ctx injector(&my_proc, &target_proc);
if (!injector.init()) if (!injector.init())
{ {

@ -1,87 +0,0 @@
#pragma once
#include "../util/nt.hpp"
#include "../vdm_ctx/vdm_ctx.hpp"
namespace nasa
{
class mem_ctx
{
public:
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);
void set_pte(void* addr, const ::pte& pte, bool use_hyperspace = false);
std::pair<ppde, pde> get_pde(void* addr, bool use_hyperspace = false);
void set_pde(void* addr, const ::pde& pde, bool use_hyperspace = false);
std::pair<ppdpte, pdpte> get_pdpte(void* addr, bool use_hyperspace = false);
void set_pdpte(void* addr, const ::pdpte& pdpte, bool use_hyperspace = false);
std::pair<ppml4e, pml4e> get_pml4e(void* addr, bool use_hyperspace = false);
void set_pml4e(void* addr, const ::pml4e& pml4e, bool use_hyperspace = false);
void* get_dirbase() const;
static void* get_dirbase(vdm::vdm_ctx& v_ctx, std::uint32_t pid);
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)
{
T buffer;
read_phys((void*)&buffer, addr, sizeof(T));
return buffer;
}
template <class T>
void write_phys(void* addr, const T& data)
{
write_phys((void*)&data, addr, sizeof(T));
}
std::pair<void*, void*> read_virtual(void* buffer, void* addr, std::size_t size);
std::pair<void*, void*> write_virtual(void* buffer, void* addr, std::size_t size);
template <class T>
__forceinline T read_virtual(void* addr)
{
T buffer;
read_virtual((void*)&buffer, addr, sizeof(T));
return buffer;
}
template <class T>
__forceinline void write_virtual(void* addr, const T& data)
{
write_virtual((void*)&data, addr, sizeof(T));
}
void* virt_to_phys(pt_entries& entries, void* addr);
void* set_page(void* addr);
void* get_page() const;
unsigned get_pid() const;
pml4e operator[](std::uint16_t pml4_idx);
pdpte operator[](const std::pair<std::uint16_t, std::uint16_t>& entry_idx);
pde operator[](const std::tuple<std::uint16_t, std::uint16_t, std::uint16_t>& entry_idx);
pte operator[](const std::tuple<std::uint16_t, std::uint16_t, std::uint16_t, std::uint16_t>& entry_idx);
private:
bool hyperspace_entries(pt_entries& entries, void* addr);
void* dirbase;
vdm::vdm_ctx* v_ctx;
std::uint16_t pml4e_index,
pdpte_index,
pde_index,
pte_index,
page_offset;
std::pair<ppdpte, ppdpte> new_pdpt;
std::pair<ppde,ppde> new_pd;
std::pair<ppte, ppte> new_pt;
unsigned pid;
};
}

@ -1,21 +1,26 @@
#include "mem_ctx.hpp" #include "ptm_ctx.hpp"
namespace nasa namespace ptm
{ {
mem_ctx::mem_ctx(vdm::vdm_ctx& v_ctx, std::uint32_t pid) ptm_ctx::ptm_ctx(vdm::vdm_ctx* v_ctx, std::uint32_t pid)
: :
v_ctx(&v_ctx), v_ctx(v_ctx),
pid(pid), dirbase(get_dirbase(*v_ctx, pid)),
dirbase(get_dirbase(v_ctx, pid)) pid(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 =
v_ctx.get_virtual(reinterpret_cast<std::uintptr_t>( v_ctx->get_virtual(reinterpret_cast<std::uintptr_t>(
get_dirbase(v_ctx, GetCurrentProcessId()))); get_dirbase(*v_ctx, GetCurrentProcessId())));
for (auto idx = 100u; idx > 0u; --idx) for (auto idx = 100u; idx > 0u; --idx)
if (!v_ctx.rkm<pml4e>(current_pml4 + (idx * sizeof pml4e)).value) {
if (!v_ctx->rkm<pml4e>(current_pml4 + (idx * sizeof pml4e)).present)
{
this->pml4e_index = idx; this->pml4e_index = idx;
break;
}
}
// allocate a pdpt // allocate a pdpt
this->new_pdpt.second = this->new_pdpt.second =
@ -31,13 +36,17 @@ namespace nasa
// get page table entries for new pdpt // get page table entries for new pdpt
pt_entries new_pdpt_entries; pt_entries new_pdpt_entries;
hyperspace_entries(new_pdpt_entries, new_pdpt.second); hyperspace_entries(new_pdpt_entries, new_pdpt.second);
this->new_pdpt.first = reinterpret_cast<ppdpte>(new_pdpt_entries.pt.second.pfn << 12);
this->new_pdpt.first =
reinterpret_cast<ppdpte>(
new_pdpt_entries.pt.second.pfn << 12);
// make a new pml4e that points to our new pdpt. // make a new pml4e that points to our new pdpt.
new_pdpt_entries.pml4.second.pfn = new_pdpt_entries.pt.second.pfn; new_pdpt_entries.pml4.second.pfn = new_pdpt_entries.pt.second.pfn;
// set the pml4e to point to the new pdpt // set the pml4e to point to the new pdpt
set_pml4e(reinterpret_cast<::ppml4e>(get_dirbase()) + this->pml4e_index, new_pdpt_entries.pml4.second, true); set_pml4e(reinterpret_cast<::ppml4e>(this->dirbase) +
this->pml4e_index, new_pdpt_entries.pml4.second, true);
// make a new pd // make a new pd
this->new_pd.second = this->new_pd.second =
@ -54,7 +63,10 @@ namespace nasa
// get paging table entries for pd // get paging table entries for pd
pt_entries new_pd_entries; pt_entries new_pd_entries;
hyperspace_entries(new_pd_entries, this->new_pd.second); hyperspace_entries(new_pd_entries, this->new_pd.second);
this->new_pd.first = reinterpret_cast<ppde>(new_pd_entries.pt.second.pfn << 12);
this->new_pd.first =
reinterpret_cast<ppde>(
new_pd_entries.pt.second.pfn << 12);
// make a new pt // make a new pt
this->new_pt.second = this->new_pt.second =
@ -67,36 +79,39 @@ 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);
this->new_pt.first = reinterpret_cast<ppte>(new_pt_entries.pt.second.pfn << 12);
this->new_pt.first =
reinterpret_cast<ppte>(
new_pt_entries.pt.second.pfn << 12);
} }
mem_ctx::~mem_ctx() ptm_ctx::~ptm_ctx()
{ {
const auto pml4 = const auto pml4 =
reinterpret_cast<ppml4e>( reinterpret_cast<ppml4e>(
set_page(dirbase))[pml4e_index] = pml4e{ NULL }; set_page(dirbase))[pml4e_index] = pml4e{ NULL };
} }
void* mem_ctx::set_page(void* addr) void* ptm_ctx::set_page(void* addr)
{ {
// table entry change.
++pte_index; ++pte_index;
if (pte_index >= 511) if (pte_index > 511)
{ {
++pde_index; ++pde_index;
pte_index = 0; pte_index = 0;
} }
if (pde_index >= 511) if (pde_index > 511)
{ {
++pdpte_index; ++pdpte_index;
pde_index = 0; pde_index = 0;
} }
if (pdpte_index >= 511) if (pdpte_index > 511)
pdpte_index = 0; pdpte_index = 0;
pdpte new_pdpte = { NULL }; pdpte new_pdpte = { NULL };
@ -104,7 +119,6 @@ namespace nasa
new_pdpte.rw = true; new_pdpte.rw = true;
new_pdpte.pfn = reinterpret_cast<std::uintptr_t>(new_pd.first) >> 12; new_pdpte.pfn = reinterpret_cast<std::uintptr_t>(new_pd.first) >> 12;
new_pdpte.user_supervisor = true; new_pdpte.user_supervisor = true;
new_pdpte.accessed = true;
// set pdpte entry // set pdpte entry
*reinterpret_cast<pdpte*>(new_pdpt.second + pdpte_index) = new_pdpte; *reinterpret_cast<pdpte*>(new_pdpt.second + pdpte_index) = new_pdpte;
@ -114,7 +128,6 @@ namespace nasa
new_pde.rw = true; new_pde.rw = true;
new_pde.pfn = reinterpret_cast<std::uintptr_t>(new_pt.first) >> 12; new_pde.pfn = reinterpret_cast<std::uintptr_t>(new_pt.first) >> 12;
new_pde.user_supervisor = true; new_pde.user_supervisor = true;
new_pde.accessed = true;
// set pde entry // set pde entry
*reinterpret_cast<pde*>(new_pd.second + pde_index) = new_pde; *reinterpret_cast<pde*>(new_pd.second + pde_index) = new_pde;
@ -124,7 +137,6 @@ namespace nasa
new_pte.rw = true; new_pte.rw = true;
new_pte.pfn = reinterpret_cast<std::uintptr_t>(addr) >> 12; new_pte.pfn = reinterpret_cast<std::uintptr_t>(addr) >> 12;
new_pte.user_supervisor = true; new_pte.user_supervisor = true;
new_pte.accessed = true;
// set pte entry // set pte entry
*reinterpret_cast<pte*>(new_pt.second + pte_index) = new_pte; *reinterpret_cast<pte*>(new_pt.second + pte_index) = new_pte;
@ -134,7 +146,7 @@ namespace nasa
return get_page(); return get_page();
} }
void* mem_ctx::get_page() const void* ptm_ctx::get_page() const
{ {
// builds a new address given the state of all table indexes // builds a new address given the state of all table indexes
virt_addr_t new_addr; virt_addr_t new_addr;
@ -143,21 +155,42 @@ namespace nasa
new_addr.pd_index = this->pde_index; new_addr.pd_index = this->pde_index;
new_addr.pt_index = this->pte_index; new_addr.pt_index = this->pte_index;
new_addr.offset = this->page_offset; new_addr.offset = this->page_offset;
// handle TLB issues, the TLB might need to be flushed for this entry...
__try
{
*(std::uint8_t*)new_addr.value = *(std::uint8_t*)new_addr.value;
return new_addr.value;
}
__except (EXCEPTION_EXECUTE_HANDLER)
{
// try again to access the page...
__try
{
*(std::uint8_t*)new_addr.value = *(std::uint8_t*)new_addr.value;
return new_addr.value;
}
// try one last time by yeilding execution...
__except (EXCEPTION_EXECUTE_HANDLER)
{
while (!SwitchToThread())
continue;
}
}
return new_addr.value; return new_addr.value;
} }
void* mem_ctx::get_dirbase(vdm::vdm_ctx& v_ctx, std::uint32_t pid) void* ptm_ctx::get_dirbase(vdm::vdm_ctx& v_ctx, DWORD pid)
{ {
const auto peproc = const auto peproc =
reinterpret_cast<std::uint64_t>(v_ctx.get_peprocess(pid)); reinterpret_cast<std::uint64_t>(
v_ctx.get_peprocess(pid));
const auto dirbase = return reinterpret_cast<void*>(
v_ctx.rkm<pte>(peproc + 0x28); v_ctx.rkm<pte>(peproc + 0x28).pfn << 12);
return reinterpret_cast<void*>(dirbase.pfn << 12);
} }
bool mem_ctx::hyperspace_entries(pt_entries& entries, void* addr) bool ptm_ctx::hyperspace_entries(pt_entries& entries, void* addr)
{ {
if (!addr || !dirbase) if (!addr || !dirbase)
return false; return false;
@ -199,95 +232,106 @@ namespace nasa
return true; return true;
} }
std::pair<ppte, pte> mem_ctx::get_pte(void* addr, bool use_hyperspace) auto ptm_ctx::get_pte(void* addr, bool use_hyperspace) -> std::pair<ppte, pte>
{ {
if (!dirbase || !addr) if (!dirbase || !addr)
return {}; return { {}, {} };
pt_entries entries; pt_entries entries;
if ((use_hyperspace ? hyperspace_entries(entries, addr) : (bool)virt_to_phys(entries, addr))) if ((use_hyperspace ? hyperspace_entries(entries, addr) : (bool)virt_to_phys(entries, addr)))
return { entries.pt.first, entries.pt.second }; return { entries.pt.first, entries.pt.second };
return {};
return { {}, {} };
} }
void mem_ctx::set_pte(void* addr, const ::pte& pte, bool use_hyperspace) bool ptm_ctx::set_pte(void* addr, const ::pte& pte, bool use_hyperspace)
{ {
if (!dirbase || !addr) if (!dirbase || !addr)
return; return false;
if (use_hyperspace) if (use_hyperspace)
v_ctx->wkm(v_ctx->get_virtual(reinterpret_cast<std::uintptr_t>(addr)), pte); return v_ctx->wkm(
else v_ctx->get_virtual(
write_phys(addr, pte); reinterpret_cast<std::uintptr_t>(addr)), pte);
return write_phys(addr, pte);
} }
std::pair<ppde, pde> mem_ctx::get_pde(void* addr, bool use_hyperspace) auto ptm_ctx::get_pde(void* addr, bool use_hyperspace) -> std::pair<ppde, pde>
{ {
if (!dirbase || !addr) if (!dirbase || !addr)
return {}; return { {}, {} };
pt_entries entries; pt_entries entries;
if ((use_hyperspace ? hyperspace_entries(entries, addr) : (bool)virt_to_phys(entries, addr))) if ((use_hyperspace ? hyperspace_entries(entries, addr) : (bool)virt_to_phys(entries, addr)))
return { entries.pd.first, entries.pd.second }; return { entries.pd.first, entries.pd.second };
return {}; return { {}, {} };
} }
void mem_ctx::set_pde(void* addr, const ::pde& pde, bool use_hyperspace) bool ptm_ctx::set_pde(void* addr, const ::pde& pde, bool use_hyperspace)
{ {
if (!this->dirbase || !addr) if (!dirbase || !addr)
return; return false;
if (use_hyperspace) if (use_hyperspace)
v_ctx->wkm(v_ctx->get_virtual(reinterpret_cast<std::uintptr_t>(addr)), pde); return v_ctx->wkm(
else v_ctx->get_virtual(
write_phys(addr, pde); reinterpret_cast<std::uintptr_t>(addr)), pde);
return write_phys(addr, pde);
} }
std::pair<ppdpte, pdpte> mem_ctx::get_pdpte(void* addr, bool use_hyperspace) auto ptm_ctx::get_pdpte(void* addr, bool use_hyperspace) -> std::pair<ppdpte, pdpte>
{ {
if (!dirbase || !addr) if (!dirbase || !addr)
return {}; return { {}, {} };
pt_entries entries; pt_entries entries;
if ((use_hyperspace ? hyperspace_entries(entries, addr) : (bool)virt_to_phys(entries, addr))) if ((use_hyperspace ? hyperspace_entries(entries, addr) : (bool)virt_to_phys(entries, addr)))
return { entries.pdpt.first, entries.pdpt.second }; return { entries.pdpt.first, entries.pdpt.second };
return {};
return { {}, {} };
} }
void mem_ctx::set_pdpte(void* addr, const ::pdpte& pdpte, bool use_hyperspace) bool ptm_ctx::set_pdpte(void* addr, const ::pdpte& pdpte, bool use_hyperspace)
{ {
if (!this->dirbase || !addr) if (!dirbase || !addr)
return; return false;
if (use_hyperspace) if (use_hyperspace)
v_ctx->wkm(v_ctx->get_virtual(reinterpret_cast<std::uintptr_t>(addr)), pdpte); return v_ctx->wkm(
else v_ctx->get_virtual(
write_phys(addr, pdpte); reinterpret_cast<std::uintptr_t>(addr)), pdpte);
return write_phys(addr, pdpte);
} }
std::pair<ppml4e, pml4e> mem_ctx::get_pml4e(void* addr, bool use_hyperspace) auto ptm_ctx::get_pml4e(void* addr, bool use_hyperspace) -> std::pair<ppml4e, pml4e>
{ {
if (!this->dirbase || !addr) if (!dirbase || !addr)
return {}; return { {}, {} };
pt_entries entries; pt_entries entries;
if ((use_hyperspace ? hyperspace_entries(entries, addr) : (bool)virt_to_phys(entries, addr))) if ((use_hyperspace ? hyperspace_entries(entries, addr) : (bool)virt_to_phys(entries, addr)))
return { entries.pml4.first, entries.pml4.second }; return { entries.pml4.first, entries.pml4.second };
return {};
return { {}, {} };
} }
void mem_ctx::set_pml4e(void* addr, const ::pml4e& pml4e, bool use_hyperspace) bool ptm_ctx::set_pml4e(void* addr, const ::pml4e& pml4e, bool use_hyperspace)
{ {
if (!this->dirbase || !addr) if (!dirbase || !addr)
return; return false;
if (use_hyperspace) if (use_hyperspace)
v_ctx->wkm(v_ctx->get_virtual(reinterpret_cast<std::uintptr_t>(addr)), pml4e); return v_ctx->wkm(
else v_ctx->get_virtual(
write_phys(addr, pml4e); reinterpret_cast<std::uintptr_t>(addr)), pml4e);
return write_phys(addr, pml4e);
} }
std::pair<void*, void*> mem_ctx::read_virtual(void* buffer, void* addr, std::size_t size) auto ptm_ctx::read_virtual(void* buffer, void* addr, std::size_t size) -> std::pair<void*, void*>
{ {
if (!buffer || !addr || !size || !dirbase) if (!buffer || !addr || !size || !dirbase)
return {}; return {};
@ -329,7 +373,7 @@ namespace nasa
} }
} }
std::pair<void*, void*> mem_ctx::write_virtual(void* buffer, void* addr, std::size_t size) auto ptm_ctx::write_virtual(void* buffer, void* addr, std::size_t size) -> std::pair<void*, void*>
{ {
if (!buffer || !addr || !size || !dirbase) if (!buffer || !addr || !size || !dirbase)
return {}; return {};
@ -371,7 +415,7 @@ namespace nasa
} }
} }
bool mem_ctx::read_phys(void* buffer, void* addr, std::size_t size) bool ptm_ctx::read_phys(void* buffer, void* addr, std::size_t size)
{ {
if (!buffer || !addr || !size) if (!buffer || !addr || !size)
return false; return false;
@ -388,7 +432,7 @@ namespace nasa
return true; return true;
} }
bool mem_ctx::write_phys(void* buffer, void* addr, std::size_t size) bool ptm_ctx::write_phys(void* buffer, void* addr, std::size_t size)
{ {
if (!buffer || !addr || !size) if (!buffer || !addr || !size)
return false; return false;
@ -405,9 +449,9 @@ namespace nasa
return true; return true;
} }
void* mem_ctx::virt_to_phys(pt_entries& entries, void* addr) void* ptm_ctx::virt_to_phys(pt_entries& entries, void* addr)
{ {
if (!addr || !this->dirbase) if (!addr || !dirbase)
return {}; return {};
const virt_addr_t virt_addr{ addr }; const virt_addr_t virt_addr{ addr };
@ -451,37 +495,4 @@ namespace nasa
return reinterpret_cast<void*>((pte.pfn << 12) + virt_addr.offset); return reinterpret_cast<void*>((pte.pfn << 12) + virt_addr.offset);
} }
unsigned mem_ctx::get_pid() const
{
return this->pid;
}
void* mem_ctx::get_dirbase() const
{
return this->dirbase;
}
pml4e mem_ctx::operator[](std::uint16_t pml4_idx)
{
return read_phys<::pml4e>(reinterpret_cast<ppml4e>(this->dirbase) + pml4_idx);
}
pdpte mem_ctx::operator[](const std::pair<std::uint16_t, std::uint16_t>& entry_idx)
{
const auto pml4_entry = this->operator[](entry_idx.first);
return read_phys<::pdpte>(reinterpret_cast<ppdpte>(pml4_entry.pfn << 12) + entry_idx.second);
}
pde mem_ctx::operator[](const std::tuple<std::uint16_t, std::uint16_t, std::uint16_t>& entry_idx)
{
const auto pdpt_entry = this->operator[]({ std::get<0>(entry_idx), std::get<1>(entry_idx) });
return read_phys<::pde>(reinterpret_cast<ppde>(pdpt_entry.pfn << 12) + std::get<2>(entry_idx));
}
pte mem_ctx::operator[](const std::tuple<std::uint16_t, std::uint16_t, std::uint16_t, std::uint16_t>& entry_idx)
{
const auto pd_entry = this->operator[]({ std::get<0>(entry_idx), std::get<1>(entry_idx), std::get<2>(entry_idx) });
return read_phys<::pte>(reinterpret_cast<ppte>(pd_entry.pfn << 12) + std::get<3>(entry_idx));
}
} }

@ -0,0 +1,80 @@
#pragma once
#include "../util/nt.hpp"
#include "../vdm_ctx/vdm_ctx.hpp"
namespace ptm
{
class ptm_ctx
{
public:
explicit ptm_ctx(vdm::vdm_ctx* v_ctx, std::uint32_t pid = GetCurrentProcessId());
~ptm_ctx();
auto get_pte(void* addr, bool use_hyperspace = false) -> std::pair<ppte, pte>;
bool set_pte(void* addr, const ::pte& pte, bool use_hyperspace = false);
auto get_pde(void* addr, bool use_hyperspace = false) -> std::pair<ppde, pde>;
bool set_pde(void* addr, const ::pde& pde, bool use_hyperspace = false);
auto get_pdpte(void* addr, bool use_hyperspace = false) -> std::pair<ppdpte, pdpte>;
bool set_pdpte(void* addr, const ::pdpte& pdpte, bool use_hyperspace = false);
auto get_pml4e(void* addr, bool use_hyperspace = false) -> std::pair<ppml4e, pml4e>;
bool set_pml4e(void* addr, const ::pml4e& pml4e, bool use_hyperspace = false);
static void* get_dirbase(vdm::vdm_ctx& v_ctx, DWORD pid);
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>
__forceinline T read_phys(void* addr)
{
T buffer;
read_phys((void*)&buffer, addr, sizeof(T));
return buffer;
}
template <class T>
__forceinline bool write_phys(void* addr, const T& data)
{
return write_phys((void*)&data, addr, sizeof(T));
}
auto read_virtual(void* buffer, void* addr, std::size_t size) -> std::pair<void*, void*>;
auto write_virtual(void* buffer, void* addr, std::size_t size) -> std::pair<void*, void*>;
template <class T>
__forceinline T read_virtual(void* addr)
{
T buffer;
read_virtual((void*)&buffer, addr, sizeof(T));
return buffer;
}
template <class T>
__forceinline void write_virtual(void* addr, const T& data)
{
write_virtual((void*)&data, addr, sizeof(T));
}
void* virt_to_phys(pt_entries& entries, void* addr);
bool hyperspace_entries(pt_entries& entries, void* addr);
void* set_page(void* addr);
void* get_page() const;
unsigned pid;
void* dirbase;
vdm::vdm_ctx* v_ctx;
private:
std::uint16_t pml4e_index,
pdpte_index,
pde_index,
pte_index,
page_offset;
std::pair<ppdpte, ppdpte> new_pdpt;
std::pair<ppde,ppde> new_pd;
std::pair<ppte, ppte> new_pt;
};
}

@ -85,13 +85,13 @@
<ItemGroup> <ItemGroup>
<ClCompile Include="injector_ctx\injector_ctx.cpp" /> <ClCompile Include="injector_ctx\injector_ctx.cpp" />
<ClCompile Include="main.cpp" /> <ClCompile Include="main.cpp" />
<ClCompile Include="mem_ctx\mem_ctx.cpp" /> <ClCompile Include="ptm_ctx\ptm_ctx.cpp" />
<ClCompile Include="set_mgr\set_mgr.cpp" /> <ClCompile Include="set_mgr\set_mgr.cpp" />
<ClCompile Include="vdm_ctx\vdm_ctx.cpp" /> <ClCompile Include="vdm_ctx\vdm_ctx.cpp" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClInclude Include="injector_ctx\injector_ctx.hpp" /> <ClInclude Include="injector_ctx\injector_ctx.hpp" />
<ClInclude Include="mem_ctx\mem_ctx.hpp" /> <ClInclude Include="ptm_ctx\ptm_ctx.hpp" />
<ClInclude Include="set_mgr\set_mgr.hpp" /> <ClInclude Include="set_mgr\set_mgr.hpp" />
<ClInclude Include="util\loadup.hpp" /> <ClInclude Include="util\loadup.hpp" />
<ClInclude Include="util\nt.hpp" /> <ClInclude Include="util\nt.hpp" />

@ -23,15 +23,15 @@
<ClCompile Include="vdm_ctx\vdm_ctx.cpp"> <ClCompile Include="vdm_ctx\vdm_ctx.cpp">
<Filter>Source Files</Filter> <Filter>Source Files</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="mem_ctx\mem_ctx.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="injector_ctx\injector_ctx.cpp"> <ClCompile Include="injector_ctx\injector_ctx.cpp">
<Filter>Source Files</Filter> <Filter>Source Files</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="set_mgr\set_mgr.cpp"> <ClCompile Include="set_mgr\set_mgr.cpp">
<Filter>Source Files</Filter> <Filter>Source Files</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="ptm_ctx\ptm_ctx.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClInclude Include="vdm\raw_driver.hpp"> <ClInclude Include="vdm\raw_driver.hpp">
@ -52,15 +52,15 @@
<ClInclude Include="util\util.hpp"> <ClInclude Include="util\util.hpp">
<Filter>Header Files\util</Filter> <Filter>Header Files\util</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="mem_ctx\mem_ctx.hpp">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="injector_ctx\injector_ctx.hpp"> <ClInclude Include="injector_ctx\injector_ctx.hpp">
<Filter>Header Files</Filter> <Filter>Header Files</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="set_mgr\set_mgr.hpp"> <ClInclude Include="set_mgr\set_mgr.hpp">
<Filter>Header Files</Filter> <Filter>Header Files</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="ptm_ctx\ptm_ctx.hpp">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ResourceCompile Include="icon.rc"> <ResourceCompile Include="icon.rc">

@ -2,11 +2,7 @@
namespace vdm namespace vdm
{ {
vdm_ctx::vdm_ctx vdm_ctx::vdm_ctx(read_phys_t& read_func, write_phys_t& write_func)
(
std::function<decltype(vdm::read_phys)>& read_func,
std::function<decltype(vdm::write_phys)>& write_func
)
: :
read_phys(read_func), read_phys(read_func),
write_phys(write_func) write_phys(write_func)
@ -41,12 +37,12 @@ namespace vdm
search_thread.join(); search_thread.join();
} }
void vdm_ctx::set_read(std::function<decltype(vdm::read_phys)>& read_func) void vdm_ctx::set_read(read_phys_t& read_func)
{ {
this->read_phys = read_func; this->read_phys = read_func;
} }
void vdm_ctx::set_write(std::function<decltype(vdm::write_phys)>& write_func) void vdm_ctx::set_write(write_phys_t& write_func)
{ {
this->write_phys = write_func; this->write_phys = write_func;
} }

@ -26,14 +26,9 @@ namespace vdm
class vdm_ctx class vdm_ctx
{ {
public: public:
vdm_ctx explicit vdm_ctx(read_phys_t& read_func, write_phys_t& write_func);
( void set_read(read_phys_t& read_func);
std::function<decltype(vdm::read_phys)>& read_func, void set_write(write_phys_t& write_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
@ -83,12 +78,12 @@ namespace vdm
} }
template <class T> template <class T>
__forceinline void wkm(std::uintptr_t addr, const T& value) __forceinline auto wkm(std::uintptr_t addr, const T& value) -> bool
{ {
static const auto ntoskrnl_memcpy = static const auto ntoskrnl_memcpy =
util::get_kmodule_export("ntoskrnl.exe", "memcpy"); util::get_kmodule_export("ntoskrnl.exe", "memcpy");
this->syscall<decltype(&memcpy)>( return this->syscall<decltype(&memcpy)>(
ntoskrnl_memcpy, (void*)addr, &value, sizeof T); ntoskrnl_memcpy, (void*)addr, &value, sizeof T);
} }
@ -118,11 +113,11 @@ namespace vdm
); );
return peproc; return peproc;
} }
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;
read_phys_t read_phys;
std::function<decltype(vdm::read_phys)> read_phys; write_phys_t write_phys;
std::function<decltype(vdm::write_phys)> write_phys;
}; };
} }
Loading…
Cancel
Save