HyperDbg/hyperdbg/hyperhv/code/assembly/AsmVmexitHandler.asm

244 lines
6.7 KiB
NASM

PUBLIC AsmVmexitHandler
PUBLIC AsmVmxoffRestoreXmmRegs
EXTERN VmxVmexitHandler:PROC
EXTERN VmxPerformVmresume:PROC
EXTERN VmxReturnStackPointerForVmxoff:PROC
EXTERN VmxReturnInstructionPointerForVmxoff:PROC
.code _text
;------------------------------------------------------------------------
AsmVmexitHandler PROC
push 0 ; we might be in an unaligned stack state, so the memory before stack might cause
; irql less or equal as it doesn't exist, so we just put some extra space avoid
; these kind of errors
; --------------- Save RFLAGS ----------------
pushfq ; Save the flags register (RFLAGS)
; ------------ Save XMM Registers ------------
; 16 Byte * 16 Byte = 256 + 4 = 260 (0x104 == 0x110 but let's align it to have better performance)
sub rsp, 0110h
movaps xmmword ptr [rsp+000h], xmm0 ; each xmm register 128 bit (16 Byte)
movaps xmmword ptr [rsp+010h], xmm1
movaps xmmword ptr [rsp+020h], xmm2
movaps xmmword ptr [rsp+030h], xmm3
movaps xmmword ptr [rsp+040h], xmm4
movaps xmmword ptr [rsp+050h], xmm5
;
; As per Microsoft ABI documentation, the following registers are nonvolatile
; So, MSVC compiler will save them on the stack if they are used in the function
; Thus, for the sake of performance, we comment them out
;
; movaps xmmword ptr [rsp+060h], xmm6
; movaps xmmword ptr [rsp+070h], xmm7
; movaps xmmword ptr [rsp+080h], xmm8
; movaps xmmword ptr [rsp+090h], xmm9
; movaps xmmword ptr [rsp+0a0h], xmm10
; movaps xmmword ptr [rsp+0b0h], xmm11
; movaps xmmword ptr [rsp+0c0h], xmm12
; movaps xmmword ptr [rsp+0d0h], xmm13
; movaps xmmword ptr [rsp+0e0h], xmm14
; movaps xmmword ptr [rsp+0f0h], xmm15
stmxcsr dword ptr [rsp+0100h] ; MxCsr is 4 Byte
; ------ Save General-purpose Registers ------
push r15
push r14
push r13
push r12
push r11
push r10
push r9
push r8
push rdi
push rsi
push rbp
push rbp ; rsp
push rbx
push rdx
push rcx
push rax
; ----------- Call VM-exit Handler -----------
mov rcx, rsp ; Fast call argument to PGUEST_REGS
sub rsp, 020h ; Free some space for Shadow Section
call VmxVmexitHandler
add rsp, 020h ; Restore the state
cmp al, 1 ; Check whether we have to turn off VMX or Not (the result is in RAX)
je AsmVmxoffHandler
; ----------- Restore XMM Registers ----------
RestoreState:
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
; ------------ Restore XMM Registers ------------
movaps xmm0, xmmword ptr [rsp+000h]
movaps xmm1, xmmword ptr [rsp+010h]
movaps xmm2, xmmword ptr [rsp+020h]
movaps xmm3, xmmword ptr [rsp+030h]
movaps xmm4, xmmword ptr [rsp+040h]
movaps xmm5, xmmword ptr [rsp+050h]
;
; As per Microsoft ABI documentation, the following registers are nonvolatile
; So, MSVC compiler will save them on the stack if they are used in the function
; Thus, for the sake of performance, we comment them out
;
; movaps xmm6, xmmword ptr [rsp+060h]
; movaps xmm7, xmmword ptr [rsp+070h]
; movaps xmm8, xmmword ptr [rsp+080h]
; movaps xmm9, xmmword ptr [rsp+090h]
; movaps xmm10, xmmword ptr [rsp+0a0h]
; movaps xmm11, xmmword ptr [rsp+0b0h]
; movaps xmm12, xmmword ptr [rsp+0c0h]
; movaps xmm13, xmmword ptr [rsp+0d0h]
; movaps xmm14, xmmword ptr [rsp+0e0h]
; movaps xmm15, xmmword ptr [rsp+0f0h]
ldmxcsr dword ptr [rsp+0100h]
add rsp, 0110h
; --------------- Restore RFLAGS ---------------
popfq ; Restore the flags register (RFLAGS)
; ----------------------------------------------
jmp VmxPerformVmresume
AsmVmexitHandler ENDP
;------------------------------------------------------------------------
AsmVmxoffRestoreXmmRegs PROC
; ------------ Restore XMM Registers ------------
movaps xmm0, xmmword ptr [rcx+000h]
movaps xmm1, xmmword ptr [rcx+010h]
movaps xmm2, xmmword ptr [rcx+020h]
movaps xmm3, xmmword ptr [rcx+030h]
movaps xmm4, xmmword ptr [rcx+040h]
movaps xmm5, xmmword ptr [rcx+050h]
;
; As per Microsoft ABI documentation, the following registers are nonvolatile
; So, MSVC compiler will save them on the stack if they are used in the function
; Thus, for the sake of performance, we comment them out
;
; movaps xmm6, xmmword ptr [rcx+060h]
; movaps xmm7, xmmword ptr [rcx+070h]
; movaps xmm8, xmmword ptr [rcx+080h]
; movaps xmm9, xmmword ptr [rcx+090h]
; movaps xmm10, xmmword ptr [rcx+0a0h]
; movaps xmm11, xmmword ptr [rcx+0b0h]
; movaps xmm12, xmmword ptr [rcx+0c0h]
; movaps xmm13, xmmword ptr [rcx+0d0h]
; movaps xmm14, xmmword ptr [rcx+0e0h]
; movaps xmm15, xmmword ptr [rcx+0f0h]
ldmxcsr dword ptr [rcx+0100h]
ret
AsmVmxoffRestoreXmmRegs ENDP
;------------------------------------------------------------------------
AsmVmxoffHandler PROC
; ------ Restore General-purpose Registers ------
RestoreState:
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
; ------------- Pass over XMM Regs -------------
; XMM registers are restored by AsmVmxoffRestoreXmmRegs
; Size of XMM registers are 110 bytes but we also remove the RFLAGS register (+8)
; so we have 118 bytes to remove from the stack
add rsp, 0118h
; ------------ Get Stack Pointer ---------------
sub rsp, 020h ; shadow space
call VmxReturnStackPointerForVmxoff
add rsp, 020h ; remove for shadow space
push rax ; save the current rsp, we will restore it later
; ------------ Get Instruction Pointer ---------
sub rsp, 020h ; shadow space
call VmxReturnInstructionPointerForVmxoff
add rsp, 020h ; remove for shadow space
pop rsp ; restore rsp
push rax ; push the instruction pointer
; ----------------------------------------------
; There might be some registers that are modified by above CALLs,
; but here we do not care about them since we are also in a function,
; so the caller do not expect us to preserve these volatile registers
xor rax, rax ; clear RAX to indicate VMXOFF was successful (VMCALL Status)
ret ; jump back to where we called Vmcall
AsmVmxoffHandler ENDP
;------------------------------------------------------------------------
END