HyperDbg/hyperdbg/include/platform/kernel/code/PlatformIntrinsicsVmx.c

456 lines
9.9 KiB
C

/**
* @file PlatformIntrinsicsVmx.c
* @author Sina Karvandi (sina@hyperdbg.org)
* @brief Implementation of cross platform APIs for intrinsic functions (VMX instructions)
* @details
* @version 0.19
* @date 2026-04-27
*
* @copyright This project is released under the GNU Public License v3.
*
*/
#include "pch.h"
#if defined(__linux__)
# include "../header/PlatformIntrinsicsVmx.h"
#endif // defined(__linux__)
#if defined(__linux__)
/**
* @brief Linux inline-asm helper for VMREAD
* Mirrors __vmx_vmread: returns 0=success, 1=VMfail valid (ZF), 2=VMfail invalid (CF)
*/
static inline UCHAR
__linux_vmx_vmread(size_t Field, size_t * FieldValue)
{
unsigned char cf, zf;
__asm__ __volatile__(
"vmread %[field], %[val] \n\t"
"setc %[cf] \n\t"
"setz %[zf] \n\t"
: [val] "=rm"(*FieldValue),
[cf] "=qm"(cf),
[zf] "=qm"(zf)
: [field] "r"(Field)
: "cc");
return cf ? 2 : (zf ? 1 : 0);
}
/**
* @brief Linux inline-asm helper for VMWRITE
* Mirrors __vmx_vmwrite: returns 0=success, 1=VMfail valid (ZF), 2=VMfail invalid (CF)
*/
static inline UCHAR
__linux_vmx_vmwrite(size_t Field, size_t FieldValue)
{
unsigned char cf, zf;
__asm__ __volatile__(
"vmwrite %[val], %[field] \n\t"
"setc %[cf] \n\t"
"setz %[zf] \n\t"
: [cf] "=qm"(cf),
[zf] "=qm"(zf)
: [val] "rm"(FieldValue),
[field] "r"(Field)
: "cc");
return cf ? 2 : (zf ? 1 : 0);
}
/**
* @brief Linux inline-asm helper for VMPTRST
* Stores the current VMCS pointer into the given physical address
*/
static inline VOID
__linux_vmx_vmptrst(UINT64 * VmcsPhysicalAddress)
{
__asm__ __volatile__(
"vmptrst %[addr]"
:
: [addr] "m"(*VmcsPhysicalAddress)
: "memory");
}
/**
* @brief Linux inline-asm helper for VMPTRLD
* Returns 0=success, 1=VMfail valid (ZF), 2=VMfail invalid (CF)
*/
static inline UCHAR
__linux_vmx_vmptrld(UINT64 * VmcsPhysicalAddress)
{
unsigned char cf, zf;
__asm__ __volatile__(
"vmptrld %[addr] \n\t"
"setc %[cf] \n\t"
"setz %[zf] \n\t"
: [cf] "=qm"(cf),
[zf] "=qm"(zf)
: [addr] "m"(*VmcsPhysicalAddress)
: "cc", "memory");
return cf ? 2 : (zf ? 1 : 0);
}
/**
* @brief Linux inline-asm helper for VMCLEAR
* Returns 0=success, 1=VMfail valid (ZF), 2=VMfail invalid (CF)
*/
static inline UCHAR
__linux_vmx_vmclear(UINT64 * VmcsPhysicalAddress)
{
unsigned char cf, zf;
__asm__ __volatile__(
"vmclear %[addr] \n\t"
"setc %[cf] \n\t"
"setz %[zf] \n\t"
: [cf] "=qm"(cf),
[zf] "=qm"(zf)
: [addr] "m"(*VmcsPhysicalAddress)
: "cc", "memory");
return cf ? 2 : (zf ? 1 : 0);
}
/**
* @brief Linux inline-asm helper for VMXON
* Returns 0=success, 1=VMfail valid (ZF), 2=VMfail invalid (CF)
*/
static inline UCHAR
__linux_vmx_vmxon(UINT64 * VmxonRegionPhysicalAddress)
{
unsigned char cf, zf;
__asm__ __volatile__(
"vmxon %[addr] \n\t"
"setc %[cf] \n\t"
"setz %[zf] \n\t"
: [cf] "=qm"(cf),
[zf] "=qm"(zf)
: [addr] "m"(*VmxonRegionPhysicalAddress)
: "cc", "memory");
return cf ? 2 : (zf ? 1 : 0);
}
#endif // defined(__linux__)
/**
* @brief VMX VMREAD instruction (64-bit)
* @param Field
* @param FieldValue
*
* @return UCHAR
*/
inline UCHAR
VmxVmread64(size_t Field,
UINT64 FieldValue)
{
#if defined(_WIN32) || defined(_WIN64)
return __vmx_vmread((size_t)Field, (size_t *)FieldValue);
#elif defined(__linux__)
return __linux_vmx_vmread((size_t)Field, (size_t *)FieldValue);
#else
# error "Unsupported platform"
#endif
}
/**
* @brief VMX VMREAD instruction (32-bit)
* @param Field
* @param FieldValue
*
* @return UCHAR
*/
inline UCHAR
VmxVmread32(size_t Field,
UINT32 FieldValue)
{
UINT64 TargetField = 0ull;
TargetField = FieldValue;
#if defined(_WIN32) || defined(_WIN64)
return __vmx_vmread((size_t)Field, (size_t *)TargetField);
#elif defined(__linux__)
return __linux_vmx_vmread((size_t)Field, (size_t *)TargetField);
#else
# error "Unsupported platform"
#endif
}
/**
* @brief VMX VMREAD instruction (16-bit)
* @param Field
* @param FieldValue
*
* @return UCHAR
*/
inline UCHAR
VmxVmread16(size_t Field,
UINT16 FieldValue)
{
UINT64 TargetField = 0ull;
TargetField = FieldValue;
#if defined(_WIN32) || defined(_WIN64)
return __vmx_vmread((size_t)Field, (size_t *)TargetField);
#elif defined(__linux__)
return __linux_vmx_vmread((size_t)Field, (size_t *)TargetField);
#else
# error "Unsupported platform"
#endif
}
/**
* @brief VMX VMREAD instruction (64-bit, pointer variant)
* @param Field
* @param FieldValue
*
* @return UCHAR
*/
inline UCHAR
VmxVmread64P(size_t Field,
UINT64 * FieldValue)
{
#if defined(_WIN32) || defined(_WIN64)
return __vmx_vmread((size_t)Field, (size_t *)FieldValue);
#elif defined(__linux__)
return __linux_vmx_vmread((size_t)Field, (size_t *)FieldValue);
#else
# error "Unsupported platform"
#endif
}
/**
* @brief VMX VMREAD instruction (32-bit, pointer variant)
* @param Field
* @param FieldValue
*
* @return UCHAR
*/
inline UCHAR
VmxVmread32P(size_t Field,
UINT32 * FieldValue)
{
UINT64 TargetField = 0ull;
TargetField = (UINT64)FieldValue;
#if defined(_WIN32) || defined(_WIN64)
return __vmx_vmread((size_t)Field, (size_t *)TargetField);
#elif defined(__linux__)
return __linux_vmx_vmread((size_t)Field, (size_t *)TargetField);
#else
# error "Unsupported platform"
#endif
}
/**
* @brief VMX VMREAD instruction (16-bit, pointer variant)
* @param Field
* @param FieldValue
*
* @return UCHAR
*/
inline UCHAR
VmxVmread16P(size_t Field,
UINT16 * FieldValue)
{
UINT64 TargetField = 0ull;
TargetField = (UINT64)FieldValue;
#if defined(_WIN32) || defined(_WIN64)
return __vmx_vmread((size_t)Field, (size_t *)TargetField);
#elif defined(__linux__)
return __linux_vmx_vmread((size_t)Field, (size_t *)TargetField);
#else
# error "Unsupported platform"
#endif
}
/**
* @brief VMX VMWRITE instruction (64-bit)
* @param Field
* @param FieldValue
*
* @return UCHAR
*/
inline UCHAR
VmxVmwrite64(size_t Field,
UINT64 FieldValue)
{
#if defined(_WIN32) || defined(_WIN64)
return __vmx_vmwrite((size_t)Field, (size_t)FieldValue);
#elif defined(__linux__)
return __linux_vmx_vmwrite((size_t)Field, (size_t)FieldValue);
#else
# error "Unsupported platform"
#endif
}
/**
* @brief VMX VMWRITE instruction (32-bit)
* @param Field
* @param FieldValue
*
* @return UCHAR
*/
inline UCHAR
VmxVmwrite32(size_t Field,
UINT32 FieldValue)
{
UINT64 TargetValue = NULL64_ZERO;
TargetValue = (UINT64)FieldValue;
#if defined(_WIN32) || defined(_WIN64)
return __vmx_vmwrite((size_t)Field, (size_t)TargetValue);
#elif defined(__linux__)
return __linux_vmx_vmwrite((size_t)Field, (size_t)TargetValue);
#else
# error "Unsupported platform"
#endif
}
/**
* @brief VMX VMWRITE instruction (16-bit)
* @param Field
* @param FieldValue
*
* @return UCHAR
*/
inline UCHAR
VmxVmwrite16(size_t Field,
UINT16 FieldValue)
{
UINT64 TargetValue = NULL64_ZERO;
TargetValue = (UINT64)FieldValue;
#if defined(_WIN32) || defined(_WIN64)
return __vmx_vmwrite((size_t)Field, (size_t)TargetValue);
#elif defined(__linux__)
return __linux_vmx_vmwrite((size_t)Field, (size_t)TargetValue);
#else
# error "Unsupported platform"
#endif
}
/**
* @brief VMX VMPTRST instruction
*
* @param VmcsPhysicalAddress
*
* @return VOID
*/
inline VOID
VmxVmptrst(UINT64 * VmcsPhysicalAddress)
{
#if defined(_WIN32) || defined(_WIN64)
__vmx_vmptrst(VmcsPhysicalAddress);
#elif defined(__linux__)
__linux_vmx_vmptrst(VmcsPhysicalAddress);
#else
# error "Unsupported platform"
#endif
}
/**
* @brief VMX VMRESUME instruction
*
* @return VOID
*/
inline VOID
VmxVmresume(VOID)
{
#if defined(_WIN32) || defined(_WIN64)
__vmx_vmresume();
#elif defined(__linux__)
__asm__ __volatile__("vmresume" ::: "cc", "memory");
#else
# error "Unsupported platform"
#endif
}
/**
* @brief VMX VMXOFF instruction
*
* @return VOID
*/
inline VOID
VmxVmxoff(VOID)
{
#if defined(_WIN32) || defined(_WIN64)
__vmx_off();
#elif defined(__linux__)
__asm__ __volatile__("vmxoff" ::: "cc", "memory");
#else
# error "Unsupported platform"
#endif
}
/**
* @brief VMX VMLAUNCH instruction
*
* @return VOID
*/
inline VOID
VmxVmlaunch(VOID)
{
#if defined(_WIN32) || defined(_WIN64)
__vmx_vmlaunch();
#elif defined(__linux__)
__asm__ __volatile__("vmlaunch" ::: "cc", "memory");
#else
# error "Unsupported platform"
#endif
}
/**
* @brief VMX VMPTRLD instruction
*
* @param VmcsPhysicalAddress
*
* @return UCHAR
*/
inline UCHAR
VmxVmptrld(UINT64 * VmcsPhysicalAddress)
{
#if defined(_WIN32) || defined(_WIN64)
return __vmx_vmptrld(VmcsPhysicalAddress);
#elif defined(__linux__)
return __linux_vmx_vmptrld(VmcsPhysicalAddress);
#else
# error "Unsupported platform"
#endif
}
/**
* @brief VMX VMCLEAR instruction
*
* @param VmcsPhysicalAddress
*
* @return UCHAR
*/
inline UCHAR
VmxVmclear(UINT64 * VmcsPhysicalAddress)
{
#if defined(_WIN32) || defined(_WIN64)
return __vmx_vmclear(VmcsPhysicalAddress);
#elif defined(__linux__)
return __linux_vmx_vmclear(VmcsPhysicalAddress);
#else
# error "Unsupported platform"
#endif
}
/**
* @brief VMX VMXON instruction
*
* @param VmxonRegionPhysicalAddress
*
* @return UCHAR
*/
inline UCHAR
VmxVmxon(UINT64 * VmxonRegionPhysicalAddress)
{
#if defined(_WIN32) || defined(_WIN64)
return __vmx_on(VmxonRegionPhysicalAddress);
#elif defined(__linux__)
return __linux_vmx_vmxon(VmxonRegionPhysicalAddress);
#else
# error "Unsupported platform"
#endif
}