Skip to content

Commit

Permalink
Extremely fast & unsafe physmem resolver
Browse files Browse the repository at this point in the history
  • Loading branch information
HoShiMin committed Jun 7, 2020
1 parent 8903dd4 commit 3d72dd1
Show file tree
Hide file tree
Showing 10 changed files with 352 additions and 65 deletions.
6 changes: 3 additions & 3 deletions CommonTypes/PTE.h
Original file line number Diff line number Diff line change
Expand Up @@ -197,7 +197,7 @@ union PDPE {
unsigned long long PCD : 1; // Page-Level Cache Disable
unsigned long long A : 1; // Accessed
unsigned long long Reserved0 : 1;
unsigned long long PS : 1; // PageSize == 0
unsigned long long PS : 1; // PageSize
unsigned long long Reserved1 : 1;
unsigned long long AVL : 3; // Available to software
unsigned long long Reserved3 : 51;
Expand Down Expand Up @@ -299,7 +299,7 @@ union PDE {
unsigned long long PCD : 1; // Page-Level Cache Disable
unsigned long long A : 1; // Accessed
unsigned long long Reserved0 : 1;
unsigned long long PS : 1; // PageSize == 0
unsigned long long PS : 1; // PageSize
unsigned long long Reserved1 : 1;
unsigned long long AVL : 3; // Available to software
unsigned long long Reserved2 : 51;
Expand Down Expand Up @@ -349,7 +349,7 @@ union PDE {
unsigned long long PCD : 1; // Page-Level Cache Disable
unsigned long long A : 1; // Accessed
unsigned long long Reserved0 : 1;
unsigned long long PS : 1; // PageSize == 0
unsigned long long PS : 1; // PageSize
unsigned long long Reserved1 : 1;
unsigned long long AVL : 3; // Available to software
unsigned long long Reserved2 : 51;
Expand Down
254 changes: 220 additions & 34 deletions Kernel-Bridge/API/Hypervisor.cpp

Large diffs are not rendered by default.

67 changes: 44 additions & 23 deletions Kernel-Bridge/API/PteUtils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@ namespace Pte {
#endif

_IRQL_requires_max_(APC_LEVEL)
BOOLEAN GetPageTables(PVOID Address, OUT PAGE_TABLES_INFO* Info) {
BOOLEAN GetPageTables(PVOID Address, OUT PAGE_TABLES_INFO* Info)
{
if (!Info) return FALSE;
*Info = {};

Expand All @@ -40,20 +41,24 @@ namespace Pte {
PVOID64 PdpePhys = reinterpret_cast<PVOID64>(PFN_TO_PAGE(Info->Pml4e->x64.Generic.PDP) + Va.x64.Generic.PageDirectoryPointerOffset * sizeof(PDPE::x64));
Info->Pdpe = reinterpret_cast<PDPE*>(GetVirtualForPhysical(PdpePhys));
if (!Info->Pdpe) return FALSE;
if (Info->Pdpe->x64.Generic.PS) {
if (Info->Pdpe->x64.Generic.PS)
{
// Page size = 1 Gb:
if (!Info->Pdpe->x64.PageSize.Page1Gb.P) return FALSE;
Info->Type = PAGE_TABLES_INFO::pt64Page1Gb;
}
else {
else
{
PVOID64 PdePhys = reinterpret_cast<PVOID64>(PFN_TO_PAGE(Info->Pdpe->x64.NonPageSize.Generic.PD) + Va.x64.NonPageSize.Generic.PageDirectoryOffset * sizeof(PDE::x64));
Info->Pde = reinterpret_cast<PDE*>(GetVirtualForPhysical(PdePhys));
if (!Info->Pde) return FALSE;
if (Info->Pde->x64.Generic.PS) {
if (Info->Pde->x64.Generic.PS)
{
// Page size = 2 Mb:
Info->Type = PAGE_TABLES_INFO::pt64Page2Mb;
}
else {
else
{
// Page size = 4 Kb:
Info->Type = PAGE_TABLES_INFO::pt64Page4Kb;

Expand All @@ -63,7 +68,8 @@ namespace Pte {
}
}
#else
if (Cr4.x32.Bitmap.PAE) {
if (Cr4.x32.Bitmap.PAE)
{
PVOID64 PdpePhys = reinterpret_cast<PVOID64>(PFN_TO_PDP_PAE(Cr3.x32.Pae.PDP) + Va.x32.Pae.Generic.PageDirectoryPointerOffset * sizeof(PDPE::x32));
Info->Pdpe = reinterpret_cast<PDPE*>(GetVirtualForPhysical(PdpePhys));
if (!Info->Pdpe) return FALSE;
Expand All @@ -72,11 +78,13 @@ namespace Pte {
PVOID64 PdePhys = reinterpret_cast<PVOID64>(PFN_TO_PAGE(Info->Pdpe->x32.Pae.Generic.PD) + Va.x32.Pae.Generic.PageDirectoryOffset * sizeof(PDE::x32));
Info->Pde = reinterpret_cast<PDE*>(GetVirtualForPhysical(PdePhys));
if (!Info->Pde) return FALSE;
if (!Info->Pde->x32.Pae.Generic.PS) {
if (!Info->Pde->x32.Pae.Generic.PS)
{
// Page size = 2 Mb:
Info->Type = PAGE_TABLES_INFO::pt32PaePage2Mb;
}
else {
else
{
// Page size = 4 Kb:
Info->Type = PAGE_TABLES_INFO::pt32PaePage4Kb;

Expand All @@ -86,17 +94,21 @@ namespace Pte {
if (!Info->Pte) return FALSE;
}
}
else {
if (Cr4.x32.Bitmap.PSE) {
else
{
if (Cr4.x32.Bitmap.PSE)
{
PVOID64 PdePhys = reinterpret_cast<PVOID64>(PFN_TO_PAGE(Cr3.x32.NonPae.PD) + Va.x32.NonPae.Page4Kb.PageDirectoryOffset * sizeof(PDE::x32));
Info->Pde = reinterpret_cast<PDE*>(GetVirtualForPhysical(PdePhys));
if (!Info->Pde) return FALSE;

if (Info->Pde->x32.NonPae.Generic.PS) {
if (Info->Pde->x32.NonPae.Generic.PS)
{
// Page size = 4 Mb:
Info->Type = PAGE_TABLES_INFO::pt32NonPaePage4Mb;
}
else {
else
{
// Page size = 4 Kb:
Info->Type = PAGE_TABLES_INFO::pt32NonPaePage4Kb;

Expand All @@ -107,7 +119,8 @@ namespace Pte {
if (!Info->Pte) return FALSE;
}
}
else {
else
{
// Page size = 4 Kb:
Info->Type = PAGE_TABLES_INFO::pt32NonPaePage4Kb;

Expand All @@ -126,7 +139,8 @@ namespace Pte {
}

_IRQL_requires_max_(APC_LEVEL)
BOOLEAN TriggerCopyOnWrite(OPTIONAL PEPROCESS Process, PVOID Address, OPTIONAL OUT PULONG PageSize) {
BOOLEAN TriggerCopyOnWrite(OPTIONAL PEPROCESS Process, PVOID Address, OPTIONAL OUT PULONG PageSize)
{
BOOLEAN NeedToAttach = Process && Process != PsGetCurrentProcess();
KAPC_STATE ApcState;
if (NeedToAttach)
Expand All @@ -135,7 +149,8 @@ namespace Pte {
BOOLEAN Status = FALSE;
PAGE_TABLES_INFO Info = {};
Status = GetPageTables(Address, &Info);
if (Status) __try {
if (Status) __try
{
// AVL is a 3-bit field:
// AVL:CopyOnWrite : 1
// AVL:Unused : 1
Expand All @@ -145,7 +160,8 @@ namespace Pte {

if (PageSize) *PageSize = 0;

switch (Info.Type) {
switch (Info.Type)
{
case PAGE_TABLES_INFO::pt32NonPaePage4Kb:
// PDE -> PTE -> PA:
if (PageSize) *PageSize = 4096;
Expand Down Expand Up @@ -193,7 +209,8 @@ namespace Pte {
__invlpg(Address); // Reset the TLB
*reinterpret_cast<unsigned char*>(Address) = *reinterpret_cast<unsigned char*>(Address);
}
__except (EXCEPTION_EXECUTE_HANDLER) {
__except (EXCEPTION_EXECUTE_HANDLER)
{
Status = FALSE;
}

Expand All @@ -204,11 +221,12 @@ namespace Pte {
}

_IRQL_requires_max_(APC_LEVEL)
BOOLEAN IsPagePresent(PVOID Address, OPTIONAL OUT PULONG PageSize) {
BOOLEAN IsPagePresent(PVOID Address, OPTIONAL OUT PULONG PageSize)
{
BOOLEAN IsPresent = FALSE;
PAGE_TABLES_INFO Info = {};
if (GetPageTables(Address, &Info)) __try {

if (GetPageTables(Address, &Info)) __try
{
if (PageSize) *PageSize = 0;

switch (Info.Type) {
Expand Down Expand Up @@ -249,15 +267,17 @@ namespace Pte {
break;
}
}
__except (EXCEPTION_EXECUTE_HANDLER) {
__except (EXCEPTION_EXECUTE_HANDLER)
{
IsPresent = FALSE;
}

return IsPresent;
}

_IRQL_requires_max_(APC_LEVEL)
BOOLEAN IsProcessPagePresent(OPTIONAL PEPROCESS Process, PVOID Address, OPTIONAL OUT PULONG PageSize) {
BOOLEAN IsProcessPagePresent(OPTIONAL PEPROCESS Process, PVOID Address, OPTIONAL OUT PULONG PageSize)
{
if (!Process || Process == PsGetCurrentProcess())
return IsPagePresent(Address, PageSize);
KAPC_STATE ApcState;
Expand All @@ -268,7 +288,8 @@ namespace Pte {
}

_IRQL_requires_max_(APC_LEVEL)
BOOLEAN IsMemoryRangePresent(OPTIONAL PEPROCESS Process, PVOID Address, SIZE_T Size) {
BOOLEAN IsMemoryRangePresent(OPTIONAL PEPROCESS Process, PVOID Address, SIZE_T Size)
{
if (!Size) return FALSE;

BOOLEAN NeedToAttach = Process && Process != PsGetCurrentProcess();
Expand Down
3 changes: 2 additions & 1 deletion Kernel-Bridge/API/PteUtils.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#pragma once

namespace Pte {
namespace Pte
{
struct PAGE_TABLES_INFO {
PML4E* Pml4e;
PDPE* Pdpe;
Expand Down
46 changes: 46 additions & 0 deletions Kernel-Bridge/API/Stopwatch.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
#include "Stopwatch.h"

#include <ntifs.h>

Stopwatch::Stopwatch()
: m_begin(0)
, m_end(0)
, m_freq(0)
{
KeQueryPerformanceCounter(reinterpret_cast<LARGE_INTEGER*>(&m_freq));
}

Stopwatch::Stopwatch(bool init)
: m_begin(0)
, m_end(0)
, m_freq(0)
{
if (init)
{
start();
}
}

void Stopwatch::reset()
{
m_begin = 0;
m_end = 0;
KeQueryPerformanceCounter(reinterpret_cast<LARGE_INTEGER*>(&m_freq));
}

void Stopwatch::start()
{
m_begin = KeQueryPerformanceCounter(reinterpret_cast<LARGE_INTEGER*>(&m_freq)).QuadPart;
m_end = m_begin;
}

float Stopwatch::stop()
{
m_end = KeQueryPerformanceCounter(NULL).QuadPart;
return delta();
}

float Stopwatch::delta()
{
return static_cast<float>(m_end - m_begin) / m_freq;
}
19 changes: 19 additions & 0 deletions Kernel-Bridge/API/Stopwatch.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
#pragma once

class Stopwatch
{
protected:
unsigned long long m_begin, m_end;
unsigned long long m_freq;

public:
Stopwatch();
Stopwatch(bool init);

void reset();

void start();
float stop();

float delta();
};
3 changes: 3 additions & 0 deletions Kernel-Bridge/API/VMM.asm
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,7 @@ __invvpid PROC PUBLIC
__invvpid ENDP

VmxVmmRun PROC PUBLIC
cli
PUSHAQ
mov rcx, [rsp + GPR_CONTEXT_SIZE + 16]
mov rdx, rsp
Expand All @@ -217,6 +218,7 @@ VmxVmmRun PROC PUBLIC
jz VmmExit

POPAQ
sti
vmresume

VmmExit:
Expand All @@ -230,6 +232,7 @@ VmmExit:

mov rsp, rcx
mov ecx, CPUID_VMM_SHUTDOWN ; Signature that says about the VM shutdown
sti
jmp rbx
VmxVmmRun ENDP

Expand Down
2 changes: 2 additions & 0 deletions Kernel-Bridge/Kernel-Bridge.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
<ClCompile Include="API\PteUtils.cpp" />
<ClCompile Include="API\SectionsUtils.cpp" />
<ClCompile Include="API\Signatures.cpp" />
<ClCompile Include="API\Stopwatch.cpp" />
<ClCompile Include="Kernel-Bridge\DriverEvents.cpp" />
<ClCompile Include="Kernel-Bridge\FilterCallbacks.cpp" />
<ClCompile Include="Kernel-Bridge\IOCTLHandlers.cpp" />
Expand Down Expand Up @@ -283,6 +284,7 @@
<ClInclude Include="API\RAII.h" />
<ClInclude Include="API\SectionsUtils.h" />
<ClInclude Include="API\Signatures.h" />
<ClInclude Include="API\Stopwatch.h" />
<ClInclude Include="API\StringsAPI.h" />
<ClInclude Include="Kernel-Bridge\DriverEvents.h" />
<ClInclude Include="Kernel-Bridge\FilterCallbacks.h" />
Expand Down
6 changes: 6 additions & 0 deletions Kernel-Bridge/Kernel-Bridge.vcxproj.filters
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,9 @@
<ClCompile Include="API\Callable.cpp">
<Filter>API</Filter>
</ClCompile>
<ClCompile Include="API\Stopwatch.cpp">
<Filter>API</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="Kernel-Bridge\FilterCallbacks.h">
Expand Down Expand Up @@ -226,6 +229,9 @@
<ClInclude Include="..\HookLib\HookLib\HookLib\HookLib.h">
<Filter>HookLib</Filter>
</ClInclude>
<ClInclude Include="API\Stopwatch.h">
<Filter>API</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<None Include="Exports.def">
Expand Down
11 changes: 7 additions & 4 deletions Kernel-Tests/Main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,8 @@
#include "SymParser.h"

#include <PTE.h>
#include "Registers.h"
#include <Registers.h>
#include <VMX.h>

#include <intrin.h>

Expand Down Expand Up @@ -279,9 +280,11 @@ void* GetFuncPtr(const void* Func)
__declspec(code_seg(".hidden")) unsigned int HiddenFunc()
{
printf("Called from hidden func!\n");
auto* Self = reinterpret_cast<PBYTE>(GetFuncPtr(HiddenFunc));
*Self = 0x55;
printf("Self memory: 0x%X\n", static_cast<unsigned int>(*Self));
for (unsigned int i = 0; i < 100; ++i)
{
volatile BYTE* Self = reinterpret_cast<PBYTE>(GetFuncPtr(HiddenFunc));
*Self = 0x55;
}
return 0x1EE7C0DE;
}

Expand Down

0 comments on commit 3d72dd1

Please sign in to comment.