|
|
|
@ -1,8 +1,8 @@
|
|
|
|
|
#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),
|
|
|
|
|
dirbase(get_dirbase(*v_ctx, pid)),
|
|
|
|
@ -14,8 +14,13 @@ namespace nasa
|
|
|
|
|
get_dirbase(*v_ctx, GetCurrentProcessId())));
|
|
|
|
|
|
|
|
|
|
for (auto idx = 100u; idx > 0u; --idx)
|
|
|
|
|
{
|
|
|
|
|
if (!v_ctx->rkm<pml4e>(current_pml4 + (idx * sizeof pml4e)).present)
|
|
|
|
|
{
|
|
|
|
|
this->pml4e_index = idx;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// allocate a pdpt
|
|
|
|
|
this->new_pdpt.second =
|
|
|
|
@ -84,30 +89,29 @@ namespace nasa
|
|
|
|
|
new_pt_entries.pt.second.pfn << 12);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
mem_ctx::~mem_ctx()
|
|
|
|
|
ptm_ctx::~ptm_ctx()
|
|
|
|
|
{
|
|
|
|
|
const auto pml4 =
|
|
|
|
|
reinterpret_cast<ppml4e>(
|
|
|
|
|
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;
|
|
|
|
|
if (pte_index >= 511)
|
|
|
|
|
if (pte_index > 511)
|
|
|
|
|
{
|
|
|
|
|
++pde_index;
|
|
|
|
|
pte_index = 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (pde_index >= 511)
|
|
|
|
|
if (pde_index > 511)
|
|
|
|
|
{
|
|
|
|
|
++pdpte_index;
|
|
|
|
|
pde_index = 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (pdpte_index >= 511)
|
|
|
|
|
if (pdpte_index > 511)
|
|
|
|
|
pdpte_index = 0;
|
|
|
|
|
|
|
|
|
|
pdpte new_pdpte = { NULL };
|
|
|
|
@ -115,7 +119,6 @@ namespace nasa
|
|
|
|
|
new_pdpte.rw = true;
|
|
|
|
|
new_pdpte.pfn = reinterpret_cast<std::uintptr_t>(new_pd.first) >> 12;
|
|
|
|
|
new_pdpte.user_supervisor = true;
|
|
|
|
|
new_pdpte.accessed = true;
|
|
|
|
|
|
|
|
|
|
// set pdpte entry
|
|
|
|
|
*reinterpret_cast<pdpte*>(new_pdpt.second + pdpte_index) = new_pdpte;
|
|
|
|
@ -125,7 +128,6 @@ namespace nasa
|
|
|
|
|
new_pde.rw = true;
|
|
|
|
|
new_pde.pfn = reinterpret_cast<std::uintptr_t>(new_pt.first) >> 12;
|
|
|
|
|
new_pde.user_supervisor = true;
|
|
|
|
|
new_pde.accessed = true;
|
|
|
|
|
|
|
|
|
|
// set pde entry
|
|
|
|
|
*reinterpret_cast<pde*>(new_pd.second + pde_index) = new_pde;
|
|
|
|
@ -135,7 +137,6 @@ namespace nasa
|
|
|
|
|
new_pte.rw = true;
|
|
|
|
|
new_pte.pfn = reinterpret_cast<std::uintptr_t>(addr) >> 12;
|
|
|
|
|
new_pte.user_supervisor = true;
|
|
|
|
|
new_pte.accessed = true;
|
|
|
|
|
|
|
|
|
|
// set pte entry
|
|
|
|
|
*reinterpret_cast<pte*>(new_pt.second + pte_index) = new_pte;
|
|
|
|
@ -145,7 +146,7 @@ namespace nasa
|
|
|
|
|
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
|
|
|
|
|
virt_addr_t new_addr;
|
|
|
|
@ -163,25 +164,23 @@ namespace nasa
|
|
|
|
|
}
|
|
|
|
|
__except (EXCEPTION_EXECUTE_HANDLER)
|
|
|
|
|
{
|
|
|
|
|
// loop until the TLB has flushed...
|
|
|
|
|
while (true)
|
|
|
|
|
// 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)
|
|
|
|
|
{
|
|
|
|
|
__try
|
|
|
|
|
{
|
|
|
|
|
*(std::uint8_t*)new_addr.value = *(std::uint8_t*)new_addr.value;
|
|
|
|
|
return new_addr.value;
|
|
|
|
|
}
|
|
|
|
|
__except(EXCEPTION_EXECUTE_HANDLER)
|
|
|
|
|
{}
|
|
|
|
|
|
|
|
|
|
while (!SwitchToThread())
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return {};
|
|
|
|
|
return new_addr.value;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void* mem_ctx::get_dirbase(vdm::vdm_ctx& v_ctx, DWORD pid)
|
|
|
|
|
void* ptm_ctx::get_dirbase(vdm::vdm_ctx& v_ctx, DWORD pid)
|
|
|
|
|
{
|
|
|
|
|
const auto peproc =
|
|
|
|
|
reinterpret_cast<std::uint64_t>(
|
|
|
|
@ -191,7 +190,7 @@ namespace nasa
|
|
|
|
|
v_ctx.rkm<pte>(peproc + 0x28).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)
|
|
|
|
|
return false;
|
|
|
|
@ -233,7 +232,7 @@ namespace nasa
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
auto mem_ctx::get_pte(void* addr, bool use_hyperspace) -> std::pair<ppte, pte>
|
|
|
|
|
auto ptm_ctx::get_pte(void* addr, bool use_hyperspace) -> std::pair<ppte, pte>
|
|
|
|
|
{
|
|
|
|
|
if (!dirbase || !addr)
|
|
|
|
|
return { {}, {} };
|
|
|
|
@ -245,84 +244,94 @@ namespace nasa
|
|
|
|
|
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)
|
|
|
|
|
return;
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
if (use_hyperspace)
|
|
|
|
|
v_ctx->wkm(v_ctx->get_virtual(reinterpret_cast<std::uintptr_t>(addr)), pte);
|
|
|
|
|
else
|
|
|
|
|
write_phys(addr, pte);
|
|
|
|
|
return v_ctx->wkm(
|
|
|
|
|
v_ctx->get_virtual(
|
|
|
|
|
reinterpret_cast<std::uintptr_t>(addr)), pte);
|
|
|
|
|
|
|
|
|
|
return write_phys(addr, pte);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
auto mem_ctx::get_pde(void* addr, bool use_hyperspace) -> std::pair<ppde, pde>
|
|
|
|
|
auto ptm_ctx::get_pde(void* addr, bool use_hyperspace) -> std::pair<ppde, pde>
|
|
|
|
|
{
|
|
|
|
|
if (!dirbase || !addr)
|
|
|
|
|
return {};
|
|
|
|
|
return { {}, {} };
|
|
|
|
|
|
|
|
|
|
pt_entries entries;
|
|
|
|
|
if ((use_hyperspace ? hyperspace_entries(entries, addr) : (bool)virt_to_phys(entries, addr)))
|
|
|
|
|
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 (!dirbase || !addr)
|
|
|
|
|
return;
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
if (use_hyperspace)
|
|
|
|
|
v_ctx->wkm(v_ctx->get_virtual(reinterpret_cast<std::uintptr_t>(addr)), pde);
|
|
|
|
|
else
|
|
|
|
|
write_phys(addr, pde);
|
|
|
|
|
return v_ctx->wkm(
|
|
|
|
|
v_ctx->get_virtual(
|
|
|
|
|
reinterpret_cast<std::uintptr_t>(addr)), pde);
|
|
|
|
|
|
|
|
|
|
return write_phys(addr, pde);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
auto mem_ctx::get_pdpte(void* addr, bool use_hyperspace) -> std::pair<ppdpte, pdpte>
|
|
|
|
|
auto ptm_ctx::get_pdpte(void* addr, bool use_hyperspace) -> std::pair<ppdpte, pdpte>
|
|
|
|
|
{
|
|
|
|
|
if (!dirbase || !addr)
|
|
|
|
|
return {};
|
|
|
|
|
return { {}, {} };
|
|
|
|
|
|
|
|
|
|
pt_entries entries;
|
|
|
|
|
if ((use_hyperspace ? hyperspace_entries(entries, addr) : (bool)virt_to_phys(entries, addr)))
|
|
|
|
|
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 (!dirbase || !addr)
|
|
|
|
|
return;
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
if (use_hyperspace)
|
|
|
|
|
v_ctx->wkm(v_ctx->get_virtual(reinterpret_cast<std::uintptr_t>(addr)), pdpte);
|
|
|
|
|
else
|
|
|
|
|
write_phys(addr, pdpte);
|
|
|
|
|
return v_ctx->wkm(
|
|
|
|
|
v_ctx->get_virtual(
|
|
|
|
|
reinterpret_cast<std::uintptr_t>(addr)), pdpte);
|
|
|
|
|
|
|
|
|
|
return write_phys(addr, pdpte);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
auto mem_ctx::get_pml4e(void* addr, bool use_hyperspace) -> std::pair<ppml4e, pml4e>
|
|
|
|
|
auto ptm_ctx::get_pml4e(void* addr, bool use_hyperspace) -> std::pair<ppml4e, pml4e>
|
|
|
|
|
{
|
|
|
|
|
if (!dirbase || !addr)
|
|
|
|
|
return {};
|
|
|
|
|
return { {}, {} };
|
|
|
|
|
|
|
|
|
|
pt_entries entries;
|
|
|
|
|
if ((use_hyperspace ? hyperspace_entries(entries, addr) : (bool)virt_to_phys(entries, addr)))
|
|
|
|
|
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 (!dirbase || !addr)
|
|
|
|
|
return;
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
if (use_hyperspace)
|
|
|
|
|
v_ctx->wkm(v_ctx->get_virtual(reinterpret_cast<std::uintptr_t>(addr)), pml4e);
|
|
|
|
|
else
|
|
|
|
|
write_phys(addr, pml4e);
|
|
|
|
|
return v_ctx->wkm(
|
|
|
|
|
v_ctx->get_virtual(
|
|
|
|
|
reinterpret_cast<std::uintptr_t>(addr)), pml4e);
|
|
|
|
|
|
|
|
|
|
return write_phys(addr, pml4e);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
auto mem_ctx::read_virtual(void* buffer, void* addr, std::size_t size) -> std::pair<void*, void*>
|
|
|
|
|
auto ptm_ctx::read_virtual(void* buffer, void* addr, std::size_t size) -> std::pair<void*, void*>
|
|
|
|
|
{
|
|
|
|
|
if (!buffer || !addr || !size || !dirbase)
|
|
|
|
|
return {};
|
|
|
|
@ -364,7 +373,7 @@ namespace nasa
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
auto mem_ctx::write_virtual(void* buffer, void* addr, std::size_t size) -> std::pair<void*, void*>
|
|
|
|
|
auto ptm_ctx::write_virtual(void* buffer, void* addr, std::size_t size) -> std::pair<void*, void*>
|
|
|
|
|
{
|
|
|
|
|
if (!buffer || !addr || !size || !dirbase)
|
|
|
|
|
return {};
|
|
|
|
@ -406,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)
|
|
|
|
|
return false;
|
|
|
|
@ -423,7 +432,7 @@ namespace nasa
|
|
|
|
|
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)
|
|
|
|
|
return false;
|
|
|
|
@ -440,7 +449,7 @@ namespace nasa
|
|
|
|
|
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 || !dirbase)
|
|
|
|
|
return {};
|