1
0
mirror of https://github.com/momo5502/hypervisor.git synced 2025-07-04 02:01:58 +00:00

27 Commits
hwl ... main

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 version: 2
updates: updates:
- package-ecosystem: gitsubmodule - package-ecosystem: gitsubmodule
directory: "/" directory: "/"
schedule: schedule:
interval: daily interval: monthly
open-pull-requests-limit: 10 open-pull-requests-limit: 10
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: monthly

View File

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

View File

@ -7,16 +7,6 @@
#include "memory.hpp" #include "memory.hpp"
#include "vmx.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 vmx
{ {
namespace namespace
@ -301,7 +291,7 @@ namespace vmx
// -------------------------- // --------------------------
epdpte temp_epdpte; pml1 temp_epdpte{};
temp_epdpte.flags = 0; temp_epdpte.flags = 0;
temp_epdpte.read_access = 1; temp_epdpte.read_access = 1;
temp_epdpte.write_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.flags = 0;
temp_epde.read_access = 1; temp_epde.read_access = 1;
temp_epde.write_access = 1; temp_epde.write_access = 1;
@ -410,18 +400,18 @@ namespace vmx
} }
const auto* pml2 = reinterpret_cast<pml2_ptr*>(pml2_entry); const auto* pml2 = reinterpret_cast<pml2_ptr*>(pml2_entry);
auto* pml1 = this->find_pml1_table(pml2->page_frame_number * PAGE_SIZE); auto* pml1_table = this->find_pml1_table(pml2->page_frame_number * PAGE_SIZE);
if (!pml1) 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 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) pml1* ept::find_pml1_table(const uint64_t physical_address)
@ -561,7 +551,7 @@ namespace vmx
auto& split = this->allocate_ept_split(); auto& split = this->allocate_ept_split();
epte pml1_template{}; pml1 pml1_template{};
pml1_template.flags = 0; pml1_template.flags = 0;
pml1_template.read_access = 1; pml1_template.read_access = 1;
pml1_template.write_access = 1; pml1_template.write_access = 1;

View File

@ -3,13 +3,30 @@
#define DECLSPEC_PAGE_ALIGN DECLSPEC_ALIGN(PAGE_SIZE) #define DECLSPEC_PAGE_ALIGN DECLSPEC_ALIGN(PAGE_SIZE)
#include "list.hpp" #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 namespace vmx
{ {
using pml4 = ept_pml4; using pml4 = ept_pml4e;
using pml3 = epdpte; using pml3 = ept_pdpte;
using pml2 = epde_2mb; using pml2 = ept_pde_2mb;
using pml2_ptr = epde; using pml2_ptr = ept_pde;
using pml1 = epte; 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 struct ept_split
{ {

View File

@ -13,6 +13,14 @@
#define DPL_USER 3 #define DPL_USER 3
#define DPL_SYSTEM 0 #define DPL_SYSTEM 0
typedef struct _EPROCESS
{
DISPATCHER_HEADER Header;
LIST_ENTRY ProfileListHead;
ULONG_PTR DirectoryTableBase;
UCHAR Data[1];
} EPROCESS, *PEPROCESS;
namespace namespace
{ {
hypervisor* instance{nullptr}; hypervisor* instance{nullptr};
@ -45,6 +53,12 @@ namespace
return cpuid_data[0] == 'momo'; 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) void cpature_special_registers(vmx::special_registers& special_registers)
{ {
special_registers.cr0 = __readcr0(); special_registers.cr0 = __readcr0();
@ -63,7 +77,7 @@ namespace
// See: https://github.com/ionescu007/SimpleVisor/issues/48 // See: https://github.com/ionescu007/SimpleVisor/issues/48
#define capture_cpu_context(launch_context) \ #define capture_cpu_context(launch_context) \
cpature_special_registers((launch_context).special_registers);\ 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) void restore_descriptor_tables(vmx::launch_context& launch_context)
{ {
@ -455,78 +469,378 @@ void vmx_handle_invd()
__wbinvd(); __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) & void inject_invalid_opcode()
SEGMENT_ACCESS_RIGHTS_DESCRIPTOR_PRIVILEGE_LEVEL_MASK) == DPL_SYSTEM; {
if(is_privileged) 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; 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) & __vmx_vmwrite(VMCS_CTRL_EXCEPTION_BITMAP, exception_bitmap);
SEGMENT_ACCESS_RIGHTS_DESCRIPTOR_PRIVILEGE_LEVEL_MASK) == DPL_SYSTEM; }
if (is_privileged)
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(); set_exception_bit(invalid_opcode, enable);
if (!string::equal(filename, "HogwartsLegacy")) }
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", scoped_cr3_switch(const scoped_cr3_switch&) = delete;
filename, scoped_cr3_switch& operator=(const scoped_cr3_switch&) = delete;
guest_rip, rax, rcx, cpu_info[0], cpu_info[1], cpu_info[2], cpu_info[3]);
//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; 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) 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) & INT32 cpu_info[4];
SEGMENT_ACCESS_RIGHTS_DESCRIPTOR_PRIVILEGE_LEVEL_MASK) == DPL_SYSTEM;
if (guest_context.vp_regs->Rax == 0x41414141 && if (guest_context.vp_regs->Rax == 0x41414141 &&
guest_context.vp_regs->Rcx == 0x42424242 && guest_context.vp_regs->Rcx == 0x42424242 &&
is_privileged) is_system())
{ {
guest_context.exit_vm = true; guest_context.exit_vm = true;
return; 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), __cpuidex(cpu_info, static_cast<int32_t>(guest_context.vp_regs->Rax),
static_cast<int32_t>(guest_context.vp_regs->Rcx)); 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) if (guest_context.vp_regs->Rax == 1)
{ {
cpu_info[2] |= HYPERV_HYPERVISOR_PRESENT_BIT; cpu_info[2] |= HYPERV_HYPERVISOR_PRESENT_BIT;
@ -553,107 +858,6 @@ void vmx_handle_cpuid(vmx::guest_context& guest_context)
cpu_info[0] = 'momo'; 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->Rax = cpu_info[0];
guest_context.vp_regs->Rbx = cpu_info[1]; guest_context.vp_regs->Rbx = cpu_info[1];
guest_context.vp_regs->Rcx = cpu_info[2]; 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: case VMX_EXIT_REASON_EPT_MISCONFIGURATION:
vm_state.ept->handle_misconfiguration(guest_context); vm_state.ept->handle_misconfiguration(guest_context);
break; break;
case VMX_EXIT_REASON_EXECUTE_RDTSC: case VMX_EXIT_REASON_EXCEPTION_OR_NMI:
{ vmx_handle_exception(guest_context);
//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);
break; break;
} //case VMX_EXIT_REASON_EXECUTE_RDTSC:
case VMX_EXIT_REASON_EXECUTE_RDTSCP: // break;
{
//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;
}
default: default:
//debug_log("Unknown VM exit: %X\n",(uint32_t) guest_context.exit_reason);
break; break;
} }
@ -810,7 +989,6 @@ void setup_vmcs_for_cpu(vmx::state& vm_state)
ia32_vmx_procbased_ctls_register procbased_ctls_register{}; ia32_vmx_procbased_ctls_register procbased_ctls_register{};
procbased_ctls_register.activate_secondary_controls = 1; procbased_ctls_register.activate_secondary_controls = 1;
procbased_ctls_register.use_msr_bitmaps = 1; procbased_ctls_register.use_msr_bitmaps = 1;
procbased_ctls_register.rdtsc_exiting = 0;
__vmx_vmwrite(VMCS_CTRL_PROCESSOR_BASED_VM_EXECUTION_CONTROLS, __vmx_vmwrite(VMCS_CTRL_PROCESSOR_BASED_VM_EXECUTION_CONTROLS,
adjust_msr(launch_context->msr_data[14], 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{}; ia32_vmx_exit_ctls_register exit_ctls_register{};
exit_ctls_register.host_address_space_size = 1; 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], adjust_msr(launch_context->msr_data[15],
exit_ctls_register.flags)); 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_DEBUGCTL, state->debug_control);
__vmx_vmwrite(VMCS_GUEST_DR7, state->kernel_dr7); __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_RSP, stack_pointer);
__vmx_vmwrite(VMCS_GUEST_RIP, reinterpret_cast<uintptr_t>(vm_launch)); __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"); throw std::runtime_error("Hypervisor is not present");
} }
enable_syscall_hooking();
} }
void hypervisor::disable_core() void hypervisor::disable_core()

View File

@ -68,6 +68,18 @@ namespace memory
return 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) uint64_t get_physical_address(void* address)
{ {
return static_cast<uint64_t>(MmGetPhysicalAddress(address).QuadPart); return static_cast<uint64_t>(MmGetPhysicalAddress(address).QuadPart);

View File

@ -10,6 +10,9 @@ namespace memory
_IRQL_requires_max_(DISPATCH_LEVEL) _IRQL_requires_max_(DISPATCH_LEVEL)
void* allocate_aligned_memory(size_t size); 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); uint64_t get_physical_address(void* address);
void* get_virtual_address(uint64_t 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 NTSYSAPI
VOID VOID
NTAPI NTAPI

View File

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

View File

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

View File

@ -87,7 +87,12 @@ void patch_t6(const uint32_t pid)
void try_patch_t6() 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) if (pid)
{ {
printf("Patching T6...\n"); printf("Patching T6...\n");