Skip to content

Commit

Permalink
added helper functions in introspection.h.
Browse files Browse the repository at this point in the history
  • Loading branch information
jonomango committed May 17, 2022
1 parent df81495 commit c9fd80b
Show file tree
Hide file tree
Showing 6 changed files with 117 additions and 8 deletions.
44 changes: 36 additions & 8 deletions hv/hv.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,19 +7,23 @@ namespace hv {

hypervisor ghv;

// function prototype doesn't really matter
// since we never call this function anyways
extern "C" NTKERNELAPI void PsGetCurrentThreadProcess();

// dynamically find the offsets for various kernel structures
static bool find_offsets() {
// TODO: maybe dont hardcode this...
ghv.kprocess_directory_table_base_offset = 0x28;
ghv.kpcr_pcrb_offset = 0x180;
ghv.kprcb_current_thread_offset = 0x8;
ghv.kapc_state_process_offset = 0x20;

ghv.system_eprocess = reinterpret_cast<uint8_t*>(PsInitialSystemProcess);

DbgPrint("[hv] System EPROCESS = 0x%zX.\n",
reinterpret_cast<size_t>(ghv.system_eprocess));

// TODO: maybe dont hardcode this...
ghv.kprocess_directory_table_base_offset = 0x28;

DbgPrint("[hv] KPROCESS::DirectoryTableBase offset = 0x%zX.\n",
ghv.kprocess_directory_table_base_offset);

auto const ps_get_process_id = reinterpret_cast<uint8_t*>(PsGetProcessId);

// mov rax, [rcx + OFFSET]
Expand All @@ -28,7 +32,7 @@ static bool find_offsets() {
ps_get_process_id[1] != 0x8B ||
ps_get_process_id[2] != 0x81 ||
ps_get_process_id[7] != 0xC3) {
DbgPrint("[hv] Failed to get offset of EPROCESS::UniqueProcessId.\n");
DbgPrint("[hv] Failed to get EPROCESS::UniqueProcessId offset.\n");
return false;
}

Expand All @@ -38,6 +42,27 @@ static bool find_offsets() {
DbgPrint("[hv] EPROCESS::UniqueProcessId offset = 0x%zX.\n",
ghv.eprocess_unique_process_id_offset);

auto const ps_get_current_thread_process =
reinterpret_cast<uint8_t*>(PsGetCurrentThreadProcess);

// mov rax, gs:188h
// mov rax, [rax + OFFSET]
// retn
if (ps_get_current_thread_process[0] != 0x65 ||
ps_get_current_thread_process[1] != 0x48 ||
ps_get_current_thread_process[2] != 0x8B ||
ps_get_current_thread_process[3] != 0x04 ||
ps_get_current_thread_process[4] != 0x25 ||
ps_get_current_thread_process[9] != 0x48 ||
ps_get_current_thread_process[10] != 0x8B ||
ps_get_current_thread_process[11] != 0x80) {
DbgPrint("[hv] Failed to get KAPC_STATE::Process offset.\n");
return false;
}

ghv.kapc_state_process_offset =
*reinterpret_cast<uint32_t*>(ps_get_current_thread_process + 12);

// store the System cr3 value (found in the System EPROCESS structure)
ghv.system_cr3 = *reinterpret_cast<cr3*>(ghv.system_eprocess +
ghv.kprocess_directory_table_base_offset);
Expand Down Expand Up @@ -70,7 +95,10 @@ static bool create() {

DbgPrint("[hv] Allocated %u VCPUs (0x%zX bytes).\n", ghv.vcpu_count, arr_size);

find_offsets();
if (!find_offsets()) {
DbgPrint("[hv] Failed to find offsets.\n");
return false;
}

prepare_host_page_tables();

Expand Down
4 changes: 4 additions & 0 deletions hv/hv.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,10 @@ struct hypervisor {
// windows specific offsets D:
uint64_t kprocess_directory_table_base_offset;
uint64_t eprocess_unique_process_id_offset;
uint64_t kpcr_pcrb_offset;
uint64_t kprcb_current_thread_offset;
uint64_t kthread_apc_state_offset;
uint64_t kapc_state_process_offset;
};

// global instance of the hypervisor
Expand Down
2 changes: 2 additions & 0 deletions hv/hv.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,7 @@
<ClInclude Include="hypercalls.h" />
<ClInclude Include="idt.h" />
<ClInclude Include="interrupt-handlers.h" />
<ClInclude Include="introspection.h" />
<ClInclude Include="mm.h" />
<ClInclude Include="mtrr.h" />
<ClInclude Include="page-tables.h" />
Expand All @@ -146,6 +147,7 @@
<ClCompile Include="hv.cpp" />
<ClCompile Include="hypercalls.cpp" />
<ClCompile Include="idt.cpp" />
<ClCompile Include="introspection.cpp" />
<ClCompile Include="main.cpp" />
<ClCompile Include="mm.cpp" />
<ClCompile Include="mtrr.cpp" />
Expand Down
6 changes: 6 additions & 0 deletions hv/hv.vcxproj.filters
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,9 @@
<ClInclude Include="vmcs.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="introspection.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="exit-handlers.cpp">
Expand Down Expand Up @@ -120,6 +123,9 @@
<ClCompile Include="vmcs.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="introspection.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<MASM Include="interrupt-handlers.asm">
Expand Down
50 changes: 50 additions & 0 deletions hv/introspection.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
#include "introspection.h"
#include "hv.h"

namespace hv {

// TODO: translate using gva2hva instead of directly reading guest memory...

// get the KPCR of the current guest (the pointer should stay constant per-vcpu)
PKPCR current_guest_kpcr() {
// GS base holds the KPCR when in ring-0
if (current_guest_cpl() == 0)
return reinterpret_cast<PKPCR>(vmx_vmread(VMCS_GUEST_GS_BASE));

// when in ring-3, the GS_SWAP contains the KPCR
return reinterpret_cast<PKPCR>(__readmsr(IA32_KERNEL_GS_BASE));
}

// get the ETHREAD of the current guest
PETHREAD current_guest_ethread() {
// KPCR
auto const kpcr = current_guest_kpcr();

if (!kpcr)
return nullptr;

// KPCR::Prcb
auto const kprcb = reinterpret_cast<uint8_t*>(kpcr)
+ ghv.kpcr_pcrb_offset;

// KPCRB::CurrentThread
return *reinterpret_cast<PETHREAD*>(kprcb
+ ghv.kprcb_current_thread_offset);
}

// get the EPROCESS of the current guest
PEPROCESS current_guest_eprocess() {
// ETHREAD (KTHREAD is first field as well)
auto const ethread = current_guest_ethread();

// KTHREAD::ApcState
auto const kapc_state = reinterpret_cast<uint8_t*>(ethread)
+ ghv.kthread_apc_state_offset;

// KAPC_STATE::Process
return *reinterpret_cast<PEPROCESS*>(kapc_state
+ ghv.kapc_state_process_offset);
}

} // namespace hv

19 changes: 19 additions & 0 deletions hv/introspection.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
#pragma once

#include "vmx.h"

#include <ntddk.h>

namespace hv {

// get the KPCR of the current guest (the pointer should stay constant per-vcpu)
PKPCR current_guest_kpcr();

// get the ETHREAD of the current guest
PETHREAD current_guest_ethread();

// get the EPROCESS of the current guest
PEPROCESS current_guest_eprocess();

} // namespace hv

0 comments on commit c9fd80b

Please sign in to comment.