1
0
mirror of https://github.com/momo5502/hypervisor.git synced 2025-07-03 01:31:51 +00:00

Compare commits

..

27 Commits

Author SHA1 Message Date
aab19ccb34 Merge pull request #13 from momo5502/dependabot/submodules/external/FindWDK-04b4151
Bump external/FindWDK from `6aaaaf4` to `04b4151`
2025-07-01 13:38:26 +02:00
4051223045 Bump external/FindWDK from 6aaaaf4 to 04b4151
Bumps [external/FindWDK](https://github.com/SergiusTheBest/FindWDK) from `6aaaaf4` to `04b4151`.
- [Commits](6aaaaf423a...04b4151f6d)

---
updated-dependencies:
- dependency-name: external/FindWDK
  dependency-version: 04b4151f6d6257554f2467edc0ff7f0c77074c7e
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-07-01 10:24:21 +00:00
dbc7b5422e Update ia32-doc submodules
Some checks failed
Build / Build binaries (debug) (push) Has been cancelled
Build / Build binaries (release) (push) Has been cancelled
2025-05-03 09:44:47 +02:00
de99750e53 Update build.yml
Some checks failed
Build / Build binaries (debug) (push) Has been cancelled
Build / Build binaries (release) (push) Has been cancelled
2024-11-24 15:23:54 +01:00
5a796c7aae Merge pull request #10 from momo5502/dependabot/github_actions/actions/upload-artifact-4
Bump actions/upload-artifact from 3 to 4
2024-11-24 15:22:47 +01:00
af3d08e791 Merge pull request #8 from momo5502/dependabot/github_actions/ilammy/msvc-dev-cmd-1.13.0
Bump ilammy/msvc-dev-cmd from 1.12.0 to 1.13.0
2024-11-24 15:22:29 +01:00
8da8fa7f8e Merge pull request #9 from momo5502/dependabot/github_actions/actions/checkout-4
Bump actions/checkout from 3 to 4
2024-11-24 15:22:18 +01:00
111b9c9a01 Bump actions/upload-artifact from 3 to 4
Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 3 to 4.
- [Release notes](https://github.com/actions/upload-artifact/releases)
- [Commits](https://github.com/actions/upload-artifact/compare/v3...v4)

---
updated-dependencies:
- dependency-name: actions/upload-artifact
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-11-24 14:18:12 +00:00
243ddeebdb Bump actions/checkout from 3 to 4
Bumps [actions/checkout](https://github.com/actions/checkout) from 3 to 4.
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/checkout/compare/v3...v4)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-11-24 14:18:10 +00:00
a6e484d9df Bump ilammy/msvc-dev-cmd from 1.12.0 to 1.13.0
Bumps [ilammy/msvc-dev-cmd](https://github.com/ilammy/msvc-dev-cmd) from 1.12.0 to 1.13.0.
- [Release notes](https://github.com/ilammy/msvc-dev-cmd/releases)
- [Commits](https://github.com/ilammy/msvc-dev-cmd/compare/v1.12.0...v1.13.0)

---
updated-dependencies:
- dependency-name: ilammy/msvc-dev-cmd
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-11-24 14:18:08 +00:00
b3dec2e80c Update dependabot.yml 2024-11-24 15:17:31 +01:00
4d68b0bb78 Merge pull request #7 from momo5502/dependabot/submodules/external/FindWDK-6aaaaf4
Some checks failed
Build / Build binaries (debug) (push) Has been cancelled
Build / Build binaries (release) (push) Has been cancelled
Bump external/FindWDK from `79a45e7` to `6aaaaf4`
2024-09-13 10:14:45 +02:00
79fd28ad7e Bump external/FindWDK from 79a45e7 to 6aaaaf4
Bumps [external/FindWDK](https://github.com/SergiusTheBest/FindWDK) from `79a45e7` to `6aaaaf4`.
- [Commits](79a45e7d70...6aaaaf423a)

---
updated-dependencies:
- dependency-name: external/FindWDK
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-09-09 09:30:54 +00:00
7073f7169a Merge pull request #6 from momo5502/dependabot/submodules/external/FindWDK-79a45e7
Some checks failed
Build / Build binaries (debug) (push) Has been cancelled
Build / Build binaries (release) (push) Has been cancelled
Bump external/FindWDK from `c941028` to `79a45e7`
2024-08-19 10:19:51 +02:00
b74f712975 Bump external/FindWDK from c941028 to 79a45e7
Bumps [external/FindWDK](https://github.com/SergiusTheBest/FindWDK) from `c941028` to `79a45e7`.
- [Commits](c941028b26...79a45e7d70)

---
updated-dependencies:
- dependency-name: external/FindWDK
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-08-14 09:05:19 +00:00
e9d4b3345c Try accessing the device first 2024-05-21 13:23:38 +02:00
55234c3504 Support disabling syscall hooking 2024-05-11 13:34:00 +02:00
69f66d11e4 Small cleanup and fixes 2024-05-11 10:43:41 +02:00
2d8de2835c Log explorer syscalls 2024-05-10 22:24:15 +02:00
b9c4d85bb0 String equality check 2024-05-10 22:23:47 +02:00
30873e4ebb More progress with syscall hooking 2024-05-10 22:15:15 +02:00
53c24b8325 Fix syscall hooking 2024-05-10 20:20:00 +02:00
0896133821 Add syscall handling 2024-05-10 17:26:57 +02:00
d5bf81d99b Prepare exception handling 2024-05-09 18:33:33 +02:00
761490c808 Prepare syscall hooking 2024-05-09 16:36:21 +02:00
c1d0a354c2 Fixes 2024-04-15 20:39:25 +02:00
08727330e1 Make exceptions copyable 2024-04-13 17:31:30 +02:00
13 changed files with 471 additions and 225 deletions

View File

@ -1,7 +1,12 @@
version: 2
updates:
- package-ecosystem: gitsubmodule
directory: "/"
schedule:
interval: daily
open-pull-requests-limit: 10
- package-ecosystem: gitsubmodule
directory: "/"
schedule:
interval: monthly
open-pull-requests-limit: 10
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: monthly

View File

@ -20,7 +20,7 @@ jobs:
- release
steps:
- name: Check out files
uses: actions/checkout@v3
uses: actions/checkout@v4
with:
submodules: true
fetch-depth: 0
@ -38,13 +38,10 @@ jobs:
uses: ammaraskar/msvc-problem-matcher@master
- name: Setup DevCmd
uses: ilammy/msvc-dev-cmd@v1.12.0
uses: ilammy/msvc-dev-cmd@v1.13.0
with:
arch: x64
- name: Setup Ninja
uses: ashutoshvarma/setup-ninja@master
- name: Configure CMake
run: cmake --preset=${{matrix.configuration}}
@ -52,7 +49,7 @@ jobs:
run: cmake --build --preset=${{matrix.configuration}}
- name: Upload ${{matrix.configuration}} binaries
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
with:
name: ${{matrix.configuration}} binaries
path: |

View File

@ -7,16 +7,6 @@
#include "memory.hpp"
#include "vmx.hpp"
#define MTRR_PAGE_SIZE 4096
#define MTRR_PAGE_MASK (~(MTRR_PAGE_SIZE-1))
#define ADDRMASK_EPT_PML1_OFFSET(_VAR_) ((_VAR_) & 0xFFFULL)
#define ADDRMASK_EPT_PML1_INDEX(_VAR_) (((_VAR_) & 0x1FF000ULL) >> 12)
#define ADDRMASK_EPT_PML2_INDEX(_VAR_) (((_VAR_) & 0x3FE00000ULL) >> 21)
#define ADDRMASK_EPT_PML3_INDEX(_VAR_) (((_VAR_) & 0x7FC0000000ULL) >> 30)
#define ADDRMASK_EPT_PML4_INDEX(_VAR_) (((_VAR_) & 0xFF8000000000ULL) >> 39)
namespace vmx
{
namespace
@ -301,7 +291,7 @@ namespace vmx
// --------------------------
epdpte temp_epdpte;
pml1 temp_epdpte{};
temp_epdpte.flags = 0;
temp_epdpte.read_access = 1;
temp_epdpte.write_access = 1;
@ -316,7 +306,7 @@ namespace vmx
// --------------------------
epde_2mb temp_epde{};
pml2 temp_epde{};
temp_epde.flags = 0;
temp_epde.read_access = 1;
temp_epde.write_access = 1;
@ -410,18 +400,18 @@ namespace vmx
}
const auto* pml2 = reinterpret_cast<pml2_ptr*>(pml2_entry);
auto* pml1 = this->find_pml1_table(pml2->page_frame_number * PAGE_SIZE);
if (!pml1)
auto* pml1_table = this->find_pml1_table(pml2->page_frame_number * PAGE_SIZE);
if (!pml1_table)
{
pml1 = static_cast<epte*>(memory::get_virtual_address(pml2->page_frame_number * PAGE_SIZE));
pml1_table = static_cast<pml1*>(memory::get_virtual_address(pml2->page_frame_number * PAGE_SIZE));
}
if (!pml1)
if (!pml1_table)
{
return nullptr;
}
return &pml1[ADDRMASK_EPT_PML1_INDEX(physical_address)];
return &pml1_table[ADDRMASK_EPT_PML1_INDEX(physical_address)];
}
pml1* ept::find_pml1_table(const uint64_t physical_address)
@ -561,7 +551,7 @@ namespace vmx
auto& split = this->allocate_ept_split();
epte pml1_template{};
pml1 pml1_template{};
pml1_template.flags = 0;
pml1_template.read_access = 1;
pml1_template.write_access = 1;

View File

@ -3,13 +3,30 @@
#define DECLSPEC_PAGE_ALIGN DECLSPEC_ALIGN(PAGE_SIZE)
#include "list.hpp"
#define MTRR_PAGE_SIZE 4096
#define MTRR_PAGE_MASK (~(MTRR_PAGE_SIZE-1))
#define ADDRMASK_EPT_PML1_OFFSET(_VAR_) ((_VAR_) & 0xFFFULL)
#define ADDRMASK_EPT_PML1_INDEX(_VAR_) (((_VAR_) & 0x1FF000ULL) >> 12)
#define ADDRMASK_EPT_PML2_INDEX(_VAR_) (((_VAR_) & 0x3FE00000ULL) >> 21)
#define ADDRMASK_EPT_PML3_INDEX(_VAR_) (((_VAR_) & 0x7FC0000000ULL) >> 30)
#define ADDRMASK_EPT_PML4_INDEX(_VAR_) (((_VAR_) & 0xFF8000000000ULL) >> 39)
namespace vmx
{
using pml4 = ept_pml4;
using pml3 = epdpte;
using pml2 = epde_2mb;
using pml2_ptr = epde;
using pml1 = epte;
using pml4 = ept_pml4e;
using pml3 = ept_pdpte;
using pml2 = ept_pde_2mb;
using pml2_ptr = ept_pde;
using pml1 = ept_pte;
using pml4_entry = pml4e_64;
using pml3_entry = pdpte_64;
using pml2_entry = pde_64;
using pml1_entry = pte_64;
struct ept_split
{

View File

@ -13,6 +13,14 @@
#define DPL_USER 3
#define DPL_SYSTEM 0
typedef struct _EPROCESS
{
DISPATCHER_HEADER Header;
LIST_ENTRY ProfileListHead;
ULONG_PTR DirectoryTableBase;
UCHAR Data[1];
} EPROCESS, *PEPROCESS;
namespace
{
hypervisor* instance{nullptr};
@ -45,6 +53,12 @@ namespace
return cpuid_data[0] == 'momo';
}
void enable_syscall_hooking()
{
int32_t cpu_info[4]{0};
__cpuidex(cpu_info, 0x41414141, 0x42424243);
}
void cpature_special_registers(vmx::special_registers& special_registers)
{
special_registers.cr0 = __readcr0();
@ -63,7 +77,7 @@ namespace
// See: https://github.com/ionescu007/SimpleVisor/issues/48
#define capture_cpu_context(launch_context) \
cpature_special_registers((launch_context).special_registers);\
RtlCaptureContext(&(launch_context).context_frame)
RtlCaptureContext(&(launch_context).context_frame);
void restore_descriptor_tables(vmx::launch_context& launch_context)
{
@ -455,78 +469,378 @@ void vmx_handle_invd()
__wbinvd();
}
bool log_other_call(uintptr_t guest_rip, bool rdtsc)
void inject_interuption(const interruption_type type, const exception_vector vector, const bool deliver_code,
const uint32_t error_code)
{
if (guest_rip < 0x140000000 || guest_rip > 0x15BC27000)
vmentry_interrupt_information interrupt{};
interrupt.valid = true;
interrupt.interruption_type = type;
interrupt.vector = vector;
interrupt.deliver_error_code = deliver_code;
__vmx_vmwrite(VMCS_CTRL_VMENTRY_INTERRUPTION_INFORMATION_FIELD, interrupt.flags);
if (deliver_code)
{
return false;
__vmx_vmwrite(VMCS_CTRL_VMENTRY_INTERRUPTION_INFORMATION_FIELD, error_code);
}
}
const auto is_privileged = (read_vmx(VMCS_GUEST_CS_SELECTOR) &
SEGMENT_ACCESS_RIGHTS_DESCRIPTOR_PRIVILEGE_LEVEL_MASK) == DPL_SYSTEM;
if(is_privileged)
void inject_invalid_opcode()
{
inject_interuption(hardware_exception, invalid_opcode, false, 0);
}
void inject_page_fault(const uint64_t page_fault_address)
{
__writecr2(page_fault_address);
page_fault_exception error_code{};
error_code.flags = 0;
inject_interuption(hardware_exception, page_fault, true, error_code.flags);
}
void inject_page_fault(const void* page_fault_address)
{
inject_page_fault(reinterpret_cast<uint64_t>(page_fault_address));
}
cr3 get_current_process_cr3()
{
cr3 guest_cr3{};
guest_cr3.flags = PsGetCurrentProcess()->DirectoryTableBase;
return guest_cr3;
}
template <size_t Length>
bool is_mem_equal(const uint8_t* ptr, const uint8_t (&array)[Length])
{
for (size_t i = 0; i < Length; ++i)
{
return false;
if (ptr[i] != array[i])
{
return false;
}
}
const auto proc = process::get_current_process();
const auto filename = proc.get_image_filename();
if (!string::equal(filename, "HogwartsLegacy"))
{
return false;
}
debug_log("%s (%s): %llX\n", rdtsc ? "RDTSC" : "RDTSCP",
filename,
guest_rip);
return true;
}
bool log_cpuid_call(uintptr_t guest_rip, uintptr_t rax, uintptr_t rcx, const INT32* cpu_info)
void set_exception_bit(const exception_vector bit, const bool value)
{
if (guest_rip < 0x140000000 || guest_rip > 0x15BC27000)
auto exception_bitmap = read_vmx(VMCS_CTRL_EXCEPTION_BITMAP);
if (value)
{
return false;
exception_bitmap |= 1ULL << bit;
}
else
{
exception_bitmap &= ~(1ULL << bit);
}
const auto is_privileged = (read_vmx(VMCS_GUEST_CS_SELECTOR) &
SEGMENT_ACCESS_RIGHTS_DESCRIPTOR_PRIVILEGE_LEVEL_MASK) == DPL_SYSTEM;
if (is_privileged)
__vmx_vmwrite(VMCS_CTRL_EXCEPTION_BITMAP, exception_bitmap);
}
void vmx_enable_syscall_hooks(const bool enable)
{
ULARGE_INTEGER msr{};
ia32_efer_register efer_register{};
ia32_vmx_basic_register vmx_basic_register{};
ia32_vmx_exit_ctls_register exit_ctls_register{};
ia32_vmx_entry_ctls_register entry_ctls_register{};
vmx_basic_register.flags = __readmsr(IA32_VMX_BASIC);
exit_ctls_register.flags = read_vmx(VMCS_CTRL_PRIMARY_VMEXIT_CONTROLS);
entry_ctls_register.flags = read_vmx(VMCS_CTRL_VMENTRY_CONTROLS);
efer_register.flags = __readmsr(IA32_EFER);
// ---------------------------------------
efer_register.syscall_enable = !enable;
exit_ctls_register.save_ia32_efer = enable;
entry_ctls_register.load_ia32_efer = enable;
// ---------------------------------------
if (enable)
{
return false;
msr.QuadPart = __readmsr(vmx_basic_register.vmx_controls ? IA32_VMX_TRUE_ENTRY_CTLS : IA32_VMX_ENTRY_CTLS);
__vmx_vmwrite(VMCS_CTRL_VMENTRY_CONTROLS, adjust_msr(msr, entry_ctls_register.flags));
msr.QuadPart = __readmsr(vmx_basic_register.vmx_controls ? IA32_VMX_TRUE_EXIT_CTLS : IA32_VMX_EXIT_CTLS);
__vmx_vmwrite(VMCS_CTRL_PRIMARY_VMEXIT_CONTROLS, adjust_msr(msr, exit_ctls_register.flags));
}
const auto proc = process::get_current_process();
__vmx_vmwrite(VMCS_GUEST_EFER, efer_register.flags);
const auto filename = proc.get_image_filename();
if (!string::equal(filename, "HogwartsLegacy"))
set_exception_bit(invalid_opcode, enable);
}
enum class syscall_state
{
is_sysret,
is_syscall,
page_fault,
none,
};
class scoped_cr3_switch
{
public:
scoped_cr3_switch()
{
return false;
original_cr3_.flags = __readcr3();
}
scoped_cr3_switch(const cr3 new_cr3)
: scoped_cr3_switch()
{
this->set_cr3(new_cr3);
}
debug_log("CPUID call (%s): %llX - (EAX: %08X - ECX: %08X) - (EAX: %08X - EBX: %08X - ECX: %08X - EDX: %08X)\n",
filename,
guest_rip, rax, rcx, cpu_info[0], cpu_info[1], cpu_info[2], cpu_info[3]);
scoped_cr3_switch(const scoped_cr3_switch&) = delete;
scoped_cr3_switch& operator=(const scoped_cr3_switch&) = delete;
//debug_log("OVERHEAD\n");
scoped_cr3_switch(scoped_cr3_switch&&) = delete;
scoped_cr3_switch& operator=(scoped_cr3_switch&&) = delete;
~scoped_cr3_switch()
{
__writecr3(original_cr3_.flags);
}
void set_cr3(const cr3 new_cr3)
{
this->must_restore_ = true;
__writecr3(new_cr3.flags);
}
private:
bool must_restore_{false};
cr3 original_cr3_{};
};
template <size_t Length>
bool read_data_or_page_fault(uint8_t (&array)[Length], const uint8_t* base)
{
for (size_t offset = 0; offset < Length;)
{
auto* current_base = base + offset;
auto* current_destination = array + offset;
auto read_length = Length - offset;
const auto* page_start = static_cast<uint8_t*>(PAGE_ALIGN(current_base));
const auto* next_page = page_start + PAGE_SIZE;
if (current_base + read_length > next_page)
{
read_length = next_page - current_base;
}
offset += read_length;
const auto physical_base = memory::get_physical_address(const_cast<uint8_t*>(current_base));
if (!physical_base)
{
inject_page_fault(current_base);
return false;
}
if (!memory::read_physical_memory(current_destination, physical_base, read_length))
{
// Not sure if we can recover from that :(
return false;
}
}
return true;
}
syscall_state get_syscall_state(const vmx::guest_context& guest_context)
{
scoped_cr3_switch cr3_switch{};
constexpr auto PCID_NONE = 0x000;
constexpr auto PCID_MASK = 0x003;
cr3 guest_cr3{};
guest_cr3.flags = read_vmx(VMCS_GUEST_CR3);
if ((guest_cr3.flags & PCID_MASK) != PCID_NONE)
{
cr3_switch.set_cr3(get_current_process_cr3());
}
const auto* rip = reinterpret_cast<uint8_t*>(guest_context.guest_rip);
constexpr uint8_t syscall_bytes[] = {0x0F, 0x05};
constexpr uint8_t sysret_bytes[] = {0x48, 0x0F, 0x07};
constexpr auto max_byte_length = max(sizeof(sysret_bytes), sizeof(syscall_bytes));
uint8_t data[max_byte_length];
if (!read_data_or_page_fault(data, rip))
{
return syscall_state::page_fault;
}
if (is_mem_equal(data, syscall_bytes))
{
return syscall_state::is_syscall;
}
if (is_mem_equal(data, sysret_bytes))
{
return syscall_state::is_sysret;
}
return syscall_state::none;
}
void vmx_handle_exception(vmx::guest_context& guest_context)
{
vmexit_interrupt_information interrupt{};
interrupt.flags = static_cast<uint32_t>(read_vmx(VMCS_VMEXIT_INTERRUPTION_INFORMATION));
if (interrupt.interruption_type == non_maskable_interrupt
&& interrupt.vector == nmi)
{
// TODO ?
return;
}
if (interrupt.vector == invalid_opcode)
{
guest_context.increment_rip = false;
const auto state = get_syscall_state(guest_context);
if (state == syscall_state::page_fault)
{
return;
}
const auto proc = process::get_current_process();
const auto filename = proc.get_image_filename();
if (string::equal(filename, "explorer.exe"))
{
debug_log("Explorer SYSCALL: %d\n", static_cast<uint32_t>(guest_context.vp_regs->Rax));
}
if (state == syscall_state::is_syscall)
{
const auto instruction_length = read_vmx(VMCS_VMEXIT_INSTRUCTION_LENGTH);
const auto star = __readmsr(IA32_STAR);
const auto lstar = __readmsr(IA32_LSTAR);
const auto fmask = __readmsr(IA32_FMASK);
guest_context.vp_regs->Rcx = guest_context.guest_rip + instruction_length;
guest_context.guest_rip = lstar;
__vmx_vmwrite(VMCS_GUEST_RIP, guest_context.guest_rip);
guest_context.vp_regs->R11 = guest_context.guest_e_flags;
guest_context.guest_e_flags &= ~(fmask | RFLAGS_RESUME_FLAG_FLAG);
__vmx_vmwrite(VMCS_GUEST_RFLAGS, guest_context.guest_e_flags);
vmx::gdt_entry gdt_entry{};
gdt_entry.selector.flags = static_cast<uint16_t>((star >> 32) & ~3);
gdt_entry.base = 0;
gdt_entry.limit = 0xFFFFF;
gdt_entry.access_rights.flags = 0xA09B;
__vmx_vmwrite(VMCS_GUEST_CS_SELECTOR, gdt_entry.selector.flags);
__vmx_vmwrite(VMCS_GUEST_CS_LIMIT, gdt_entry.limit);
__vmx_vmwrite(VMCS_GUEST_CS_ACCESS_RIGHTS, gdt_entry.access_rights.flags);
__vmx_vmwrite(VMCS_GUEST_CS_BASE, gdt_entry.base);
gdt_entry = {};
gdt_entry.selector.flags = static_cast<uint16_t>(((star >> 32) & ~3) + 8);
gdt_entry.base = 0;
gdt_entry.limit = 0xFFFFF;
gdt_entry.access_rights.flags = 0xC093;
__vmx_vmwrite(VMCS_GUEST_SS_SELECTOR, gdt_entry.selector.flags);
__vmx_vmwrite(VMCS_GUEST_SS_LIMIT, gdt_entry.limit);
__vmx_vmwrite(VMCS_GUEST_SS_ACCESS_RIGHTS, gdt_entry.access_rights.flags);
__vmx_vmwrite(VMCS_GUEST_SS_BASE, gdt_entry.base);
}
else if (state == syscall_state::is_sysret)
{
const auto star = __readmsr(IA32_STAR);
guest_context.vp_regs->Rip = guest_context.vp_regs->Rcx;
__vmx_vmwrite(VMCS_GUEST_RIP, guest_context.vp_regs->Rip);
guest_context.guest_e_flags = (guest_context.vp_regs->R11 & 0x3C7FD7) | 2;
__vmx_vmwrite(VMCS_GUEST_RFLAGS, guest_context.guest_e_flags);
vmx::gdt_entry gdt_entry{};
gdt_entry.selector.flags = static_cast<uint16_t>(((star >> 48) + 16) | 3);
gdt_entry.base = 0;
gdt_entry.limit = 0xFFFFF;
gdt_entry.access_rights.flags = 0xA0FB;
__vmx_vmwrite(VMCS_GUEST_CS_SELECTOR, gdt_entry.selector.flags);
__vmx_vmwrite(VMCS_GUEST_CS_LIMIT, gdt_entry.limit);
__vmx_vmwrite(VMCS_GUEST_CS_ACCESS_RIGHTS, gdt_entry.access_rights.flags);
__vmx_vmwrite(VMCS_GUEST_CS_BASE, gdt_entry.base);
gdt_entry = {};
gdt_entry.selector.flags = static_cast<uint16_t>(((star >> 48) + 8) | 3);
gdt_entry.base = 0;
gdt_entry.limit = 0xFFFFF;
gdt_entry.access_rights.flags = 0xC0F3;
__vmx_vmwrite(VMCS_GUEST_SS_SELECTOR, gdt_entry.selector.flags);
__vmx_vmwrite(VMCS_GUEST_SS_LIMIT, gdt_entry.limit);
__vmx_vmwrite(VMCS_GUEST_SS_ACCESS_RIGHTS, gdt_entry.access_rights.flags);
__vmx_vmwrite(VMCS_GUEST_SS_BASE, gdt_entry.base);
}
else
{
inject_invalid_opcode();
}
}
else
{
__vmx_vmwrite(VMCS_CTRL_VMENTRY_INTERRUPTION_INFORMATION_FIELD, interrupt.flags);
if (interrupt.error_code_valid)
{
__vmx_vmwrite(VMCS_CTRL_VMENTRY_EXCEPTION_ERROR_CODE, read_vmx(VMCS_VMEXIT_INTERRUPTION_ERROR_CODE));
}
}
}
bool is_system()
{
return (read_vmx(VMCS_GUEST_CS_SELECTOR) & SEGMENT_ACCESS_RIGHTS_DESCRIPTOR_PRIVILEGE_LEVEL_MASK) == DPL_SYSTEM;
}
void vmx_handle_cpuid(vmx::guest_context& guest_context)
{
INT32 cpu_info[4]{0, 0, 0, 0};
if (guest_context.vp_regs->Rax == 0x41414141 &&
guest_context.vp_regs->Rcx == 0x42424243 &&
is_system())
{
vmx_enable_syscall_hooks(true);
return;
}
const auto is_privileged = (read_vmx(VMCS_GUEST_CS_SELECTOR) &
SEGMENT_ACCESS_RIGHTS_DESCRIPTOR_PRIVILEGE_LEVEL_MASK) == DPL_SYSTEM;
INT32 cpu_info[4];
if (guest_context.vp_regs->Rax == 0x41414141 &&
guest_context.vp_regs->Rcx == 0x42424242 &&
is_privileged)
is_system())
{
guest_context.exit_vm = true;
return;
@ -535,15 +849,6 @@ void vmx_handle_cpuid(vmx::guest_context& guest_context)
__cpuidex(cpu_info, static_cast<int32_t>(guest_context.vp_regs->Rax),
static_cast<int32_t>(guest_context.vp_regs->Rcx));
bool should_zero = false;
if (!is_privileged)
{
should_zero = log_cpuid_call(guest_context.guest_rip, guest_context.vp_regs->Rax, guest_context.vp_regs->Rcx,
cpu_info);
}
const auto _rax = guest_context.vp_regs->Rax;
if (guest_context.vp_regs->Rax == 1)
{
cpu_info[2] |= HYPERV_HYPERVISOR_PRESENT_BIT;
@ -553,107 +858,6 @@ void vmx_handle_cpuid(vmx::guest_context& guest_context)
cpu_info[0] = 'momo';
}
if (should_zero)
{
// [MOMO] CPUID call(HogwartsLegacy) : 140D2451B - (EAX : 80000006 - ECX : 00000000) - (EAX : 00000000 - EBX : 00000000 - ECX : 01006040 - EDX : 00000000)
// [MOMO] CPUID call (HogwartsLegacy): 1405F4817 - (EAX: 00000004 - ECX: 00000000) - (EAX: 1C004121 - EBX: 01C0003F - ECX: 0000003F - EDX: 00000000)
bool allow_all = true;
// not sure if necessary
/*if (_rax == 0 && allow_all)
{
cpu_info[0] = 0x00000016;
cpu_info[1] = 0x756E6547;
cpu_info[2] = 0x6C65746E;
cpu_info[3] = 0x49656E69;
}
else if (_rax == 4 && allow_all)
{
cpu_info[0] = 0x00000000;
cpu_info[1] = 0x01C0003F;
cpu_info[2] = 0x0000003F;
cpu_info[3] = 0x00000000;
}
else if (_rax == 7 && allow_all)
{
cpu_info[0] = 0x1C004121;
cpu_info[1] = 0x029C6FBF;
cpu_info[2] = 0x40000000;
cpu_info[3] = (INT32)0xBC002E00;
}
else if (_rax == 0x80000000 && allow_all)
{
cpu_info[0] = (INT32)0x80000008;
cpu_info[1] = 0x00000000;
cpu_info[2] = 0x00000000;
cpu_info[3] = 0x00000000;
}
else if (_rax == 0x80000006 && allow_all)
{
cpu_info[0] = 0x00000000;
cpu_info[1] = 0x00000000;
cpu_info[2] = 0x01006040;
cpu_info[3] = 0x00000000;
}
// absolutely necessary v
else*/ if (_rax == 1 && allow_all)
{
cpu_info[0] = 0x000306A9;
cpu_info[1] = 0x02100800;
cpu_info[2] = 0x7FBAE3FF & (~0xC000000);
//cpu_info[0] = 0x000906EA;
//cpu_info[1] = 0x04100800;
//cpu_info[2] = 0x7FFAFBFF & (~0xC000000);
cpu_info[3] = (INT32)0xBFEBFBFF ;
}
else if (_rax == 0x80000002)
{
cpu_info[0] = 0x65746E49;
cpu_info[1] = 0x2952286C;
cpu_info[2] = 0x726F4320;
cpu_info[3] = 0x4D542865;
}
else if (_rax == 0x80000003)
{
cpu_info[0] = 0x37692029;
cpu_info[1] = 0x3538382D;
cpu_info[2] = 0x43204830;
cpu_info[3] = 0x40205550;
}
else if (_rax == 0x80000004)
{
cpu_info[0] = 0x362E3220;
cpu_info[1] = 0x7A484730;
cpu_info[2] = 0x00000000;
cpu_info[3] = 0x00000000;
}
else if(false)
{
cpu_info[0] = 0;
cpu_info[1] = 0;
cpu_info[2] = 0;
cpu_info[3] = 0;
debug_log("Not zeroing!\n");
}
/* should_zero &= _rax == 1
|| _rax == 0x80000002
|| _rax == 0x80000003
|| _rax == 0x80000004;
*
if (should_zero)
{
cpu_info[0] = 0;
cpu_info[1] = 0;
cpu_info[2] = 0;
cpu_info[3] = 0;
}*/
}
guest_context.vp_regs->Rax = cpu_info[0];
guest_context.vp_regs->Rbx = cpu_info[1];
guest_context.vp_regs->Rcx = cpu_info[2];
@ -703,37 +907,12 @@ void vmx_dispatch_vm_exit(vmx::guest_context& guest_context, const vmx::state& v
case VMX_EXIT_REASON_EPT_MISCONFIGURATION:
vm_state.ept->handle_misconfiguration(guest_context);
break;
case VMX_EXIT_REASON_EXECUTE_RDTSC:
{
//debug_log("VM exit: VMX_EXIT_REASON_EXECUTE_RDTSC\n");
ULARGE_INTEGER tsc{};
tsc.QuadPart = __rdtsc();
guest_context.vp_regs->Rax = tsc.LowPart;
guest_context.vp_regs->Rdx = tsc.HighPart;
log_other_call(guest_context.guest_rip, true);
case VMX_EXIT_REASON_EXCEPTION_OR_NMI:
vmx_handle_exception(guest_context);
break;
}
case VMX_EXIT_REASON_EXECUTE_RDTSCP:
{
//debug_log("VM exit: VMX_EXIT_REASON_EXECUTE_RDTSCP\n");
uint32_t _rcx{};
ULARGE_INTEGER tsc{};
tsc.QuadPart = __rdtscp(&_rcx);
guest_context.vp_regs->Rax = tsc.LowPart;
guest_context.vp_regs->Rdx = tsc.HighPart;
guest_context.vp_regs->Rcx = _rcx;
log_other_call(guest_context.guest_rip, false);
break;
}
//case VMX_EXIT_REASON_EXECUTE_RDTSC:
// break;
default:
//debug_log("Unknown VM exit: %X\n",(uint32_t) guest_context.exit_reason);
break;
}
@ -810,7 +989,6 @@ void setup_vmcs_for_cpu(vmx::state& vm_state)
ia32_vmx_procbased_ctls_register procbased_ctls_register{};
procbased_ctls_register.activate_secondary_controls = 1;
procbased_ctls_register.use_msr_bitmaps = 1;
procbased_ctls_register.rdtsc_exiting = 0;
__vmx_vmwrite(VMCS_CTRL_PROCESSOR_BASED_VM_EXECUTION_CONTROLS,
adjust_msr(launch_context->msr_data[14],
@ -818,7 +996,7 @@ void setup_vmcs_for_cpu(vmx::state& vm_state)
ia32_vmx_exit_ctls_register exit_ctls_register{};
exit_ctls_register.host_address_space_size = 1;
__vmx_vmwrite(VMCS_CTRL_VMEXIT_CONTROLS,
__vmx_vmwrite(VMCS_CTRL_PRIMARY_VMEXIT_CONTROLS,
adjust_msr(launch_context->msr_data[15],
exit_ctls_register.flags));
@ -909,7 +1087,8 @@ void setup_vmcs_for_cpu(vmx::state& vm_state)
__vmx_vmwrite(VMCS_GUEST_DEBUGCTL, state->debug_control);
__vmx_vmwrite(VMCS_GUEST_DR7, state->kernel_dr7);
const auto stack_pointer = reinterpret_cast<uintptr_t>(vm_state.stack_buffer) + KERNEL_STACK_SIZE - sizeof(CONTEXT);
const auto stack_pointer = reinterpret_cast<uintptr_t>(vm_state.stack_buffer) + KERNEL_STACK_SIZE - sizeof(
CONTEXT);
__vmx_vmwrite(VMCS_GUEST_RSP, stack_pointer);
__vmx_vmwrite(VMCS_GUEST_RIP, reinterpret_cast<uintptr_t>(vm_launch));
@ -972,6 +1151,8 @@ void hypervisor::enable_core(const uint64_t system_directory_table_base)
{
throw std::runtime_error("Hypervisor is not present");
}
enable_syscall_hooking();
}
void hypervisor::disable_core()

View File

@ -68,6 +68,18 @@ namespace memory
return memory;
}
_IRQL_requires_max_(APC_LEVEL)
bool read_physical_memory(void* destination, uint64_t physical_address, const size_t size)
{
size_t bytes_read{};
MM_COPY_ADDRESS source{};
source.PhysicalAddress.QuadPart = static_cast<int64_t>(physical_address);
return MmCopyMemory(destination, source, size, MM_COPY_MEMORY_PHYSICAL, &bytes_read) == STATUS_SUCCESS &&
bytes_read == size;
}
uint64_t get_physical_address(void* address)
{
return static_cast<uint64_t>(MmGetPhysicalAddress(address).QuadPart);

View File

@ -10,6 +10,9 @@ namespace memory
_IRQL_requires_max_(DISPATCH_LEVEL)
void* allocate_aligned_memory(size_t size);
_IRQL_requires_max_(APC_LEVEL)
bool read_physical_memory(void* destination, uint64_t physical_address, size_t size);
uint64_t get_physical_address(void* address);
void* get_virtual_address(uint64_t address);

View File

@ -56,6 +56,29 @@ MmAllocateContiguousNodeMemory(
// ----------------------------------------
typedef struct _MM_COPY_ADDRESS {
union {
PVOID VirtualAddress;
PHYSICAL_ADDRESS PhysicalAddress;
};
} MM_COPY_ADDRESS, * PMMCOPY_ADDRESS;
#define MM_COPY_MEMORY_PHYSICAL 0x1
#define MM_COPY_MEMORY_VIRTUAL 0x2
_IRQL_requires_max_(APC_LEVEL)
NTKERNELAPI
NTSTATUS
MmCopyMemory(
_In_ PVOID TargetAddress,
_In_ MM_COPY_ADDRESS SourceAddress,
_In_ SIZE_T NumberOfBytes,
_In_ ULONG Flags,
_Out_ PSIZE_T NumberOfBytesTransferred
);
// ----------------------------------------
NTSYSAPI
VOID
NTAPI

View File

@ -10,7 +10,7 @@ namespace string
char* get_va_buffer();
template <typename... Args>
template <typename ...Args>
const char* va(const char* message, Args&&... args)
{
auto* buffer = get_va_buffer();
@ -25,9 +25,9 @@ namespace string
return !s2;
}
while(*s1)
while (*s1)
{
if(*(s1++) != *(s2++))
if (*(s1++) != *(s2++))
{
return false;
}

View File

@ -45,12 +45,25 @@ namespace
static driver hypervisor{};
static driver_device device{};
if (!hypervisor)
if (!device)
{
try
{
hypervisor = create_driver();
}catch(...){}
device = create_driver_device();
}
catch (...)
{
}
}
if (device)
{
return device;
}
if (!hypervisor)
{
hypervisor = create_driver();
}
if (!device)

View File

@ -87,7 +87,12 @@ void patch_t6(const uint32_t pid)
void try_patch_t6()
{
const auto pid = get_process_id_from_window(nullptr, "Call of Duty" "\xAE" ": Black Ops II - Multiplayer");
auto pid = get_process_id_from_window(nullptr, "Call of Duty" "\xAE" ": Black Ops II - Multiplayer");
if (!pid)
{
pid = get_process_id_from_window("CoDBlackOps", nullptr);
}
if (pid)
{
printf("Patching T6...\n");