HyperDbg Debugger
Loading...
Searching...
No Matches
Vmx.c File Reference

VMX Instructions and VMX Related Functions. More...

#include "pch.h"

Functions

UCHAR VmxVmread64 (size_t Field, UINT64 FieldValue)
 VMX VMREAD instruction (64-bit)
 
UCHAR VmxVmread32 (size_t Field, UINT32 FieldValue)
 VMX VMREAD instruction (32-bit)
 
UCHAR VmxVmread16 (size_t Field, UINT16 FieldValue)
 VMX VMREAD instruction (16-bit)
 
UCHAR VmxVmread64P (size_t Field, UINT64 *FieldValue)
 VMX VMREAD instruction (64-bit)
 
UCHAR VmxVmread32P (size_t Field, UINT32 *FieldValue)
 VMX VMREAD instruction (32-bit)
 
UCHAR VmxVmread16P (size_t Field, UINT16 *FieldValue)
 VMX VMREAD instruction (16-bit)
 
UCHAR VmxVmwrite64 (size_t Field, UINT64 FieldValue)
 VMX VMWRITE instruction (64-bit)
 
UCHAR VmxVmwrite32 (size_t Field, UINT32 FieldValue)
 VMX VMWRITE instruction (32-bit)
 
UCHAR VmxVmwrite16 (size_t Field, UINT16 FieldValue)
 VMX VMWRITE instruction (16-bit)
 
BOOLEAN VmxCheckVmxSupport ()
 Check whether VMX Feature is supported or not.
 
BOOLEAN VmxGetCurrentExecutionMode ()
 Check current execution mode (vmx-root and non-root)
 
BOOLEAN VmxGetCurrentLaunchState ()
 Check if the VMX is launched or not.
 
BOOLEAN VmxInitialize ()
 Initialize the VMX operation.
 
BOOLEAN VmxPerformVirtualizationOnAllCores ()
 Initialize essential VMX Operation tasks.
 
BOOLEAN VmxPerformVirtualizationOnSpecificCore ()
 Allocates Vmx regions for all logical cores (Vmxon region and Vmcs region)
 
VOID VmxFixCr4AndCr0Bits ()
 Fix values for cr0 and cr4 bits.
 
BOOLEAN VmxCheckIsOnVmxRoot ()
 It can deterministically check whether the caller is on vmx-root mode or not.
 
BOOLEAN VmxVirtualizeCurrentSystem (PVOID GuestStack)
 Initialize VMX Operation.
 
BOOLEAN VmxTerminate ()
 Broadcast to terminate VMX on all logical cores.
 
VOID VmxVmptrst ()
 Implementation of VMPTRST instruction.
 
_Use_decl_annotations_ BOOLEAN VmxClearVmcsState (VIRTUAL_MACHINE_STATE *VCpu)
 Clearing Vmcs status using vmclear instruction.
 
_Use_decl_annotations_ BOOLEAN VmxLoadVmcs (VIRTUAL_MACHINE_STATE *VCpu)
 Implementation of VMPTRLD instruction.
 
_Use_decl_annotations_ BOOLEAN VmxSetupVmcs (VIRTUAL_MACHINE_STATE *VCpu, PVOID GuestStack)
 Create and Configure a Vmcs Layout.
 
VOID VmxVmresume ()
 Resume VM using VMRESUME instruction.
 
UINT64 VmxVmfunc (UINT32 EptpIndex, UINT32 Function)
 VMFUNC instruction.
 
VOID VmxVmxoff (VIRTUAL_MACHINE_STATE *VCpu)
 Prepare and execute Vmxoff instruction.
 
UINT64 VmxReturnStackPointerForVmxoff ()
 Get the RIP of guest (VMCS_GUEST_RIP) in the case of return from VMXOFF.
 
UINT64 VmxReturnInstructionPointerForVmxoff ()
 Get the RIP of guest (VMCS_GUEST_RIP) in the case of return from VMXOFF.
 
VOID VmxPerformTermination ()
 Terminate Vmx on all logical cores.
 
UINT32 VmxCompatibleStrlen (const CHAR *S)
 implementation of vmx-root mode compatible strlen
 
UINT32 VmxCompatibleWcslen (const wchar_t *S)
 implementation of vmx-root mode compatible wcslen
 
INT32 VmxCompatibleStrcmp (const CHAR *Address1, const CHAR *Address2, SIZE_T Num, BOOLEAN IsStrncmp)
 implementation of vmx-root mode compatible strcmp and strncmp
 
INT32 VmxCompatibleWcscmp (const wchar_t *Address1, const wchar_t *Address2, SIZE_T Num, BOOLEAN IsWcsncmp)
 implementation of vmx-root mode compatible wcscmp and wcsncmp
 
INT32 VmxCompatibleMemcmp (const CHAR *Address1, const CHAR *Address2, size_t Count)
 implementation of vmx-root mode compatible memcmp
 

Detailed Description

VMX Instructions and VMX Related Functions.

Author
Sina Karvandi (sina@.nosp@m.hype.nosp@m.rdbg..nosp@m.org)
Version
0.1
Date
2020-04-11

Function Documentation

◆ VmxCheckIsOnVmxRoot()

BOOLEAN VmxCheckIsOnVmxRoot ( )

It can deterministically check whether the caller is on vmx-root mode or not.

Returns
BOOLEAN Returns true if current operation mode is vmx-root and false if current operation mode is vmx non-root
577{
578 UINT64 VmcsLink = 0;
579
580 __try
581 {
582 if (!__vmx_vmread(VMCS_GUEST_VMCS_LINK_POINTER, &VmcsLink))
583 {
584 if (VmcsLink != 0)
585 {
586 return TRUE;
587 }
588 }
589 }
590 __except (1)
591 {
592 }
593
594 return FALSE;
595}
#define TRUE
Definition BasicTypes.h:55
#define FALSE
Definition BasicTypes.h:54
unsigned __int64 UINT64
Definition BasicTypes.h:21

◆ VmxCheckVmxSupport()

BOOLEAN VmxCheckVmxSupport ( )

Check whether VMX Feature is supported or not.

Returns
BOOLEAN Returns true if vmx is supported or false if it's not supported
167{
168 CPUID Data = {0};
169 IA32_FEATURE_CONTROL_REGISTER FeatureControlMsr = {0};
170
171 //
172 // Gets Processor Info and Feature Bits
173 //
174 __cpuid((int *)&Data, 1);
175
176 //
177 // Check For VMX Bit CPUID.ECX[5]
178 //
179 if (!_bittest((const LONG *)&Data.ecx, 5))
180 {
181 //
182 // returns FALSE if vmx is not supported
183 //
184 return FALSE;
185 }
186
187 FeatureControlMsr.AsUInt = __readmsr(IA32_FEATURE_CONTROL);
188
189 //
190 // Commented because of https://stackoverflow.com/questions/34900224/
191 // and https://github.com/HyperDbg/HyperDbg/issues/24
192 // the problem is when writing to IA32_FEATURE_CONTROL MSR, the lock bit
193 // of this MSR Is not set to 0 on most computers, if the user enabled VT-X
194 // from the BIOS the VMXON will be already set so checking lock bit and
195 // then writing to EnableVmxon again is not meaningful since its already
196 // there
197 //
198
199 //
200 // if (FeatureControlMsr.Fields.Lock == 0)
201 // {
202 // FeatureControlMsr.Fields.Lock = TRUE;
203 // FeatureControlMsr.Fields.EnableVmxon = TRUE;
204 // __writemsr(IA32_FEATURE_CONTROL, FeatureControlMsr.Flags);
205 // }
206
207 if (FeatureControlMsr.EnableVmxOutsideSmx == FALSE)
208 {
209 LogError("Err, you should enable vt-x from BIOS");
210 return FALSE;
211 }
212
213 return TRUE;
214}
#define LogError(format,...)
Log in the case of error.
Definition HyperDbgHyperLogIntrinsics.h:113
Start of Optional Data
Definition script_buffer.hex.txt:8
CPUID Registers.
Definition Common.h:236

◆ VmxClearVmcsState()

_Use_decl_annotations_ BOOLEAN VmxClearVmcsState ( VIRTUAL_MACHINE_STATE * VCpu)

Clearing Vmcs status using vmclear instruction.

Parameters
VCpu
Returns
BOOLEAN If vmclear execution was successful it returns true otherwise and if there was error with vmclear then it returns false
767{
768 UINT8 VmclearStatus;
769
770 //
771 // Clear the state of the VMCS to inactive
772 //
773 VmclearStatus = __vmx_vmclear(&VCpu->VmcsRegionPhysicalAddress);
774
775 LogDebugInfo("VMCS VMCLEAR status : 0x%x", VmclearStatus);
776
777 if (VmclearStatus)
778 {
779 //
780 // Otherwise terminate the VMX
781 //
782 LogDebugInfo("VMCS failed to clear, status : 0x%x", VmclearStatus);
783 __vmx_off();
784 return FALSE;
785 }
786 return TRUE;
787}
unsigned char UINT8
Definition BasicTypes.h:46
#define LogDebugInfo(format,...)
Log, initialize boot information and debug information.
Definition HyperDbgHyperLogIntrinsics.h:155
UINT64 VmcsRegionPhysicalAddress
Definition State.h:312

◆ VmxCompatibleMemcmp()

INT32 VmxCompatibleMemcmp ( const CHAR * Address1,
const CHAR * Address2,
size_t Count )

implementation of vmx-root mode compatible memcmp

Parameters
Address1
Address2
Count
Returns
INT32 0x2 indicates error, otherwise the same result as memcmp in string.h
1749{
1750 CHAR C1 = NULL_ZERO, C2 = NULL_ZERO;
1751 INT32 Result = 0;
1752 UINT64 AlignedAddress1, AlignedAddress2;
1753 CR3_TYPE GuestCr3;
1754 CR3_TYPE OriginalCr3;
1755
1756 AlignedAddress1 = (UINT64)PAGE_ALIGN((UINT64)Address1);
1757 AlignedAddress2 = (UINT64)PAGE_ALIGN((UINT64)Address2);
1758
1759 //
1760 // Find the current process cr3
1761 //
1763
1764 //
1765 // Move to new cr3
1766 //
1767 OriginalCr3.Flags = __readcr3();
1768 __writecr3(GuestCr3.Flags);
1769
1770 //
1771 // First check
1772 //
1773 if (!CheckAccessValidityAndSafety(AlignedAddress1, sizeof(wchar_t)) || !CheckAccessValidityAndSafety(AlignedAddress2, sizeof(wchar_t)))
1774 {
1775 //
1776 // Error
1777 //
1778
1779 //
1780 // Move back to original cr3
1781 //
1782 __writecr3(OriginalCr3.Flags);
1783 return 0x2;
1784 }
1785
1786 while (Count-- > 0 && !Result)
1787 {
1788 /*
1789 C1 = *Address1;
1790 */
1791 MemoryMapperReadMemorySafe((UINT64)Address1, &C1, sizeof(CHAR));
1792
1793 /*
1794 C2 = *Address2;
1795 */
1796 MemoryMapperReadMemorySafe((UINT64)Address2, &C2, sizeof(CHAR));
1797
1798 Address1++;
1799 Address2++;
1800
1801 if (!((UINT64)AlignedAddress1 & (PAGE_SIZE - 1)))
1802 {
1803 if (!CheckAccessValidityAndSafety((UINT64)AlignedAddress1, sizeof(wchar_t)))
1804 {
1805 //
1806 // Error
1807 //
1808
1809 //
1810 // Move back to original cr3
1811 //
1812 __writecr3(OriginalCr3.Flags);
1813 return 0x2;
1814 }
1815 }
1816
1817 if (!((UINT64)AlignedAddress2 & (PAGE_SIZE - 1)))
1818 {
1819 if (!CheckAccessValidityAndSafety((UINT64)AlignedAddress2, sizeof(wchar_t)))
1820 {
1821 //
1822 // Error
1823 //
1824
1825 //
1826 // Move back to original cr3
1827 //
1828 __writecr3(OriginalCr3.Flags);
1829 return 0x2;
1830 }
1831 }
1832
1833 Result = C1 - C2;
1834 }
1835
1836 if (Result < 0)
1837 {
1838 Result = -1;
1839 }
1840 else if (Result > 0)
1841 {
1842 Result = 1;
1843 }
1844
1845 //
1846 // Move back to original cr3
1847 //
1848 __writecr3(OriginalCr3.Flags);
1849 return Result;
1850}
BOOLEAN CheckAccessValidityAndSafety(UINT64 TargetAddress, UINT32 Size)
Check the safety to access the memory.
Definition AddressCheck.c:156
signed int INT32
Definition BasicTypes.h:44
#define NULL_ZERO
Definition BasicTypes.h:51
char CHAR
Definition BasicTypes.h:31
CR3_TYPE LayoutGetCurrentProcessCr3()
Get cr3 of the target running process.
Definition Layout.c:55
_Use_decl_annotations_ BOOLEAN MemoryMapperReadMemorySafe(UINT64 VaAddressToRead, PVOID BufferToSaveMemory, SIZE_T SizeToRead)
Read memory safely by mapping the buffer (It's a wrapper)
Definition MemoryMapper.c:1101
#define PAGE_SIZE
Size of each page (4096 bytes)
Definition common.h:69
#define PAGE_ALIGN(Va)
Aligning a page.
Definition common.h:75
CR3 Structure.
Definition BasicTypes.h:130
UINT64 Flags
Definition BasicTypes.h:133

◆ VmxCompatibleStrcmp()

INT32 VmxCompatibleStrcmp ( const CHAR * Address1,
const CHAR * Address2,
SIZE_T Num,
BOOLEAN IsStrncmp )

implementation of vmx-root mode compatible strcmp and strncmp

Parameters
Address1
Address2
Numparam IsStrncmp
Returns
INT32 0x2 indicates error, otherwise the same result as strcmp in string.h
1476{
1477 CHAR C1 = NULL_ZERO, C2 = NULL_ZERO;
1478 INT32 Result = 0;
1479 UINT32 Count = 0;
1480 UINT64 AlignedAddress1, AlignedAddress2;
1481 CR3_TYPE GuestCr3;
1482 CR3_TYPE OriginalCr3;
1483
1484 AlignedAddress1 = (UINT64)PAGE_ALIGN((UINT64)Address1);
1485 AlignedAddress2 = (UINT64)PAGE_ALIGN((UINT64)Address2);
1486
1487 //
1488 // Find the current process cr3
1489 //
1491
1492 //
1493 // Move to new cr3
1494 //
1495 OriginalCr3.Flags = __readcr3();
1496 __writecr3(GuestCr3.Flags);
1497
1498 //
1499 // First check
1500 //
1501 if (!CheckAccessValidityAndSafety(AlignedAddress1, sizeof(CHAR)) || !CheckAccessValidityAndSafety(AlignedAddress2, sizeof(CHAR)))
1502 {
1503 //
1504 // Error
1505 //
1506
1507 //
1508 // Move back to original cr3
1509 //
1510 __writecr3(OriginalCr3.Flags);
1511 return 0x2;
1512 }
1513
1514 do
1515 {
1516 //
1517 // Check to see if we have byte number constraints
1518 //
1519 if (IsStrncmp)
1520 {
1521 if (Count == Num)
1522 {
1523 //
1524 // Maximum number of bytes reached
1525 //
1526 break;
1527 }
1528 else
1529 {
1530 //
1531 // Maximum number of bytes not reached
1532 //
1533 Count++;
1534 }
1535 }
1536
1537 /*
1538 C1 = *Address1;
1539 */
1540 MemoryMapperReadMemorySafe((UINT64)Address1, &C1, sizeof(CHAR));
1541
1542 /*
1543 C2 = *Address2;
1544 */
1545 MemoryMapperReadMemorySafe((UINT64)Address2, &C2, sizeof(CHAR));
1546
1547 Address1++;
1548 Address2++;
1549
1550 if (!((UINT64)AlignedAddress1 & (PAGE_SIZE - 1)))
1551 {
1552 if (!CheckAccessValidityAndSafety((UINT64)AlignedAddress1, sizeof(CHAR)))
1553 {
1554 //
1555 // Error
1556 //
1557
1558 //
1559 // Move back to original cr3
1560 //
1561 __writecr3(OriginalCr3.Flags);
1562 return 0x2;
1563 }
1564 }
1565
1566 if (!((UINT64)AlignedAddress2 & (PAGE_SIZE - 1)))
1567 {
1568 if (!CheckAccessValidityAndSafety((UINT64)AlignedAddress2, sizeof(CHAR)))
1569 {
1570 //
1571 // Error
1572 //
1573
1574 //
1575 // Move back to original cr3
1576 //
1577 __writecr3(OriginalCr3.Flags);
1578 return 0x2;
1579 }
1580 }
1581 Result = C1 - C2;
1582 } while (!Result && C2);
1583
1584 if (Result < 0)
1585 {
1586 Result = -1;
1587 }
1588 else if (Result > 0)
1589 {
1590 Result = 1;
1591 }
1592
1593 //
1594 // Move back to original cr3
1595 //
1596 __writecr3(OriginalCr3.Flags);
1597 return Result;
1598}
unsigned int UINT32
Definition BasicTypes.h:48

◆ VmxCompatibleStrlen()

UINT32 VmxCompatibleStrlen ( const CHAR * S)

implementation of vmx-root mode compatible strlen

Parameters
S
Returns
UINT32 If 0x0 indicates an error, otherwise length of the string
1291{
1292 CHAR Temp = NULL_ZERO;
1293 UINT32 Count = 0;
1294 UINT64 AlignedAddress;
1295 CR3_TYPE GuestCr3;
1296 CR3_TYPE OriginalCr3;
1297
1298 AlignedAddress = (UINT64)PAGE_ALIGN((UINT64)S);
1299
1300 //
1301 // Find the current process cr3
1302 //
1304
1305 //
1306 // Move to new cr3
1307 //
1308 OriginalCr3.Flags = __readcr3();
1309 __writecr3(GuestCr3.Flags);
1310
1311 //
1312 // First check
1313 //
1314 if (!CheckAccessValidityAndSafety(AlignedAddress, sizeof(CHAR)))
1315 {
1316 //
1317 // Error
1318 //
1319
1320 //
1321 // Move back to original cr3
1322 //
1323 __writecr3(OriginalCr3.Flags);
1324 return 0;
1325 }
1326
1327 while (TRUE)
1328 {
1329 /*
1330 Temp = *S;
1331 */
1332 MemoryMapperReadMemorySafe((UINT64)S, &Temp, sizeof(CHAR));
1333
1334 if (Temp != '\0')
1335 {
1336 Count++;
1337 S++;
1338 }
1339 else
1340 {
1341 //
1342 // Move back to original cr3
1343 //
1344 __writecr3(OriginalCr3.Flags);
1345 return Count;
1346 }
1347
1348 if (!((UINT64)S & (PAGE_SIZE - 1)))
1349 {
1350 if (!CheckAccessValidityAndSafety((UINT64)S, sizeof(CHAR)))
1351 {
1352 //
1353 // Error
1354 //
1355
1356 //
1357 // Move back to original cr3
1358 //
1359 __writecr3(OriginalCr3.Flags);
1360 return 0;
1361 }
1362 }
1363 }
1364
1365 //
1366 // Move back to original cr3
1367 //
1368 __writecr3(OriginalCr3.Flags);
1369}
ThreeOpFunc1 interlocked_compare_exchange ThreeOpFunc2 event_inject_error_code memcpy TwoOpFunc1 ed eb eq interlocked_exchange interlocked_exchange_add TwoOpFunc2 spinlock_lock_custom_wait event_inject OneOpFunc1 poi db dd dw dq neg hi low not check_address disassemble_len disassemble_len32 disassemble_len64 interlocked_increment interlocked_decrement reference physical_to_virtual virtual_to_physical OneOpFunc2 print formats event_enable event_disable event_clear test_statement spinlock_lock spinlock_unlock event_sc OneOpFunc3 strlen TwoOpFunc3 strcmp ThreeOpFunc3 memcmp strncmp ThreeOpFunc4 wcsncmp OneOpFunc4 wcslen TwoOpFunc4 wcscmp ZeroOpFunc1 pause flush event_trace_step event_trace_step_in event_trace_step_out event_trace_instrumentation_step event_trace_instrumentation_step_in VarArgFunc1 printf OperatorsTwoOperand or xor and asr asl add sub mul div mod gt lt egt elt equal neq OperatorsOneOperand inc dec reference dereference SemantiRules start_of_if jmp jz jnz jmp_to_end_and_jzcompleted end_of_if start_of_while end_of_while vargstart mov start_of_do_while start_of_do_while_commands end_of_do_while start_of_for for_inc_dec start_of_for_ommands end_of_if ignore_lvalue push pop call ret Registers rax eax ax ah al rcx ecx cx ch cl rdx edx dx dh dl rbx ebx bx bh bl rsp esp sp spl rbp ebp bp bpl rsi esi si sil rdi edi di dil r8 r8d r8w r8h r8l r9 r9d r9w r9h r9l r10 r10d r10w r10h r10l r11 r11d r11w r11h r11l r12 r12d r12w r12h r12l r13 r13d r13w r13h r13l r14 r14d r14w r14h r14l r15 r15d r15w r15h r15l ds es fs gs cs ss rflags eflags flags cf pf af zf sf tf if df of iopl nt rf vm ac vif vip id rip eip ip idtr ldtr gdtr tr cr0 cr2 cr3 cr4 cr8 dr0 dr1 dr2 dr3 dr6 dr7 PseudoRegisters pid tid pname core proc thread peb teb ip buffer context event_tag event_id event_stage date time S STATEMENT S S
Definition Grammar.txt:51

◆ VmxCompatibleWcscmp()

INT32 VmxCompatibleWcscmp ( const wchar_t * Address1,
const wchar_t * Address2,
SIZE_T Num,
BOOLEAN IsWcsncmp )

implementation of vmx-root mode compatible wcscmp and wcsncmp

Parameters
Address1
Address2
Num
IsWcsncmp
Returns
INT32 0x2 indicates error, otherwise the same result as wcscmp in string.h
1614{
1615 wchar_t C1 = NULL_ZERO, C2 = NULL_ZERO;
1616 INT32 Result = 0;
1617 UINT32 Count = 0;
1618 UINT64 AlignedAddress1, AlignedAddress2;
1619 CR3_TYPE GuestCr3;
1620 CR3_TYPE OriginalCr3;
1621
1622 AlignedAddress1 = (UINT64)PAGE_ALIGN((UINT64)Address1);
1623 AlignedAddress2 = (UINT64)PAGE_ALIGN((UINT64)Address2);
1624
1625 //
1626 // Find the current process cr3
1627 //
1629
1630 //
1631 // Move to new cr3
1632 //
1633 OriginalCr3.Flags = __readcr3();
1634 __writecr3(GuestCr3.Flags);
1635
1636 //
1637 // First check
1638 //
1639 if (!CheckAccessValidityAndSafety(AlignedAddress1, sizeof(wchar_t)) || !CheckAccessValidityAndSafety(AlignedAddress2, sizeof(wchar_t)))
1640 {
1641 //
1642 // Error
1643 //
1644
1645 //
1646 // Move back to original cr3
1647 //
1648 __writecr3(OriginalCr3.Flags);
1649 return 0x2;
1650 }
1651
1652 do
1653 {
1654 //
1655 // Check to see if we have byte number constraints
1656 //
1657 if (IsWcsncmp)
1658 {
1659 if (Count == Num)
1660 {
1661 //
1662 // Maximum number of bytes reached
1663 //
1664 break;
1665 }
1666 else
1667 {
1668 //
1669 // Maximum number of bytes not reached
1670 //
1671 Count++;
1672 }
1673 }
1674
1675 /*
1676 C1 = *Address1;
1677 */
1678 MemoryMapperReadMemorySafe((UINT64)Address1, &C1, sizeof(wchar_t));
1679
1680 /*
1681 C2 = *Address2;
1682 */
1683 MemoryMapperReadMemorySafe((UINT64)Address2, &C2, sizeof(wchar_t));
1684
1685 Address1++;
1686 Address2++;
1687
1688 if (!((UINT64)AlignedAddress1 & (PAGE_SIZE - 1)))
1689 {
1690 if (!CheckAccessValidityAndSafety((UINT64)AlignedAddress1, sizeof(wchar_t)))
1691 {
1692 //
1693 // Error
1694 //
1695
1696 //
1697 // Move back to original cr3
1698 //
1699 __writecr3(OriginalCr3.Flags);
1700 return 0x2;
1701 }
1702 }
1703
1704 if (!((UINT64)AlignedAddress2 & (PAGE_SIZE - 1)))
1705 {
1706 if (!CheckAccessValidityAndSafety((UINT64)AlignedAddress2, sizeof(wchar_t)))
1707 {
1708 //
1709 // Error
1710 //
1711
1712 //
1713 // Move back to original cr3
1714 //
1715 __writecr3(OriginalCr3.Flags);
1716 return 0x2;
1717 }
1718 }
1719
1720 Result = C1 - C2;
1721 } while (!Result && C2);
1722
1723 if (Result < 0)
1724 {
1725 Result = -1;
1726 }
1727 else if (Result > 0)
1728 {
1729 Result = 1;
1730 }
1731
1732 //
1733 // Move back to original cr3
1734 //
1735 __writecr3(OriginalCr3.Flags);
1736 return Result;
1737}

◆ VmxCompatibleWcslen()

UINT32 VmxCompatibleWcslen ( const wchar_t * S)

implementation of vmx-root mode compatible wcslen

Parameters
S
Returns
UINT32 If 0x0 indicates an error, otherwise length of the string
1380{
1381 wchar_t Temp = NULL_ZERO;
1382 UINT32 Count = 0;
1383 UINT64 AlignedAddress;
1384 CR3_TYPE GuestCr3;
1385 CR3_TYPE OriginalCr3;
1386
1387 AlignedAddress = (UINT64)PAGE_ALIGN((UINT64)S);
1388
1389 //
1390 // Find the current process cr3
1391 //
1393
1394 //
1395 // Move to new cr3
1396 //
1397 OriginalCr3.Flags = __readcr3();
1398 __writecr3(GuestCr3.Flags);
1399
1400 AlignedAddress = (UINT64)PAGE_ALIGN((UINT64)S);
1401
1402 //
1403 // First check
1404 //
1405 if (!CheckAccessValidityAndSafety(AlignedAddress, sizeof(wchar_t)))
1406 {
1407 //
1408 // Error
1409 //
1410
1411 //
1412 // Move back to original cr3
1413 //
1414 __writecr3(OriginalCr3.Flags);
1415 return 0;
1416 }
1417
1418 while (TRUE)
1419 {
1420 /*
1421 Temp = *S;
1422 */
1423 MemoryMapperReadMemorySafe((UINT64)S, &Temp, sizeof(wchar_t));
1424
1425 if (Temp != '\0\0')
1426 {
1427 Count++;
1428 S++;
1429 }
1430 else
1431 {
1432 //
1433 // Move back to original cr3
1434 //
1435 __writecr3(OriginalCr3.Flags);
1436 return Count;
1437 }
1438
1439 if (!((UINT64)S & (PAGE_SIZE - 1)))
1440 {
1441 if (!CheckAccessValidityAndSafety((UINT64)S, sizeof(wchar_t)))
1442 {
1443 //
1444 // Error
1445 //
1446
1447 //
1448 // Move back to original cr3
1449 //
1450 __writecr3(OriginalCr3.Flags);
1451 return 0;
1452 }
1453 }
1454 }
1455
1456 //
1457 // Move back to original cr3
1458 //
1459 __writecr3(OriginalCr3.Flags);
1460}

◆ VmxFixCr4AndCr0Bits()

VOID VmxFixCr4AndCr0Bits ( )

Fix values for cr0 and cr4 bits.

The Cr4 And Cr0 Bits During VMX Operation Preventing Them From Any Change (https://revers.engineering/day-2-entering-vmx-operation/)

Returns
VOID
542{
543 CR_FIXED CrFixed = {0};
544 CR4 Cr4 = {0};
545 CR0 Cr0 = {0};
546
547 //
548 // Fix Cr0
549 //
550 CrFixed.Flags = __readmsr(IA32_VMX_CR0_FIXED0);
551 Cr0.AsUInt = __readcr0();
552 Cr0.AsUInt |= CrFixed.Fields.Low;
553 CrFixed.Flags = __readmsr(IA32_VMX_CR0_FIXED1);
554 Cr0.AsUInt &= CrFixed.Fields.Low;
555 __writecr0(Cr0.AsUInt);
556
557 //
558 // Fix Cr4
559 //
560 CrFixed.Flags = __readmsr(IA32_VMX_CR4_FIXED0);
561 Cr4.AsUInt = __readcr4();
562 Cr4.AsUInt |= CrFixed.Fields.Low;
563 CrFixed.Flags = __readmsr(IA32_VMX_CR4_FIXED1);
564 Cr4.AsUInt &= CrFixed.Fields.Low;
565 __writecr4(Cr4.AsUInt);
566}
Definition Common.h:244
unsigned long Low
Definition Common.h:249
struct _CR_FIXED::@0 Fields
UINT64 Flags
Definition Common.h:245

◆ VmxGetCurrentExecutionMode()

BOOLEAN VmxGetCurrentExecutionMode ( )

Check current execution mode (vmx-root and non-root)

Returns
BOOLEAN Returns true if the execution is on vmx-root, otherwise false
223{
224 if (g_GuestState)
225 {
226 ULONG CurrentCore = KeGetCurrentProcessorNumberEx(NULL);
227 VIRTUAL_MACHINE_STATE * CurrentVmState = &g_GuestState[CurrentCore];
228
230 }
231 else
232 {
233 //
234 // The structure for guest state is not initialized, thus, we're in VMX non-root
235 //
237 }
238}
unsigned long ULONG
Definition BasicTypes.h:37
@ VmxExecutionModeNonRoot
Definition DataTypes.h:82
@ VmxExecutionModeRoot
Definition DataTypes.h:83
VIRTUAL_MACHINE_STATE * g_GuestState
Save the state and variables related to virtualization on each to logical core.
Definition GlobalVariables.h:38
The status of each core after and before VMX.
Definition State.h:290
BOOLEAN IsOnVmxRootMode
Definition State.h:291

◆ VmxGetCurrentLaunchState()

BOOLEAN VmxGetCurrentLaunchState ( )

Check if the VMX is launched or not.

Returns
BOOLEAN Returns true if it's launched, otherwise false
247{
248 ULONG CurrentCore = KeGetCurrentProcessorNumberEx(NULL);
249 VIRTUAL_MACHINE_STATE * CurrentVmState = &g_GuestState[CurrentCore];
250
251 return CurrentVmState->HasLaunched;
252}
BOOLEAN HasLaunched
Definition State.h:293

◆ VmxInitialize()

BOOLEAN VmxInitialize ( )

Initialize the VMX operation.

Returns
BOOLEAN Returns true if vmx initialized successfully
261{
262 ULONG ProcessorsCount;
263
264 //
265 // ****** Start Virtualizing Current System ******
266 //
267
268 //
269 // Initiating EPTP and VMX
270 //
272 {
273 //
274 // there was error somewhere in initializing
275 //
276 return FALSE;
277 }
278
279 ProcessorsCount = KeQueryActiveProcessorCount(0);
280
281 for (size_t ProcessorID = 0; ProcessorID < ProcessorsCount; ProcessorID++)
282 {
283 //
284 // *** Launching VM for Test (in the all logical processor) ***
285 //
286
287 VIRTUAL_MACHINE_STATE * GuestState = &g_GuestState[ProcessorID];
288
289 //
290 // Allocating VMM Stack
291 //
292 if (!VmxAllocateVmmStack(GuestState))
293 {
294 //
295 // Some error in allocating Vmm Stack
296 //
297 return FALSE;
298 }
299
300 //
301 // Allocating MSR Bit
302 //
303 if (!VmxAllocateMsrBitmap(GuestState))
304 {
305 //
306 // Some error in allocating Msr Bitmaps
307 //
308 return FALSE;
309 }
310
311 //
312 // Allocating I/O Bit
313 //
314 if (!VmxAllocateIoBitmaps(GuestState))
315 {
316 //
317 // Some error in allocating I/O Bitmaps
318 //
319 return FALSE;
320 }
321
322#if USE_DEFAULT_OS_IDT_AS_HOST_IDT == FALSE
323
324 //
325 // Allocating Host IDT
326 //
327 if (!VmxAllocateHostIdt(GuestState))
328 {
329 //
330 // Some error in allocating Host IDT
331 //
332 return FALSE;
333 }
334#endif // USE_DEFAULT_OS_IDT_AS_HOST_IDT == FALSE
335
336#if USE_DEFAULT_OS_GDT_AS_HOST_GDT == FALSE
337
338 //
339 // Allocating Host GDT
340 //
341 if (!VmxAllocateHostGdt(GuestState))
342 {
343 //
344 // Some error in allocating Host GDT
345 //
346 return FALSE;
347 }
348
349 //
350 // Allocating Host TSS
351 //
352 if (!VmxAllocateHostTss(GuestState))
353 {
354 //
355 // Some error in allocating Host TSS
356 //
357 return FALSE;
358 }
359
360#endif // USE_DEFAULT_OS_GDT_AS_HOST_GDT == FALSE
361
362#if USE_INTERRUPT_STACK_TABLE == TRUE
363
364 //
365 // Allocating Host Interrupt Stack
366 //
367 if (!VmxAllocateHostInterruptStack(GuestState))
368 {
369 //
370 // Some error in allocating Interrupt Stack
371 //
372 return FALSE;
373 }
374
375#endif // USE_INTERRUPT_STACK_TABLE == TRUE
376 }
377
378 //
379 // Create a bitmap of the MSRs that cause #GP
380 //
382
383 if (g_MsrBitmapInvalidMsrs == NULL)
384 {
385 return FALSE;
386 }
387
388 //
389 // As we want to support more than 32 processor (64 logical-core)
390 // we let windows execute our routine for us
391 //
392 KeGenericCallDpc(DpcRoutineInitializeGuest, 0x0);
393
394 //
395 // Check if everything is ok then return true otherwise false
396 //
397 if (AsmVmxVmcall(VMCALL_TEST, 0x22, 0x333, 0x4444) == STATUS_SUCCESS)
398 {
399 return TRUE;
400 }
401 else
402 {
403 return FALSE;
404 }
405}
UINT64 * g_MsrBitmapInvalidMsrs
Bitmap of MSRs that cause #GP.
Definition GlobalVariables.h:107
NTSTATUS AsmVmxVmcall(unsigned long long VmcallNumber, unsigned long long OptionalParam1, unsigned long long OptionalParam2, long long OptionalParam3)
Request Vmcall.
#define VMCALL_TEST
VMCALL to test hypervisor.
Definition Vmcall.h:22
BOOLEAN VmxPerformVirtualizationOnAllCores()
Initialize essential VMX Operation tasks.
Definition Vmx.c:413
BOOLEAN VmxAllocateHostIdt(_Inout_ VIRTUAL_MACHINE_STATE *VCpu)
Allocate a buffer for host IDT.
Definition VmxRegions.c:297
UINT64 * VmxAllocateInvalidMsrBimap()
Allocates a buffer and tests for the MSRs that cause #GP.
Definition VmxRegions.c:264
BOOLEAN VmxAllocateIoBitmaps(_Inout_ VIRTUAL_MACHINE_STATE *VCpu)
Allocate a buffer for I/O Bitmap.
Definition VmxRegions.c:221
BOOLEAN VmxAllocateMsrBitmap(_Inout_ VIRTUAL_MACHINE_STATE *VCpu)
Allocate a buffer for Msr Bitmap.
Definition VmxRegions.c:192
BOOLEAN VmxAllocateHostInterruptStack(_Inout_ VIRTUAL_MACHINE_STATE *VCpu)
Allocate a buffer for host interrupt stack.
Definition VmxRegions.c:394
BOOLEAN VmxAllocateVmmStack(_Inout_ VIRTUAL_MACHINE_STATE *VCpu)
Allocate VMM Stack.
Definition VmxRegions.c:167
BOOLEAN VmxAllocateHostGdt(_Inout_ VIRTUAL_MACHINE_STATE *VCpu)
Allocate a buffer for host GDT.
Definition VmxRegions.c:332
BOOLEAN VmxAllocateHostTss(_Inout_ VIRTUAL_MACHINE_STATE *VCpu)
Allocate a buffer for host TSS.
Definition VmxRegions.c:367
VOID DpcRoutineInitializeGuest(KDPC *Dpc, PVOID DeferredContext, PVOID SystemArgument1, PVOID SystemArgument2)
The broadcast function which initialize the guest.
Definition DpcRoutines.c:1714

◆ VmxLoadVmcs()

_Use_decl_annotations_ BOOLEAN VmxLoadVmcs ( VIRTUAL_MACHINE_STATE * VCpu)

Implementation of VMPTRLD instruction.

Parameters
VCpu
Returns
BOOLEAN If vmptrld was unsuccessful then it returns false otherwise it returns false
799{
800 int VmptrldStatus;
801
802 VmptrldStatus = __vmx_vmptrld(&VCpu->VmcsRegionPhysicalAddress);
803 if (VmptrldStatus)
804 {
805 LogDebugInfo("VMCS failed to load, status : 0x%x", VmptrldStatus);
806 return FALSE;
807 }
808 return TRUE;
809}

◆ VmxPerformTermination()

VOID VmxPerformTermination ( )

Terminate Vmx on all logical cores.

Returns
VOID
1201{
1202 ULONG ProcessorsCount;
1203
1204 LogDebugInfo("Terminating VMX...\n");
1205
1206 //
1207 // Get number of processors
1208 //
1209 ProcessorsCount = KeQueryActiveProcessorCount(0);
1210
1211 //
1212 // ******* Terminating Vmx *******
1213 //
1214
1215 //
1216 // Unhide (disable and de-allocate) transparent-mode
1217 //
1219
1220 //
1221 // Remove All the hooks if any
1222 //
1224
1225 //
1226 // Restore the state of execution trap hooks
1227 //
1229
1230 //
1231 // Broadcast to terminate Vmx
1232 //
1233 KeGenericCallDpc(DpcRoutineTerminateGuest, 0x0);
1234
1235 //
1236 // ****** De-allocatee global variables ******
1237 //
1238
1239 //
1240 // Free the buffer related to MSRs that cause #GP
1241 //
1244
1245 //
1246 // Free Identity Page Table
1247 //
1248 for (size_t i = 0; i < ProcessorsCount; i++)
1249 {
1250 if (g_GuestState[i].EptPageTable != NULL)
1251 {
1252 MmFreeContiguousMemory(g_GuestState[i].EptPageTable);
1253 }
1254
1256 }
1257
1258 //
1259 // Free EptState
1260 //
1262 g_EptState = NULL;
1263
1264 //
1265 // Free the Pool manager
1266 //
1268
1269 //
1270 // Uninitialize memory mapper
1271 //
1273
1274 //
1275 // Free g_GuestState
1276 //
1278
1279 LogDebugInfo("VMX operation turned off successfully");
1280}
VOID EptHookUnHookAll()
Remove all hooks from the hooked pages list and invalidate TLB @detailsShould be called from Vmx Non-...
Definition EptHook.c:2431
VOID ExecTrapUninitialize()
Uinitialize the needed structure for the reversing machine.
Definition ExecTrap.c:605
VOID GlobalGuestStateFreeMemory(VOID)
Free guest state memory.
Definition GlobalVariableManagement.c:52
EPT_STATE * g_EptState
Save the state and variables related to EPT.
Definition GlobalVariables.h:50
VOID PlatformMemFreePool(PVOID BufferAddress)
Free (dellocate) a non-paged buffer.
Definition Mem.c:86
VOID MemoryMapperUninitialize()
uninitialize the Memory Mapper
Definition MemoryMapper.c:716
VOID PoolManagerUninitialize()
Uninitialize the pool manager (free the buffers, etc.)
Definition PoolManager.c:87
NTSTATUS TransparentUnhideDebugger()
Deactivate transparent-mode.
Definition Transparency.c:425
VOID DpcRoutineTerminateGuest(KDPC *Dpc, PVOID DeferredContext, PVOID SystemArgument1, PVOID SystemArgument2)
The broadcast function which terminate the guest.
Definition DpcRoutines.c:1745
NULL()
Definition test-case-generator.py:530
PVMM_EPT_PAGE_TABLE EptPageTable
Definition State.h:342

◆ VmxPerformVirtualizationOnAllCores()

BOOLEAN VmxPerformVirtualizationOnAllCores ( )

Initialize essential VMX Operation tasks.

Returns
BOOLEAN Returns true if vmx is successfully initialized
414{
415 PAGED_CODE();
416
417 if (!VmxCheckVmxSupport())
418 {
419 LogError("Err, VMX is not supported in this machine");
420 return FALSE;
421 }
422
423 //
424 // Allocate global variable to hold Ept State
425 //
427
428 if (!g_EptState)
429 {
430 LogError("Err, insufficient memory");
431 return FALSE;
432 }
433
434 //
435 // Initialize the list of hooked pages detail
436 //
438
439 //
440 // Check whether EPT is supported or not
441 //
442 if (!EptCheckFeatures())
443 {
444 LogError("Err, your processor doesn't support all EPT features");
445 return FALSE;
446 }
447 else
448 {
449 //
450 // Our processor supports EPT, now let's build MTRR
451 //
452 LogDebugInfo("Your processor supports all EPT features");
453
454 //
455 // Build MTRR Map
456 //
457 if (!EptBuildMtrrMap())
458 {
459 LogError("Err, could not build MTRR memory map");
460 return FALSE;
461 }
462
463 LogDebugInfo("MTRR memory map built successfully");
464 }
465
466 //
467 // Initialize Pool Manager
468 //
470 {
471 LogError("Err, could not initialize pool manager");
472 return FALSE;
473 }
474
476 {
477 //
478 // There were some errors in EptLogicalProcessorInitialize
479 //
480 return FALSE;
481 }
482
483 //
484 // Broadcast to run vmx-specific task to virtualize cores
485 //
487
488 //
489 // Everything is ok, let's return true
490 //
491 return TRUE;
492}
VOID BroadcastVmxVirtualizationAllCores()
routines to broadcast virtualization and vmx initialization on all cores
Definition Broadcast.c:21
BOOLEAN EptLogicalProcessorInitialize(VOID)
Initialize EPT for an individual logical processor.
Definition Ept.c:759
BOOLEAN EptBuildMtrrMap(VOID)
Build MTRR Map of current physical addresses.
Definition Ept.c:156
BOOLEAN EptCheckFeatures(VOID)
Check whether EPT features are present or not.
Definition Ept.c:22
PVOID PlatformMemAllocateZeroedNonPagedPool(SIZE_T NumberOfBytes)
Allocate a non-paged buffer (zeroed)
Definition Mem.c:69
BOOLEAN PoolManagerInitialize()
Initializes the pool manager.
Definition PoolManager.c:53
BOOLEAN VmxCheckVmxSupport()
Check whether VMX Feature is supported or not.
Definition Vmx.c:166
FORCEINLINE VOID InitializeListHead(_Out_ PLIST_ENTRY ListHead)
Definition Windows.h:41
Main structure for saving the state of EPT among the project.
Definition Ept.h:117
LIST_ENTRY HookedPagesList
Definition Ept.h:118

◆ VmxPerformVirtualizationOnSpecificCore()

BOOLEAN VmxPerformVirtualizationOnSpecificCore ( )

Allocates Vmx regions for all logical cores (Vmxon region and Vmcs region)

Returns
BOOLEAN
501{
502 ULONG CurrentCore = KeGetCurrentProcessorNumberEx(NULL);
503 VIRTUAL_MACHINE_STATE * VCpu = &g_GuestState[CurrentCore];
504
505 LogDebugInfo("Allocating vmx regions for logical core %d", CurrentCore);
506
507 //
508 // Enabling VMX Operation
509 //
511
512 //
513 // Fix Cr4 and Cr0 bits during VMX operation
514 //
516
517 LogDebugInfo("VMX-Operation enabled successfully");
518
519 if (!VmxAllocateVmxonRegion(VCpu))
520 {
521 LogError("Err, allocating memory for vmxon region was not successful");
522 return FALSE;
523 }
524 if (!VmxAllocateVmcsRegion(VCpu))
525 {
526 LogError("Err, allocating memory for vmcs region was not successful");
527 return FALSE;
528 }
529
530 return TRUE;
531}
void AsmEnableVmxOperation()
Enable VMX Operation.
VOID VmxFixCr4AndCr0Bits()
Fix values for cr0 and cr4 bits.
Definition Vmx.c:541
_Use_decl_annotations_ BOOLEAN VmxAllocateVmxonRegion(VIRTUAL_MACHINE_STATE *VCpu)
Allocates Vmxon region and set the Revision ID based on IA32_VMX_BASIC_MSR.
Definition VmxRegions.c:23
_Use_decl_annotations_ BOOLEAN VmxAllocateVmcsRegion(VIRTUAL_MACHINE_STATE *VCpu)
Allocate Vmcs region and set the Revision ID based on IA32_VMX_BASIC_MSR.
Definition VmxRegions.c:103

◆ VmxReturnInstructionPointerForVmxoff()

UINT64 VmxReturnInstructionPointerForVmxoff ( )

Get the RIP of guest (VMCS_GUEST_RIP) in the case of return from VMXOFF.

Returns
UINT64 Returns the instruction pointer, to change in the case of Vmxoff
1190{
1191 return g_GuestState[KeGetCurrentProcessorNumberEx(NULL)].VmxoffState.GuestRip;
1192}
VMX_VMXOFF_STATE VmxoffState
Definition State.h:328
UINT64 GuestRip
Definition State.h:153

◆ VmxReturnStackPointerForVmxoff()

UINT64 VmxReturnStackPointerForVmxoff ( )

Get the RIP of guest (VMCS_GUEST_RIP) in the case of return from VMXOFF.

Returns
UINT64 Returns the stack pointer, to change in the case of Vmxoff
1179{
1180 return g_GuestState[KeGetCurrentProcessorNumberEx(NULL)].VmxoffState.GuestRsp;
1181}
UINT64 GuestRsp
Definition State.h:154

◆ VmxSetupVmcs()

_Use_decl_annotations_ BOOLEAN VmxSetupVmcs ( VIRTUAL_MACHINE_STATE * VCpu,
PVOID GuestStack )

Create and Configure a Vmcs Layout.

Parameters
VCpu
GuestStack
Returns
BOOLEAN
821{
822 UINT32 CpuBasedVmExecControls;
823 UINT32 SecondaryProcBasedVmExecControls;
824 PVOID HostRsp;
825 UINT64 GdtBase = 0;
826 IA32_VMX_BASIC_REGISTER VmxBasicMsr = {0};
828
829 //
830 // Reading IA32_VMX_BASIC_MSR
831 //
832 VmxBasicMsr.AsUInt = __readmsr(IA32_VMX_BASIC);
833
834 VmxVmwrite64(VMCS_HOST_ES_SELECTOR, AsmGetEs() & 0xF8);
835 VmxVmwrite64(VMCS_HOST_CS_SELECTOR, AsmGetCs() & 0xF8);
836 VmxVmwrite64(VMCS_HOST_SS_SELECTOR, AsmGetSs() & 0xF8);
837 VmxVmwrite64(VMCS_HOST_DS_SELECTOR, AsmGetDs() & 0xF8);
838 VmxVmwrite64(VMCS_HOST_FS_SELECTOR, AsmGetFs() & 0xF8);
839 VmxVmwrite64(VMCS_HOST_GS_SELECTOR, AsmGetGs() & 0xF8);
840 VmxVmwrite64(VMCS_HOST_TR_SELECTOR, AsmGetTr() & 0xF8);
841
842 //
843 // Setting the link pointer to the required value for 4KB VMCS
844 //
845 VmxVmwrite64(VMCS_GUEST_VMCS_LINK_POINTER, ~0ULL);
846
847 VmxVmwrite64(VMCS_GUEST_DEBUGCTL, __readmsr(IA32_DEBUGCTL) & 0xFFFFFFFF);
848 VmxVmwrite64(VMCS_GUEST_DEBUGCTL_HIGH, __readmsr(IA32_DEBUGCTL) >> 32);
849
850 //
851 // ******* Time-stamp counter offset *******
852 //
853 VmxVmwrite64(VMCS_CTRL_TSC_OFFSET, 0);
854
855 VmxVmwrite64(VMCS_CTRL_PAGEFAULT_ERROR_CODE_MASK, 0);
856 VmxVmwrite64(VMCS_CTRL_PAGEFAULT_ERROR_CODE_MATCH, 0);
857
858 VmxVmwrite64(VMCS_CTRL_VMEXIT_MSR_STORE_COUNT, 0);
859 VmxVmwrite64(VMCS_CTRL_VMEXIT_MSR_LOAD_COUNT, 0);
860
861 VmxVmwrite64(VMCS_CTRL_VMENTRY_MSR_LOAD_COUNT, 0);
862 VmxVmwrite64(VMCS_CTRL_VMENTRY_INTERRUPTION_INFORMATION_FIELD, 0);
863
864 GdtBase = AsmGetGdtBase();
865
866 HvFillGuestSelectorData((PVOID)GdtBase, ES, AsmGetEs());
867 HvFillGuestSelectorData((PVOID)GdtBase, CS, AsmGetCs());
868 HvFillGuestSelectorData((PVOID)GdtBase, SS, AsmGetSs());
869 HvFillGuestSelectorData((PVOID)GdtBase, DS, AsmGetDs());
870 HvFillGuestSelectorData((PVOID)GdtBase, FS, AsmGetFs());
871 HvFillGuestSelectorData((PVOID)GdtBase, GS, AsmGetGs());
872 HvFillGuestSelectorData((PVOID)GdtBase, LDTR, AsmGetLdtr());
873 HvFillGuestSelectorData((PVOID)GdtBase, TR, AsmGetTr());
874
875 VmxVmwrite64(VMCS_GUEST_FS_BASE, __readmsr(IA32_FS_BASE));
876 VmxVmwrite64(VMCS_GUEST_GS_BASE, __readmsr(IA32_GS_BASE));
877
879 VmxBasicMsr.VmxControls ? IA32_VMX_TRUE_PROCBASED_CTLS : IA32_VMX_PROCBASED_CTLS);
880
881 VmxVmwrite64(VMCS_CTRL_PROCESSOR_BASED_VM_EXECUTION_CONTROLS, CpuBasedVmExecControls);
882
883 LogDebugInfo("CPU Based VM Exec Controls (Based on %s) : 0x%x",
884 VmxBasicMsr.VmxControls ? "IA32_VMX_TRUE_PROCBASED_CTLS" : "IA32_VMX_PROCBASED_CTLS",
885 CpuBasedVmExecControls);
886
888 IA32_VMX_PROCBASED_CTLS2);
889
890 VmxVmwrite64(VMCS_CTRL_SECONDARY_PROCESSOR_BASED_VM_EXECUTION_CONTROLS, SecondaryProcBasedVmExecControls);
891
892 LogDebugInfo("Secondary Proc Based VM Exec Controls (IA32_VMX_PROCBASED_CTLS2) : 0x%x", SecondaryProcBasedVmExecControls);
893
894 VmxVmwrite64(VMCS_CTRL_PIN_BASED_VM_EXECUTION_CONTROLS, HvAdjustControls(0, VmxBasicMsr.VmxControls ? IA32_VMX_TRUE_PINBASED_CTLS : IA32_VMX_PINBASED_CTLS));
895
896 VmxVmwrite64(VMCS_CTRL_PRIMARY_VMEXIT_CONTROLS, HvAdjustControls(VM_EXIT_HOST_ADDR_SPACE_SIZE, VmxBasicMsr.VmxControls ? IA32_VMX_TRUE_EXIT_CTLS : IA32_VMX_EXIT_CTLS));
897
898 VmxVmwrite64(VMCS_CTRL_VMENTRY_CONTROLS, HvAdjustControls(VM_ENTRY_IA32E_MODE, VmxBasicMsr.VmxControls ? IA32_VMX_TRUE_ENTRY_CTLS : IA32_VMX_ENTRY_CTLS));
899
900 VmxVmwrite64(VMCS_CTRL_CR0_GUEST_HOST_MASK, 0);
901 VmxVmwrite64(VMCS_CTRL_CR4_GUEST_HOST_MASK, 0);
902
903 VmxVmwrite64(VMCS_CTRL_CR0_READ_SHADOW, 0);
904 VmxVmwrite64(VMCS_CTRL_CR4_READ_SHADOW, 0);
905
906 VmxVmwrite64(VMCS_GUEST_CR0, __readcr0());
907 VmxVmwrite64(VMCS_GUEST_CR3, __readcr3());
908 VmxVmwrite64(VMCS_GUEST_CR4, __readcr4());
909
910 VmxVmwrite64(VMCS_GUEST_DR7, 0x400);
911
912 VmxVmwrite64(VMCS_HOST_CR0, __readcr0());
913 VmxVmwrite64(VMCS_HOST_CR4, __readcr4());
914
915 //
916 // Because we may be executing in an arbitrary user-mode, process as part
917 // of the DPC interrupt we execute in We have to save Cr3, for VMCS_HOST_CR3
918 //
919
921
922 VmxVmwrite64(VMCS_GUEST_GDTR_BASE, AsmGetGdtBase());
923 VmxVmwrite64(VMCS_GUEST_IDTR_BASE, AsmGetIdtBase());
924
925 VmxVmwrite64(VMCS_GUEST_GDTR_LIMIT, AsmGetGdtLimit());
926 VmxVmwrite64(VMCS_GUEST_IDTR_LIMIT, AsmGetIdtLimit());
927
928 VmxVmwrite64(VMCS_GUEST_RFLAGS, AsmGetRflags());
929
930 VmxVmwrite64(VMCS_GUEST_SYSENTER_CS, __readmsr(IA32_SYSENTER_CS));
931 VmxVmwrite64(VMCS_GUEST_SYSENTER_EIP, __readmsr(IA32_SYSENTER_EIP));
932 VmxVmwrite64(VMCS_GUEST_SYSENTER_ESP, __readmsr(IA32_SYSENTER_ESP));
933
934#if USE_DEFAULT_OS_GDT_AS_HOST_GDT == FALSE
935
937
938 VmxVmwrite64(VMCS_HOST_TR_BASE, SegmentSelector.Base);
939 VmxVmwrite64(VMCS_HOST_GDTR_BASE, VCpu->HostGdt);
940
941#else
942
944
945 VmxVmwrite64(VMCS_HOST_TR_BASE, SegmentSelector.Base);
946 VmxVmwrite64(VMCS_HOST_GDTR_BASE, AsmGetGdtBase());
947
948#endif // USE_DEFAULT_OS_GDT_AS_HOST_GDT == FALSE
949
950 VmxVmwrite64(VMCS_HOST_FS_BASE, __readmsr(IA32_FS_BASE));
951 VmxVmwrite64(VMCS_HOST_GS_BASE, __readmsr(IA32_GS_BASE));
952
953#if USE_DEFAULT_OS_IDT_AS_HOST_IDT == FALSE
954
955 VmxVmwrite64(VMCS_HOST_IDTR_BASE, VCpu->HostIdt);
956
957#else
958
959 VmxVmwrite64(VMCS_HOST_IDTR_BASE, AsmGetIdtBase());
960
961#endif // USE_DEFAULT_OS_IDT_AS_HOST_IDT == FALSE
962
963 VmxVmwrite64(VMCS_HOST_SYSENTER_CS, __readmsr(IA32_SYSENTER_CS));
964 VmxVmwrite64(VMCS_HOST_SYSENTER_EIP, __readmsr(IA32_SYSENTER_EIP));
965 VmxVmwrite64(VMCS_HOST_SYSENTER_ESP, __readmsr(IA32_SYSENTER_ESP));
966
967 //
968 // Set MSR Bitmaps
969 //
970 VmxVmwrite64(VMCS_CTRL_MSR_BITMAP_ADDRESS, VCpu->MsrBitmapPhysicalAddress);
971
972 //
973 // Set I/O Bitmaps
974 //
975 VmxVmwrite64(VMCS_CTRL_IO_BITMAP_A_ADDRESS, VCpu->IoBitmapPhysicalAddressA);
976 VmxVmwrite64(VMCS_CTRL_IO_BITMAP_B_ADDRESS, VCpu->IoBitmapPhysicalAddressB);
977
978 //
979 // Set up EPT
980 //
981 VmxVmwrite64(VMCS_CTRL_EPT_POINTER, VCpu->EptPointer.AsUInt);
982
983 //
984 // Set up VPID
985
986 //
987 // For all processors, we will use a VPID = 1. This allows the processor to separate caching
988 // of EPT structures away from the regular OS page translation tables in the TLB.
989 //
991
992 //
993 // setup guest rsp
994 //
995 VmxVmwrite64(VMCS_GUEST_RSP, (UINT64)GuestStack);
996
997 //
998 // setup guest rip
999 //
1000 VmxVmwrite64(VMCS_GUEST_RIP, (UINT64)AsmVmxRestoreState);
1001
1002 //
1003 // Stack should be aligned to 16 because we wanna save XMM and FPU registers and those instructions
1004 // needs alignment to 16
1005 //
1006 HostRsp = (PVOID)((UINT64)VCpu->VmmStack + VMM_STACK_SIZE - 1);
1007 HostRsp = ((PVOID)((ULONG_PTR)(HostRsp) & ~(16 - 1)));
1008 VmxVmwrite64(VMCS_HOST_RSP, (UINT64)HostRsp);
1009 VmxVmwrite64(VMCS_HOST_RIP, (UINT64)AsmVmexitHandler);
1010
1011 return TRUE;
1012}
UINT32 HvAdjustControls(UINT32 Ctl, UINT32 Msr)
Adjust controls for VMCS based on processor capability.
Definition Hv.c:23
VOID HvFillGuestSelectorData(PVOID GdtBase, UINT32 SegmentRegister, UINT16 Selector)
Fill the guest's selector data.
Definition Hv.c:276
unsigned short AsmGetGs()
Get GS Register.
void AsmVmexitHandler()
Vm-exit handler.
unsigned short AsmGetTr()
Get TR Register.
unsigned short AsmGetDs()
Get DS Register.
unsigned short AsmGetSs()
Get SS Register.
unsigned short AsmGetGdtLimit()
Get GDT Limit.
unsigned long long AsmGetIdtBase()
Get IDT base.
unsigned short AsmGetLdtr()
Get LDTR Register.
unsigned short AsmGetCs()
Get CS Register.
unsigned short AsmGetFs()
Get FS Register.
unsigned short AsmGetEs()
Get ES Register.
unsigned long long AsmGetGdtBase()
get GDT base
unsigned short AsmGetRflags()
Get R/EFLAGS.
void AsmVmxRestoreState()
Restore state on vmx.
unsigned short AsmGetIdtLimit()
Get IDT limit.
UINT64 LayoutGetSystemDirectoryTableBase()
Find cr3 of system process.
Definition Layout.c:90
_Use_decl_annotations_ BOOLEAN SegmentGetDescriptor(PUCHAR GdtBase, UINT16 Selector, PVMX_SEGMENT_SELECTOR SegmentSelector)
Get Segment Descriptor.
Definition Segmentation.c:24
_In_ UINT16 _Out_ PVMX_SEGMENT_SELECTOR SegmentSelector
Definition Segmentation.h:51
UCHAR VmxVmwrite64(size_t Field, UINT64 FieldValue)
VMX VMWRITE instruction (64-bit)
Definition Vmx.c:122
#define CPU_BASED_CTL2_ENABLE_VPID
Definition Vmx.h:72
#define VIRTUAL_PROCESSOR_ID
Definition Vmx.h:291
#define CPU_BASED_ACTIVATE_MSR_BITMAP
Definition Vmx.h:61
#define VM_EXIT_HOST_ADDR_SPACE_SIZE
Definition Vmx.h:84
#define CPU_BASED_ACTIVATE_SECONDARY_CONTROLS
Definition Vmx.h:64
#define CPU_BASED_ACTIVATE_IO_BITMAP
Definition Vmx.h:59
#define CPU_BASED_CTL2_ENABLE_XSAVE_XRSTORS
Definition Vmx.h:77
#define CPU_BASED_CTL2_ENABLE_INVPCID
Definition Vmx.h:75
#define CPU_BASED_CTL2_ENABLE_EPT
Secondary CPU-Based Controls.
Definition Vmx.h:70
#define VM_ENTRY_IA32E_MODE
Definition Vmx.h:98
#define CPU_BASED_CTL2_RDTSCP
Definition Vmx.h:71
#define VMM_STACK_SIZE
Stack Size.
Definition Vmx.h:140
#define VMCS_GUEST_DEBUGCTL_HIGH
Definition Vmx.h:290
#define VPID_TAG
VPID Tag.
Definition Vpid.h:30
@ TR
Definition Common.h:31
@ LDTR
Definition Common.h:30
@ FS
Definition Common.h:28
@ ES
Definition Common.h:24
@ CS
Definition Common.h:25
@ GS
Definition Common.h:29
@ DS
Definition Common.h:27
@ SS
Definition Common.h:26
UINT64 MsrBitmapPhysicalAddress
Definition State.h:316
UINT64 HostGdt
Definition State.h:334
EPT_POINTER EptPointer
Definition State.h:341
UINT64 IoBitmapPhysicalAddressA
Definition State.h:318
UINT64 VmmStack
Definition State.h:314
UINT64 HostIdt
Definition State.h:333
UINT64 IoBitmapPhysicalAddressB
Definition State.h:320
Segment selector.
Definition DataTypes.h:436
UINT64 Base
Definition DataTypes.h:440

◆ VmxTerminate()

BOOLEAN VmxTerminate ( )

Broadcast to terminate VMX on all logical cores.

Returns
BOOLEAN Returns true if vmxoff successfully executed in vmcall or otherwise returns false
700{
701 NTSTATUS Status = STATUS_SUCCESS;
702 ULONG CurrentCore = KeGetCurrentProcessorNumberEx(NULL);
703 VIRTUAL_MACHINE_STATE * VCpu = &g_GuestState[CurrentCore];
704
705 //
706 // Execute Vmcall to to turn off vmx from Vmx root mode
707 //
709
710 if (Status == STATUS_SUCCESS)
711 {
712 LogDebugInfo("VMX terminated on logical core %d\n", CurrentCore);
713
714 //
715 // Free the destination memory
716 //
717 MmFreeContiguousMemory((PVOID)VCpu->VmxonRegionVirtualAddress);
718 MmFreeContiguousMemory((PVOID)VCpu->VmcsRegionVirtualAddress);
719 PlatformMemFreePool((PVOID)VCpu->VmmStack);
723#if USE_DEFAULT_OS_IDT_AS_HOST_IDT == FALSE
724 PlatformMemFreePool((PVOID)VCpu->HostIdt);
725#endif // USE_DEFAULT_OS_IDT_AS_HOST_IDT == FALSE
726
727#if USE_DEFAULT_OS_GDT_AS_HOST_GDT == FALSE
728 PlatformMemFreePool((PVOID)VCpu->HostGdt);
729 PlatformMemFreePool((PVOID)VCpu->HostTss);
730#endif // USE_DEFAULT_OS_GDT_AS_HOST_GDT == FALSE
731
732#if USE_INTERRUPT_STACK_TABLE == TRUE
734#endif // USE_INTERRUPT_STACK_TABLE == FALSE
735
736 return TRUE;
737 }
738
739 return FALSE;
740}
#define NULL64_ZERO
Definition BasicTypes.h:52
#define VMCALL_VMXOFF
VMCALL to Call VMXOFF to turn off the hypervisor.
Definition Vmcall.h:28
UINT64 VmxonRegionVirtualAddress
Definition State.h:311
UINT64 HostInterruptStack
Definition State.h:336
UINT64 IoBitmapVirtualAddressB
Definition State.h:319
UINT64 MsrBitmapVirtualAddress
Definition State.h:315
UINT64 HostTss
Definition State.h:335
UINT64 IoBitmapVirtualAddressA
Definition State.h:317
UINT64 VmcsRegionVirtualAddress
Definition State.h:313

◆ VmxVirtualizeCurrentSystem()

BOOLEAN VmxVirtualizeCurrentSystem ( PVOID GuestStack)

Initialize VMX Operation.

Parameters
GuestStackGuest stack for the this core (VMCS_GUEST_RSP)
Returns
BOOLEAN This function won't return true as when Vmlaunch is executed the rest of the function never executes but returning FALSE is an indication of error
606{
607 UINT64 ErrorCode = 0;
608 ULONG CurrentCore = KeGetCurrentProcessorNumberEx(NULL);
609 VIRTUAL_MACHINE_STATE * VCpu = &g_GuestState[CurrentCore];
610
611 LogDebugInfo("Virtualizing current system (logical core : 0x%x)", CurrentCore);
612
613#if USE_DEFAULT_OS_IDT_AS_HOST_IDT == FALSE
614
615 //
616 // Prepare Host IDT
617 //
619#endif // USE_DEFAULT_OS_IDT_AS_HOST_IDT == FALSE
620
621#if USE_DEFAULT_OS_GDT_AS_HOST_GDT == FALSE
622
623 //
624 // Prepare Host GDT and TSS
625 //
626 SegmentPrepareHostGdt((SEGMENT_DESCRIPTOR_32 *)AsmGetGdtBase(),
628 AsmGetTr(),
629 VCpu->HostInterruptStack,
630 (SEGMENT_DESCRIPTOR_32 *)VCpu->HostGdt,
631 (TASK_STATE_SEGMENT_64 *)VCpu->HostTss);
632
633#endif // USE_DEFAULT_OS_GDT_AS_HOST_GDT == FALSE
634
635 //
636 // Clear the VMCS State
637 //
638 if (!VmxClearVmcsState(VCpu))
639 {
640 LogError("Err, failed to clear vmcs");
641 return FALSE;
642 }
643
644 //
645 // Load VMCS (Set the Current VMCS)
646 //
647 if (!VmxLoadVmcs(VCpu))
648 {
649 LogError("Err, failed to load vmcs");
650 return FALSE;
651 }
652
653 LogDebugInfo("Setting up VMCS for current logical core");
654
655 VmxSetupVmcs(VCpu, GuestStack);
656
657 LogDebugInfo("Executing VMLAUNCH on logical core %d", CurrentCore);
658
659 //
660 // Setting the state to indicate current core is currently virtualized
661 //
662
663 VCpu->HasLaunched = TRUE;
664
665 __vmx_vmlaunch();
666
667 //
668 // ******** if Vmlaunch succeed will never be here ! ********
669 //
670
671 //
672 // If failed, then indicate that current core is not currently virtualized
673 //
674 VCpu->HasLaunched = FALSE;
675
676 //
677 // Read error code firstly
678 //
679 __vmx_vmread(VMCS_VM_INSTRUCTION_ERROR, &ErrorCode);
680
681 LogError("Err, unable to execute VMLAUNCH, status : 0x%llx", ErrorCode);
682
683 //
684 // Then Execute Vmxoff
685 //
686 __vmx_off();
687 LogError("Err, VMXOFF Executed Successfully but it was because of an error");
688
689 return FALSE;
690}
VOID IdtEmulationPrepareHostIdt(_Inout_ VIRTUAL_MACHINE_STATE *VCpu)
Prepare Host IDT.
Definition IdtEmulation.c:67
VOID SegmentPrepareHostGdt(SEGMENT_DESCRIPTOR_32 *OsGdtBase, UINT16 OsGdtLimit, UINT16 TrSelector, UINT64 HostStack, SEGMENT_DESCRIPTOR_32 *AllocatedHostGdt, TASK_STATE_SEGMENT_64 *AllocatedHostTss)
Initialize the host GDT.
Definition Segmentation.c:95
_Use_decl_annotations_ BOOLEAN VmxClearVmcsState(VIRTUAL_MACHINE_STATE *VCpu)
Clearing Vmcs status using vmclear instruction.
Definition Vmx.c:766
_Use_decl_annotations_ BOOLEAN VmxLoadVmcs(VIRTUAL_MACHINE_STATE *VCpu)
Implementation of VMPTRLD instruction.
Definition Vmx.c:798
_Use_decl_annotations_ BOOLEAN VmxSetupVmcs(VIRTUAL_MACHINE_STATE *VCpu, PVOID GuestStack)
Create and Configure a Vmcs Layout.
Definition Vmx.c:820

◆ VmxVmfunc()

UINT64 VmxVmfunc ( UINT32 EptpIndex,
UINT32 Function )

VMFUNC instruction.

Should be executed in VMX NON-root

Parameters
EptpIndex
Function
Returns
UINT64
1051{
1052 //
1053 // *** To be executed in VMX non-root ***
1054 //
1055
1056 //
1057 // Description from : https://users.cs.utah.edu/~aburtsev/lls-sem/index.php?n=Main.VMFUNCNotes
1058 //
1059 // VMFUNC is a new Intel primitive that allows to change an EPT page table underneath a VT-x VM without exiting into the hypervisor
1060 // Effectively, it's a page table switch in hardware and thus it allows one to build a fast context switch
1061 //
1062
1063 //
1064 // Each VT-x virtual machine is configured with a Virtual Machine Control Structure (VMCS)
1065 // This is a page of memory in which the VMM writes configuration data for things like how interrupts are handled,
1066 // initial control register values during guest entry, and a whole bunch of other things
1067 //
1068 // One of those other things is a pointer to a page of candidate EPT pointers. These are pointers to different EPT
1069 // page table hierarchies, each one giving a possibly different physical -> machine mapping. The VMM sets up this page
1070 // of EPT pointers and has to also turn on a couple other settings in the VMCS to fully enable EPT switching via VMFUNC
1071 //
1072 // In non-root operation (inside a VM) code running in any privilege level can switch EPT hierarchies through the following
1073 // steps:
1074 //
1075 // Storing 0 in %rax (EPT switching is VMFUNC 0)
1076 // Storing the index into the candidate EPT table in %rcx
1077 // Invoking the VMFUNC instruction
1078 // The processor will switch EPTs. Invoking VMFUNC will not cause a VM Exit
1079 //
1080 // All of this is detailed in the Intel SDM Volume 3, 25.5.5.3 "EPT Switching"
1081 //
1082 // It is worth noting that this will not change/save values in control registers (e.g. %cr3), general purpose registers,
1083 // and so on. It's up to the code and VMM to set things up so it all works gracefully
1084 //
1085
1086 //
1087 // Are TLBs flushed ? No, unless VPIDs are not being used(which I, Charlie, would say is rare)
1088 // See Intel SDM Volume 3, 25.5.5.3 "EPT Switching" and 28.3.3.1 "Operations that Invalidate Cached Mappings"
1089 //
1090
1091 return AsmVmfunc(EptpIndex, Function);
1092}
unsigned long long AsmVmfunc(unsigned long EptpIndex, unsigned long Function)
VMFUNC instruction.

◆ VmxVmptrst()

VOID VmxVmptrst ( )

Implementation of VMPTRST instruction.

Returns
VOID
749{
750 PHYSICAL_ADDRESS VmcsPhysicalAddr;
751 VmcsPhysicalAddr.QuadPart = 0;
752 __vmx_vmptrst((unsigned __int64 *)&VmcsPhysicalAddr);
753
754 LogDebugInfo("VMPTRST result : %llx", VmcsPhysicalAddr);
755}

◆ VmxVmread16()

UCHAR VmxVmread16 ( size_t Field,
UINT16 FieldValue )
inline

VMX VMREAD instruction (16-bit)

Parameters
Field
FieldValue
Returns
UCHAR
56{
57 UINT64 TargetField = 0ull;
58
59 TargetField = FieldValue;
60
61 return __vmx_vmread((size_t)Field, (size_t *)TargetField);
62}

◆ VmxVmread16P()

UCHAR VmxVmread16P ( size_t Field,
UINT16 * FieldValue )
inline

VMX VMREAD instruction (16-bit)

Parameters
Field
FieldValue
Returns
UCHAR
106{
107 UINT64 TargetField = 0ull;
108
109 TargetField = (UINT64)FieldValue;
110
111 return __vmx_vmread((size_t)Field, (size_t *)TargetField);
112}

◆ VmxVmread32()

UCHAR VmxVmread32 ( size_t Field,
UINT32 FieldValue )
inline

VMX VMREAD instruction (32-bit)

Parameters
Field
FieldValue
Returns
UCHAR
38{
39 UINT64 TargetField = 0ull;
40
41 TargetField = FieldValue;
42
43 return __vmx_vmread((size_t)Field, (size_t *)TargetField);
44}

◆ VmxVmread32P()

UCHAR VmxVmread32P ( size_t Field,
UINT32 * FieldValue )
inline

VMX VMREAD instruction (32-bit)

Parameters
Field
FieldValue
Returns
UCHAR
88{
89 UINT64 TargetField = 0ull;
90
91 TargetField = (UINT64)FieldValue;
92
93 return __vmx_vmread((size_t)Field, (size_t *)TargetField);
94}

◆ VmxVmread64()

UCHAR VmxVmread64 ( size_t Field,
UINT64 FieldValue )
inline

VMX VMREAD instruction (64-bit)

Parameters
Field
FieldValue
Returns
UCHAR
24{
25 return __vmx_vmread((size_t)Field, (size_t *)FieldValue);
26}

◆ VmxVmread64P()

UCHAR VmxVmread64P ( size_t Field,
UINT64 * FieldValue )
inline

VMX VMREAD instruction (64-bit)

Parameters
Field
FieldValue
Returns
UCHAR
74{
75 return __vmx_vmread((size_t)Field, (size_t *)FieldValue);
76}

◆ VmxVmresume()

VOID VmxVmresume ( )

Resume VM using VMRESUME instruction.

Returns
VOID
1021{
1022 UINT64 ErrorCode = 0;
1023
1024 __vmx_vmresume();
1025
1026 //
1027 // if VMRESUME succeed will never be here !
1028 //
1029
1030 __vmx_vmread(VMCS_VM_INSTRUCTION_ERROR, &ErrorCode);
1031 __vmx_off();
1032
1033 //
1034 // It's such a bad error because we don't where to go !
1035 // prefer to break
1036 //
1037 LogError("Err, in executing VMRESUME , status : 0x%llx", ErrorCode);
1038}

◆ VmxVmwrite16()

UCHAR VmxVmwrite16 ( size_t Field,
UINT16 FieldValue )
inline

VMX VMWRITE instruction (16-bit)

Parameters
Field
FieldValue
Returns
UCHAR
154{
155 UINT64 TargetValue = NULL64_ZERO;
156 TargetValue = (UINT64)FieldValue;
157 return __vmx_vmwrite((size_t)Field, (size_t)TargetValue);
158}

◆ VmxVmwrite32()

UCHAR VmxVmwrite32 ( size_t Field,
UINT32 FieldValue )
inline

VMX VMWRITE instruction (32-bit)

Parameters
Field
FieldValue
Returns
UCHAR
138{
139 UINT64 TargetValue = NULL64_ZERO;
140 TargetValue = (UINT64)FieldValue;
141 return __vmx_vmwrite((size_t)Field, (size_t)TargetValue);
142}

◆ VmxVmwrite64()

UCHAR VmxVmwrite64 ( size_t Field,
UINT64 FieldValue )
inline

VMX VMWRITE instruction (64-bit)

Parameters
Field
FieldValue
Returns
UCHAR
124{
125 return __vmx_vmwrite((size_t)Field, (size_t)FieldValue);
126}

◆ VmxVmxoff()

VOID VmxVmxoff ( VIRTUAL_MACHINE_STATE * VCpu)

Prepare and execute Vmxoff instruction.

Parameters
VCpuThe virtual processor's state
Returns
VOID
1102{
1103 UINT64 GuestRSP = 0; // Save a pointer to guest rsp for times that we want to return to previous guest stateS
1104 UINT64 GuestRIP = 0; // Save a pointer to guest rip for times that we want to return to previous guest state
1105 UINT64 GuestCr3 = 0;
1106 UINT64 ExitInstructionLength = 0;
1107
1108 //
1109 // According to SimpleVisor :
1110 // Our callback routine may have interrupted an arbitrary user process,
1111 // and therefore not a thread running with a system-wide page directory.
1112 // Therefore if we return back to the original caller after turning off
1113 // VMX, it will keep our current "host" CR3 value which we set on entry
1114 // to the PML4 of the SYSTEM process. We want to return back with the
1115 // correct value of the "guest" CR3, so that the currently executing
1116 // process continues to run with its expected address space mappings.
1117 //
1118
1119 __vmx_vmread(VMCS_GUEST_CR3, &GuestCr3);
1120 __writecr3(GuestCr3);
1121
1122 //
1123 // Read guest rsp and rip
1124 //
1125 __vmx_vmread(VMCS_GUEST_RIP, &GuestRIP);
1126 __vmx_vmread(VMCS_GUEST_RSP, &GuestRSP);
1127
1128 //
1129 // Read instruction length
1130 //
1131 __vmx_vmread(VMCS_VMEXIT_INSTRUCTION_LENGTH, &ExitInstructionLength);
1132 GuestRIP += ExitInstructionLength;
1133
1134 //
1135 // Set the previous register states
1136 //
1137 VCpu->VmxoffState.GuestRip = GuestRIP;
1138 VCpu->VmxoffState.GuestRsp = GuestRSP;
1139
1140 //
1141 // Notify the Vmexit handler that VMX already turned off
1142 //
1144
1145 //
1146 // Restore the previous FS, GS , GDTR and IDTR register as patchguard might find the modified
1147 //
1149
1150 //
1151 // Before using vmxoff, you first need to use vmclear on any VMCSes that you want to be able to use again.
1152 // See sections 24.1 and 24.11 of the SDM.
1153 //
1154 VmxClearVmcsState(VCpu);
1155
1156 //
1157 // Execute Vmxoff
1158 //
1159 __vmx_off();
1160
1161 //
1162 // Indicate the current core is not currently virtualized
1163 //
1164 VCpu->HasLaunched = FALSE;
1165
1166 //
1167 // Now that VMX is OFF, we have to unset vmx-enable bit on cr4
1168 //
1169 __writecr4(__readcr4() & (~X86_CR4_VMXE));
1170}
VOID HvRestoreRegisters()
Reset GDTR/IDTR and other old when you do vmxoff as the patchguard will detect them left modified.
Definition Hv.c:463
#define X86_CR4_VMXE
Definition Common.h:83
BOOLEAN IsVmxoffExecuted
Definition State.h:152