From 8d86cc945fdc8fd120aa630af9d59fe9c246587b Mon Sep 17 00:00:00 2001 From: xorrsp <94297076+xorrsp@users.noreply.github.com> Date: Mon, 15 Nov 2021 01:00:56 +0800 Subject: [PATCH 01/10] Update ept.c --- gbhv/ept.c | 41 +++++++++++++++++++++++++++-------------- 1 file changed, 27 insertions(+), 14 deletions(-) diff --git a/gbhv/ept.c b/gbhv/ept.c index 55c4ac1..5c9381f 100644 --- a/gbhv/ept.c +++ b/gbhv/ept.c @@ -597,19 +597,32 @@ VOID HvEptFreeLogicalProcessorContext(PVMM_PROCESSOR_CONTEXT ProcessorContext) /* Write an absolute x64 jump to an arbitrary address to a buffer. */ VOID HvEptHookWriteAbsoluteJump(PCHAR TargetBuffer, SIZE_T TargetAddress) { - /* mov r15, Target */ - TargetBuffer[0] = 0x49; - TargetBuffer[1] = 0xBB; - - /* Target */ - *((PSIZE_T)&TargetBuffer[2]) = TargetAddress; - - /* push r15 */ - TargetBuffer[10] = 0x41; - TargetBuffer[11] = 0x53; - - /* ret */ - TargetBuffer[12] = 0xC3; + /** + * Use 'push ret' instead of 'jmp qword[rip+0]', + * Because 'jmp qword[rip+0]' will read hooked page 8bytes. + * + * 14 bytes hook: + * 0x68 0x12345678 ......................push 'low 32bit of TargetAddress' + * 0xC7 0x44 0x24 0x04 0x12345678........mov dword[rsp + 4], 'high 32bit of TargetAddress' + * 0xC3..................................ret + */ + + UINT32 Low32; + UINT32 High32; + + Low32 = (UINT32)TargetAddress; + High32 = (UINT32)(TargetAddress >> 32); + + /* push 'low 32bit of TargetAddress' */ + TargetBuffer[0] = 0x68; + *((UINT32*)&TargetBuffer[1]) = Low32; + + /* mov dword[rsp + 4], 'high 32bit of TargetAddress' */ + *((UINT32*)&TargetBuffer[5]) = 0x042444C7; + *((UINT32*)&TargetBuffer[9]) = High32; + + /* ret */ + TargetBuffer[13] = 0xC3; } @@ -630,7 +643,7 @@ BOOL HvEptHookInstructionMemory(PVMM_EPT_PAGE_HOOK Hook, PVOID TargetFunction, P /* Determine the number of instructions necessary to overwrite using Length Disassembler Engine */ for(SizeOfHookedInstructions = 0; SizeOfHookedInstructions < 13; - SizeOfHookedInstructions += LDE(TargetFunction, 64)) + SizeOfHookedInstructions += LDE((PCHAR)TargetFunction + SizeOfHookedInstructions, 64)) { // Get the full size of instructions necessary to copy } From 922a2c73b5e414ca2552095e43720c6e38e3051f Mon Sep 17 00:00:00 2001 From: xorrsp <94297076+xorrsp@users.noreply.github.com> Date: Mon, 15 Nov 2021 01:03:17 +0800 Subject: [PATCH 02/10] Update ept.c --- gbhv/ept.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/gbhv/ept.c b/gbhv/ept.c index 5c9381f..693cd88 100644 --- a/gbhv/ept.c +++ b/gbhv/ept.c @@ -634,7 +634,7 @@ BOOL HvEptHookInstructionMemory(PVMM_EPT_PAGE_HOOK Hook, PVOID TargetFunction, P OffsetIntoPage = ADDRMASK_EPT_PML1_OFFSET((SIZE_T)TargetFunction); HvUtilLogDebug("OffsetIntoPage: 0x%llx\n", OffsetIntoPage); - if ((OffsetIntoPage + 13) > PAGE_SIZE-1) + if ((OffsetIntoPage + 14) > PAGE_SIZE-1) { HvUtilLogError("Function extends past a page boundary. We just don't have the technology to solve this.....\n"); return FALSE; @@ -642,7 +642,7 @@ BOOL HvEptHookInstructionMemory(PVMM_EPT_PAGE_HOOK Hook, PVOID TargetFunction, P /* Determine the number of instructions necessary to overwrite using Length Disassembler Engine */ for(SizeOfHookedInstructions = 0; - SizeOfHookedInstructions < 13; + SizeOfHookedInstructions < 14; SizeOfHookedInstructions += LDE((PCHAR)TargetFunction + SizeOfHookedInstructions, 64)) { // Get the full size of instructions necessary to copy @@ -653,7 +653,7 @@ BOOL HvEptHookInstructionMemory(PVMM_EPT_PAGE_HOOK Hook, PVOID TargetFunction, P /* Build a trampoline */ /* Allocate some executable memory for the trampoline */ - Hook->Trampoline = OsAllocateExecutableNonpagedMemory(SizeOfHookedInstructions + 13); + Hook->Trampoline = OsAllocateExecutableNonpagedMemory(SizeOfHookedInstructions + 14); if (!Hook->Trampoline) { From c5da861b5c25863cb82048ba29da3ec9f943e429 Mon Sep 17 00:00:00 2001 From: xorrsp <94297076+xorrsp@users.noreply.github.com> Date: Wed, 17 Nov 2021 07:09:17 +0800 Subject: [PATCH 03/10] Update vmxdefs.asm --- gbhv/vmxdefs.asm | 19 +++++-------------- 1 file changed, 5 insertions(+), 14 deletions(-) diff --git a/gbhv/vmxdefs.asm b/gbhv/vmxdefs.asm index 975df26..2217286 100644 --- a/gbhv/vmxdefs.asm +++ b/gbhv/vmxdefs.asm @@ -125,13 +125,9 @@ HvEnterFromGuest PROC ; Save XMM registers. The stack must be 16-byte aligned ; or a #GP exception is generated. - sub rsp, 68h - movaps xmmword ptr [rsp], xmm0 - movaps xmmword ptr [rsp+10h], xmm1 - movaps xmmword ptr [rsp+20h], xmm2 - movaps xmmword ptr [rsp+30h], xmm3 - movaps xmmword ptr [rsp+40h], xmm4 - movaps xmmword ptr [rsp+50h], xmm5 + ; 520 = 512(fxsave need) + 8 + sub rsp, 520 + fxsave [rsp] ; Call HvHandleVmExit to actually handle the ; incoming exit @@ -140,13 +136,8 @@ HvEnterFromGuest PROC add rsp, 20h ; Restore XMM registers - movaps xmm0, xmmword ptr [rsp] - movaps xmm1, xmmword ptr [rsp+10h] - movaps xmm2, xmmword ptr [rsp+20h] - movaps xmm3, xmmword ptr [rsp+30h] - movaps xmm4, xmmword ptr [rsp+40h] - movaps xmm5, xmmword ptr [rsp+50h] - add rsp, 68h + fxrstor [rsp] + add rsp, 520 ; If it's not successful, we need to stop and figure out why test al, al From 2cc09caa9ca8f44100c3d9b7118b2d74c9e4a17e Mon Sep 17 00:00:00 2001 From: xorrsp <94297076+xorrsp@users.noreply.github.com> Date: Wed, 17 Nov 2021 07:49:22 +0800 Subject: [PATCH 04/10] Update vmxdefs.asm --- gbhv/vmxdefs.asm | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/gbhv/vmxdefs.asm b/gbhv/vmxdefs.asm index 2217286..975df26 100644 --- a/gbhv/vmxdefs.asm +++ b/gbhv/vmxdefs.asm @@ -125,9 +125,13 @@ HvEnterFromGuest PROC ; Save XMM registers. The stack must be 16-byte aligned ; or a #GP exception is generated. - ; 520 = 512(fxsave need) + 8 - sub rsp, 520 - fxsave [rsp] + sub rsp, 68h + movaps xmmword ptr [rsp], xmm0 + movaps xmmword ptr [rsp+10h], xmm1 + movaps xmmword ptr [rsp+20h], xmm2 + movaps xmmword ptr [rsp+30h], xmm3 + movaps xmmword ptr [rsp+40h], xmm4 + movaps xmmword ptr [rsp+50h], xmm5 ; Call HvHandleVmExit to actually handle the ; incoming exit @@ -136,8 +140,13 @@ HvEnterFromGuest PROC add rsp, 20h ; Restore XMM registers - fxrstor [rsp] - add rsp, 520 + movaps xmm0, xmmword ptr [rsp] + movaps xmm1, xmmword ptr [rsp+10h] + movaps xmm2, xmmword ptr [rsp+20h] + movaps xmm3, xmmword ptr [rsp+30h] + movaps xmm4, xmmword ptr [rsp+40h] + movaps xmm5, xmmword ptr [rsp+50h] + add rsp, 68h ; If it's not successful, we need to stop and figure out why test al, al From cc43ed2f10e127b012f69833f5139ac13502bc78 Mon Sep 17 00:00:00 2001 From: xorrsp <94297076+xorrsp@users.noreply.github.com> Date: Sat, 20 Nov 2021 01:56:02 +0800 Subject: [PATCH 05/10] Update os.h --- gbhv/os.h | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/gbhv/os.h b/gbhv/os.h index 06632aa..572fbfb 100644 --- a/gbhv/os.h +++ b/gbhv/os.h @@ -7,6 +7,10 @@ SIZE_T OsGetCPUCount(); SIZE_T OsGetCurrentProcessorNumber(); +/** + * When your data size is divided by PAGE_SIZE, + * you should be sure that no remainder is discarded. + */ PVOID OsAllocateContiguousAlignedPages(SIZE_T NumberOfPages); VOID OsFreeContiguousAlignedPages(PVOID PageRegionAddress); @@ -23,4 +27,4 @@ PVOID OsPhysicalToVirtual(PPHYSVOID PhysicalAddress); VOID OsZeroMemory(PVOID VirtualAddress, SIZE_T Length); -VOID OsCaptureContext(PREGISTER_CONTEXT ContextRecord); \ No newline at end of file +VOID OsCaptureContext(PREGISTER_CONTEXT ContextRecord); From 7b3413e67c1e10f59709a4a7842d92f6d0c91edf Mon Sep 17 00:00:00 2001 From: xorrsp <94297076+xorrsp@users.noreply.github.com> Date: Sat, 20 Nov 2021 01:58:23 +0800 Subject: [PATCH 06/10] Update os.h --- gbhv/os.h | 4 ---- 1 file changed, 4 deletions(-) diff --git a/gbhv/os.h b/gbhv/os.h index 572fbfb..f03494d 100644 --- a/gbhv/os.h +++ b/gbhv/os.h @@ -7,10 +7,6 @@ SIZE_T OsGetCPUCount(); SIZE_T OsGetCurrentProcessorNumber(); -/** - * When your data size is divided by PAGE_SIZE, - * you should be sure that no remainder is discarded. - */ PVOID OsAllocateContiguousAlignedPages(SIZE_T NumberOfPages); VOID OsFreeContiguousAlignedPages(PVOID PageRegionAddress); From 5999d264403d18e39dd4ea64d4ffd8fffe1aecb1 Mon Sep 17 00:00:00 2001 From: xorrsp <94297076+xorrsp@users.noreply.github.com> Date: Sat, 20 Nov 2021 02:00:16 +0800 Subject: [PATCH 07/10] Update os_nt.c --- gbhv/os_nt.c | 1 + 1 file changed, 1 insertion(+) diff --git a/gbhv/os_nt.c b/gbhv/os_nt.c index bb1390e..061305d 100644 --- a/gbhv/os_nt.c +++ b/gbhv/os_nt.c @@ -25,6 +25,7 @@ SIZE_T OsGetCurrentProcessorNumber() /* * Allocate a number of page-aligned, contiguous pages of memory and return a pointer to the region. + * When your data size is divided by PAGE_SIZE, you should be sure that no remainder is discarded. * * Returns NULL if the pages could not be allocated. */ From bf632e2ebd19fc600cdbf309ce0ef4b7087ba068 Mon Sep 17 00:00:00 2001 From: xorrsp <94297076+xorrsp@users.noreply.github.com> Date: Sat, 20 Nov 2021 02:04:32 +0800 Subject: [PATCH 08/10] Update ept.c --- gbhv/ept.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gbhv/ept.c b/gbhv/ept.c index 693cd88..6059ce9 100644 --- a/gbhv/ept.c +++ b/gbhv/ept.c @@ -173,7 +173,7 @@ PVMM_EPT_PAGE_TABLE HvEptAllocateAndCreateIdentityPageTable(PVMM_CONTEXT GlobalC SIZE_T EntryIndex; /* Allocate all paging structures as 4KB aligned pages */ - PageTable = OsAllocateContiguousAlignedPages(sizeof(VMM_EPT_PAGE_TABLE) / PAGE_SIZE); + PageTable = OsAllocateContiguousAlignedPages(ALIGN_UP_BY(sizeof(VMM_EPT_PAGE_TABLE), PAGE_SIZE) / PAGE_SIZE); if(PageTable == NULL) { @@ -393,7 +393,7 @@ BOOL HvEptSplitLargePage(PVMM_PROCESSOR_CONTEXT ProcessorContext, SIZE_T Physica * alternative was to use the contiguous aligned pages allocator because, in my testing, it resulted in only 4KB virtual * allocations. This allocator also utilizes nonpaged pool frames, so it is more-or-less the same as the other allocator. */ - NewSplit = (PVMM_EPT_DYNAMIC_SPLIT) OsAllocateContiguousAlignedPages(sizeof(VMM_EPT_DYNAMIC_SPLIT)/PAGE_SIZE); + NewSplit = (PVMM_EPT_DYNAMIC_SPLIT) OsAllocateContiguousAlignedPages(ALIGN_UP_BY(sizeof(VMM_EPT_DYNAMIC_SPLIT), PAGE_SIZE) / PAGE_SIZE); if(!NewSplit) { HvUtilLogError("HvEptSplitLargePage: Failed to allocate dynamic split memory.\n"); From f3c38ea19f68915ef54381b37625a0ce5e29df01 Mon Sep 17 00:00:00 2001 From: xorrsp <94297076+xorrsp@users.noreply.github.com> Date: Sun, 21 Nov 2021 09:11:44 +0800 Subject: [PATCH 09/10] Update vmxdefs.asm --- gbhv/vmxdefs.asm | 60 +++++++++++++++++++++--------------------------- 1 file changed, 26 insertions(+), 34 deletions(-) diff --git a/gbhv/vmxdefs.asm b/gbhv/vmxdefs.asm index 975df26..816be6c 100644 --- a/gbhv/vmxdefs.asm +++ b/gbhv/vmxdefs.asm @@ -21,7 +21,7 @@ PushGeneralPurposeRegisterContext MACRO push rdi push rsi push rbp - sub rsp, 8 ; placeholder for rsp + push rbp ;rsp push rbx push rdx push rcx @@ -32,22 +32,22 @@ ENDM ; RSP is read from VMCS, so there's a placeholder. ; https://github.com/asamy/ksm/blob/e7e24931c9df26c33d6e2a0ea9a44c78d3ced7a6/vmx.asm#L62 PopGeneralPurposeRegisterContext MACRO - pop rax - pop rcx - pop rdx - pop rbx - add rsp, 8 - pop rbp - pop rsi - pop rdi - pop r8 - pop r9 - pop r10 - pop r11 - pop r12 - pop r13 - pop r14 - pop r15 + pop rax + pop rcx + pop rdx + pop rbx + pop rbp ;rsp + pop rbp + pop rsi + pop rdi + pop r8 + pop r9 + pop r10 + pop r11 + pop r12 + pop r13 + pop r14 + pop r15 ENDM __invept PROC @@ -111,6 +111,8 @@ HvBeginInitializeLogicalProcessor ENDP ; and we have to handle the VMRESUME failure. ; Interrupts are automatically disabled for us at this point. HvEnterFromGuest PROC + ; rsp == 0x...............8, qword[rsp] == PVMM_GLOBAL_CONTEXT + ; Macro to push all GP registers PushGeneralPurposeRegisterContext @@ -123,15 +125,10 @@ HvEnterFromGuest PROC ; Second argument (RDX) is stack pointer, which is also the location of the general purpose registers mov rdx, rsp - ; Save XMM registers. The stack must be 16-byte aligned - ; or a #GP exception is generated. - sub rsp, 68h - movaps xmmword ptr [rsp], xmm0 - movaps xmmword ptr [rsp+10h], xmm1 - movaps xmmword ptr [rsp+20h], xmm2 - movaps xmmword ptr [rsp+30h], xmm3 - movaps xmmword ptr [rsp+40h], xmm4 - movaps xmmword ptr [rsp+50h], xmm5 + ; Save the x87 FPU, MMX, XMM, and MXCSR register state to m512byte. + ; The stack must be 16-byte aligned, or a #GP exception is generated. + sub rsp, 208h + fxsave [rsp] ; Call HvHandleVmExit to actually handle the ; incoming exit @@ -139,14 +136,9 @@ HvEnterFromGuest PROC call HvHandleVmExit add rsp, 20h - ; Restore XMM registers - movaps xmm0, xmmword ptr [rsp] - movaps xmm1, xmmword ptr [rsp+10h] - movaps xmm2, xmmword ptr [rsp+20h] - movaps xmm3, xmmword ptr [rsp+30h] - movaps xmm4, xmmword ptr [rsp+40h] - movaps xmm5, xmmword ptr [rsp+50h] - add rsp, 68h + ; Restore the x87 FPU, MMX, XMM, and MXCSR register state from m512byte. + fxrstor [rsp] + add rsp, 208h ; If it's not successful, we need to stop and figure out why test al, al From 22bfbf6f8b080d65655f572aca832ada57ea271a Mon Sep 17 00:00:00 2001 From: xorrsp <94297076+xorrsp@users.noreply.github.com> Date: Sun, 21 Nov 2021 09:16:48 +0800 Subject: [PATCH 10/10] Update vmm.h --- gbhv/vmm.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/gbhv/vmm.h b/gbhv/vmm.h index cd4399d..2b90195 100644 --- a/gbhv/vmm.h +++ b/gbhv/vmm.h @@ -39,7 +39,10 @@ typedef struct _VMM_HOST_STACK_REGION /* * Top of the host stack must always have a pointer to the global context. * This allows the exit handler to access the global context after the host area is loaded. + * In order to follow the x64 calling convention, must ensure that the end of rsp is 8 after entering HOST. + * So we need a 16-byte aligned member in front of GlobalContext. */ + DECLSPEC_ALIGN(16) UINT64 Alignment; PVMM_CONTEXT GlobalContext; } VMM_HOST_STACK_REGION, *PVMM_HOST_STACK_REGION;