GithubHelp home page GithubHelp logo

ionescu007 / simplevisor Goto Github PK

View Code? Open in Web Editor NEW
1.7K 98.0 258.0 187 KB

SimpleVisor is a simple, portable, Intel VT-x hypervisor with two specific goals: using the least amount of assembly code (10 lines), and having the smallest amount of VMX-related code to support dynamic hyperjacking and unhyperjacking (that is, virtualizing the host state from within the host). It works on Windows and UEFI.

Home Page: http://ionescu007.github.io/SimpleVisor/

C 93.45% Assembly 6.55%

simplevisor's Introduction

SimpleVisor

SimpleVisor is a simple, portable, Intel x64/EM64T VT-x specific hypervisor with two specific goals: using the least amount of assembly code (10 lines), and having the smallest amount of VMX-related code to support dynamic hyperjacking and unhyperjacking (that is, virtualizing the host state from within the host) while also supporting advanced features such as EPT and VPID. It currently runs on both Windows and in UEFI environments.

Introduction

Have you always been curious on how to build a hypervisor? Has Intel's documentation (the many hundreds of pages) gotten you down? Have the samples you've found online just made things more confusing, or required weeks of reading through dozens of thousands of lines and code? If so, SimpleVisor might be the project for you.

Not counting the exhaustive comments which explain every single line of code, and specific Windows-related or Intel-related idiosyncrasies, SimpleVisor clocks in at about 500 lines of C code, and 10 lines of x64 assembly code, all while containing the ability to run on every recent version of 64-bit Windows, and supporting dynamic load/unload at runtime.

Additionally, SimpleVisor utilizes a lightweight OS-library for Windows-specific functionality, separating out the hypervisor pieces from the Windows-specific pieces. Leveraging this portable design, a UEFI version of SimpleVisor is also now available. Note however, that it does not have robust support for MP environments due to issues with UEFI, and that loading an operating system will eventually result in a crash as the OS will hit unimplemented code paths due to its re-configuration of processor resources. Virtualizing the entire boot of the operating system from UEFI is beyond the scope of the project.

SimpleVisor can be built with Visual Studio 2015 Update 3, and while older/newer compilers have not been tested and are not supported, it's likely that they can build the project as well. It's important, however, to keep the various compiler and linker settings as you see them, however.

SimpleVisor has currently been tested on the following platforms successfully:

  • Windows 8.1 on a Haswell Processor (Custom Desktop)
  • Windows 10 Redstone 1 on a Sandy Bridge Processor (Samsung 930 Laptop)
  • Windows 10 Threshold 2/Redstone 1 on a Skylake Processor (Surface Pro 4 Tablet)
  • Windows 10 Threshold 2 on a Skylake Processor (Dell Inspiron 11-3153 w/ SGX)
  • VMWare Workstation 11, but without EPT (VMWare does not support 1GB EPTs)
  • UEFI 2.4 on an Asus Maximus VII Extreme Motherboard (Custom Desktop)

At this time, it has not been tested on Bochs, but there's no reason why SimpleVisor could not run in such an environment as well. However, if your machine is already running under a hypervisor such as Hyper-V or Xen, SimpleVisor will not load.

Keep in mind that x86 versions of Windows are expressly not supported, nor are processors earlier than the Nehalem microarchitecture, nor is Windows 7. Support for the latter two is easy to add and exists in certain forks.

Motivation

Too many hypervisor projects out there are either extremely complicated (Xen, KVM, VirtualBox) and/or closed-source (VMware, Hyper-V), as well as heavily focused toward Linux-based development or system. Additionally, most (other than Hyper-V) of them are expressly built for the purpose of enabling the execution of virtual machines, and not the virtualization of a live, running system, in order to perform introspection or other security-related tasks on it.

A few projects do stand out from the fold however, such as the original Blue Pill from Joanna, or projects such as VirtDbg and HyperDbg. Unfortunately, most of these have become quite old by now, and some only function on x86 processors, and don't support newer operating systems such as Windows 10. Another rather simple example, similar to Blue Pill in some aspects, but actually delivering a good example of EPT use for "Split-TLB" is MoRE from Jacob Torrey/AIS.

The closest project that actually delivers a Windows-centric, modern, and supported hypervisor is HyperPlatform, and we strongly recommend its use as a starting place for more broadly usable research-type hypervisor development. However, in attempting to create a generic "platform" that is more broadly robust, HyperPlatform also suffers from a bit of bloat, making it harder to understand what truly are the basic needs of a hypervisor, and how to initialize one. In a similar vein, and showing an equal love for STL/C++, but also including an ELF loader and UEFI/Linux support alongside unit tests and even more robustness is Bareflank, also from AIS. Beyond that, you're probably getting into Xen-level complexity.

The express goal of this project, as stated above, was to minimize code in any way possible, without causing negative side-effects, and focusing on the 'bare-metal' needs. This includes:

  • Minimizing use of assembly code. If it weren't for the lack of an __lgdt intrinsic, and a workaround for the behavior of a Windows API, only the first 4 instructions of the hypervisor's entry point would require assembly. As it stands, the project has a total of 10 instructions, spread throughout 3 functions. This is a massive departure from other hypervisor projects, which often have multiple hundreds of line of assembly code. A variety of OS-specific tricks and compiler shortcuts are used to achieve this result.
  • Reducing checks for errors which are unlikely to happen. Given a properly configured, and trusted, set of input data, instructions such as vmx_vmwrite and vmx_vmread should never fail, for example.
  • Removing support for x86, which complicates matters and causes special handling around 64-bit fields.
  • Expressly reducing all possible VM-Exits to only the Intel architecturally defined minimum (CPUID, INVD, VMX Instructions, and XSETBV). This is purposefully done to keep the hypervisor as small as possible, as well as the initialization code.
  • No support for VMCALL. Many hypervisors use VMCALL as a way to exit the hypervisor, which requires assembly programming (there is no intrinsic) and additional exit handling. SimpleVisor uses a CPUID trap instead.
  • Relying on little-known OS functions to simplify development of the hypervisor, such as Generic DPCs and hibernation contexts on Windows, or the PI MP protocol on UEFI.
  • Supporting EPT/VPID in a very simple fashion, to demonstrate a solid base of the simplest possible implementation of the feature.
  • Portability and isolation of OS-specific routines.

Another implied goal was to support the very latest in hardware features, as even Bochs doesn't always have the very-latest Intel VMX instructions and/or definitions. These are often found in header files such as "vmcs.h" and "vmx.h" that various projects have at various levels of definition. For example, Xen master has some unreleased VM Exit reasons, but not certain released ones, which Bochs does have, albeit it doesn't have the unreleased ones! One such example is the usage of 1GB EPT entries, which for example VMWare does not virtualize correctly.

Finally, SimpleVisor is meant to be an educational tool -- it has exhaustive comments explaining all logic behind each line of code, and specific Windows or Intel VMX tips and tricks that allow it to achieve its desired outcome. Various bugs or poorly documented behaviors are called out explicitly.

Installation on Windows

Because x64 Windows requires all drivers to be signed, you must testsign the SimpleVisor binary. The Visual Studio project file can be setup to do so by using the "Driver Signing" options and enabling "Test Sign" with your own certificate. From the UI, you can also generate your own.

Secondly, you must enable Test Signing Mode on your machine. To do so, first boot into UEFI to turn off "Secure Boot", otherwise Test Signing mode cannot be enabled. Alternatively, if you possess a valid KMCS certificate, you may "Production Sign" the driver to avoid this requirement.

To setup Test Signing Mode, you can use the following command:

bcdedit /set testsigning on

After a reboot, you can then setup the required Service Control Manager entries for SimpleVisor in the registry with the following command:

sc create simplevisor type= kernel binPath= "<PATH_TO_SIMPLEVISOR.SYS>"

You can then launch SimpleVisor with

sc start simplevisor

And stop it with

sc stop simplevisor

You must have administrative rights for usage of any of these commands.

References

If you would like to know more about my research or work, I invite you check out my blog at http://www.alex-ionescu.com as well as my training & consulting company, Winsider Seminars & Solutions Inc., at http://www.windows-internals.com.

https://github.com/upring/virtdbg

http://xenbits.xen.org/gitweb/?p=xen.git;a=summary

https://github.com/svn2github/bochs

https://github.com/rmusser01/hyperdbg

http://invisiblethingslab.com/resources/bh07/nbp-0.32-public.zip

https://github.com/tandasat/HyperPlatform

https://github.com/ainfosec/MoRE

https://github.com/Bareflank/hypervisor

Caveats

SimpleVisor is designed to minimize code size and complexity -- this does come at a cost of robustness. For example, even though many VMX operations performed by SimpleVisor "should" never fail, there are always unknown reasons, such as memory corruption, CPU errata, invalid host OS state, and potential bugs, which can cause certain operations to fail. For truly robust, commercial-grade software, these possibilities must be taken into account, and error handling, exception handling, and checks must be added to support them. Additionally, the vast array of BIOSes out there, and different CPU and chipset iterations, can each have specific incompatibilities or workarounds that must be checked for. SimpleVisor does not do any such error checking, validation, and exception handling. It is not robust software designed for production use, but rather a reference code base.

License

Copyright 2016 Alex Ionescu. All rights reserved. 

Redistribution and use in source and binary forms, with or without modification, are permitted provided
that the following conditions are met: 
1. Redistributions of source code must retain the above copyright notice, this list of conditions and
   the following disclaimer. 
2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions
   and the following disclaimer in the documentation and/or other materials provided with the 
   distribution. 

THIS SOFTWARE IS PROVIDED BY ALEX IONESCU ``AS IS'' AND ANY EXPRESS OR IMPLIED
WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ALEX IONESCU
OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

The views and conclusions contained in the software and documentation are those of the authors and
should not be interpreted as representing official policies, either expressed or implied, of Alex Ionescu.

simplevisor's People

Contributors

gbps avatar ionescu007 avatar jtsylve avatar saaramar avatar tandasat avatar tezeb avatar wbenny avatar zachriggle avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

simplevisor's Issues

Can't build on Windows 8.1

I'm trying to build on Windows 8.1. I have the Windows 8.1 WDK installed. I have made no changes to the config other than setting the target to Windows 8.1. When I attempt to build, I get this:

The command "ml64.exe /c /nologo /Zi /Fo"x64\Optimized\shvosx64.obj" /W3 /errorReport:prompt  /Tant\shvosx64.asm" exited with code 1.

I've been messing around for a bit, but I can't get it to work. If I go into a VS command prompt, the command works. I'm using Visual Studio Community Update 3.

Calling convention not respected by ShvVmxEntry

The ShvVmxEntry function performs the jump to ShvVmxEntryHandler without allocating the parameter stack area (32 bytes for 4 parameters - see https://msdn.microsoft.com/en-us/library/ew5tede7.aspx).

The result is that the ShvVmxEntryHandler function may clobber the guest rcx value stored on the stack before actually saving it in the CONTEXT structure - out of luck this didn't seem to happen on the optimized build, but on debug it happens.

As a note, care must also be taken to make sure the stack is always 16-byte aligned when the jump is made - because of the way the host RSP is calculated and because the CONTEXT structure is 16 byte aligned this problem seems to be solved.

crash on debug code

When use the option "/Od", Windows must be BSOD, in my VMWare
I found that it is caused by ShvOsCaptureContext
Via IDA, the function is jmp RtlCaptureContext with "/Ox"
and is sub rsp, xxx; ...; call RtlCaptureContext; add rsp, xxx; retn; with "/Od"
so, move the implement to asm, simple to jmp, and it worked fine on debug code

Question about "UINT64 PageFrameNumber : 36"

Hi,
In VMX_EPTP, VMX_EPML4E, VMX_PDPTE, MTRR_VARIABLE_BASE & MTRR_VARIABLE_MASK structures, there is a member defined as:
UINT64 PageFrameNumber : 36

Intel manual says size of this field should be MAXPHYADDR, which is obtained by CPUID.80000008H:EAX[7:0] (39 on my machine).

Intel also says:

the width is generally 36 if CPUID.01H:EDX.PAE [bit 6] = 1 and 32 otherwise.)
... MAXPHYADDR is at most 52

My question is: couldn't this cause problems (assuming the available RAM is really, really big) & wouldn't it be better to simply define this field as:
UINT64 PageFrameNumber : 52
?

I assume "unused" bits are set to 0 anyway.

question how works

hi is there a simple document how works? Sincerelly except a definition i cant find a mini document explaining how works the mechanism for hypervisor.
Ideally i imagined you define a memory area where you can work , you load the code in that area and if a instruction is trying to go outside there is a trap to a specific function in hypervisor.
a special trap is used also for instructions with IO accesses. But this is just a my idea.How it is possible to associate a trap to hypervisor for wrong memory access,...?
is there a way for creating a trap in user mode in the memory access?

Run SimpleVisor on Xen

The Xen supports Nested Virtualization, that means I can run Xen or KVM hypervisor inside a virtual machine of Xen, however I can't run SimpleVisor on Xen.

Is it able to run SimpleVisor inside a vitual machine of Xen?

UEFI compilation

Hi,

The VS project creates a .sys file by default. A short guide how to generate the efi version (UEFI) would be just great.

Overview?

I really like the idea of this project, but I'm new to this and was wondering if there is some overview of the project.

ShvOsCaptureContext suffers from stack corruptions on restore

ShvOsCaptureContext​ (at least the nt implementation) can suffer from stack corruptions when restoring the context.

The reason is that it adds an extra stack frame when calling RtlCaptureContext. While capturing the registers, including the stack pointer, it does not capture the data on the stack.

That means the captured stack pointer points to data, that might and will be overwriten by future function calls after ShvOsCaptureContext​ has returned.

In consequence, control flow will not continue here after a launch: https://github.com/ionescu007/SimpleVisor/blob/master/shvvp.c#L143
But rather here instead: https://github.com/ionescu007/SimpleVisor/blob/master/shvvp.c#L149 right after the call to ShvVmxLaunchOnVp

The reason is that the return pointer on the stack, where rsp of the stored context points to, is overwritten by the call to ShvVmxLaunchOnVp.

Either ShvOsCaptureContext would need to be inlined or a fixup must be done to remove the extra frame from the captured context.

Question about VM_EXIT_ACK_INTR_ON_EXIT

Hi,
is setting VM_EXIT_ACK_INTR_ON_EXIT flag really necessary, if PIN_BASED_EXT_INTR is not set? I hope it's not super stupid question, but if I understand Intel Manual correctly, you shouldn't get any VMEXITs for external interrupts when PIN_BASED_EXT_INTR is not set - and if this is the case, the VM_EXIT_ACK_INTR_ON_EXIT is unnecessary.

I'm quite confused by this - I've been stuck on the VM_EXIT_ACK_INTR_ON_EXIT flag for too long in the Intel Manual, and when I thought I understand what it does, I realised many "simple opensource hypervisors" unneccessarily set it (SimpleVisor, ksm, HyperPlatform, ...).

So now I'm wondering, if either my understanding is correct OR if everyone just blatantly copy-pasted this practice from somewhere :)

If I'm completely wrong, I would be glad if you corrected me.

Question:ShvVmxMtrrAdjustEffectiveMemoryType Wrong?

This judgment can guarantee 2M space is within the scope of it?
if (((LargePageAddress + _2MB) >= VpData->MtrrData[i].PhysicalAddressMin) &&
(LargePageAddress <= VpData->MtrrData[i].PhysicalAddressMax))
I think It should be:
if (((LargePageAddress + _2MB) <= VpData->MtrrData[i].PhysicalAddressMax) &&
(LargePageAddress >= VpData->MtrrData[i].PhysicalAddressMin))

Updating description on HyperPlatform

Hi,

Would you mind updating a description on HyperPlatform in README? While it is true that HyperPlatform suffer from certain complexity comparared with SimpleVisor, it is designed for a research platform and not quite for commercial and/or production usage.

Also, please let me know if you think HyperPlatform can seen as if it were aiming for production-level use. Since I am one of authors of HyperPlatform, I am very happy with updating a description of HyperPlatform to give a right understanding of the project.

Thank you,

How to use preemption timer in simplevisor?

Hi,
I turn on the preemption timer in the simplevisor.When the timer count reaches 0, it will trigger vm exit(no.52).Every VM exit (No. 52), I will read the tsc value in ShvVmxEntryHandler.
My question is:1.The period of Vm exit (No. 52) differs greatly from the theoretical value;2.Windows will restart randomly.
Could you help me or give me some suggestions.Thanks.

General Protection Fault in ShvVmxLaunchOnVp

I'm getting a general protection fault when starting the service.

1: kd> k
 # Child-SP          RetAddr           Call Site
00 ffffd001`1399b658 fffff803`71bd1afe nt!KeBugCheckEx
01 ffffd001`1399b660 fffff803`71b5a80d nt!KiFatalExceptionHandler+0x22
02 ffffd001`1399b6a0 fffff803`71a17139 nt!RtlpExecuteHandlerForException+0xd
03 ffffd001`1399b6d0 fffff803`71a155a8 nt!RtlDispatchException+0x429
04 ffffd001`1399bdd0 fffff803`71b5f3c2 nt!KiDispatchException+0x144
05 ffffd001`1399c4b0 fffff803`71b5d87d nt!KiExceptionDispatch+0xc2
06 ffffd001`1399c690 fffff801`046508e5 nt!KiGeneralProtectionFault+0xfd
07 ffffd001`1399c820 fffff801`04650c4e SimpleVisor!ShvVmxLaunchOnVp+0x21 [c:\users\joe\source\repos\simplevisor\shvvmx.c @ 379]
08 ffffd001`1399c850 fffff801`04650ca3 SimpleVisor!ShvVpInitialize+0xb2 [c:\users\joe\source\repos\simplevisor\shvvp.c @ 101]
09 ffffd001`1399c880 fffff803`71a806a0 SimpleVisor!ShvVpCallbackDpc+0x47 [c:\users\joe\source\repos\simplevisor\shvvp.c @ 161]
0a ffffd001`1399c8c0 fffff803`71a7fdb9 nt!KiExecuteAllDpcs+0x270
0b ffffd001`1399ca10 fffff803`71b5751a nt!KiRetireDpcList+0xe9
0c ffffd001`1399cc60 00000000`00000000 nt!KiIdleLoop+0x5a
1: kd> .frame 0n7;dv /t /v
07 ffffd001`1399c820 fffff801`04650c4e SimpleVisor!ShvVmxLaunchOnVp+0x21 [c:\users\joe\source\repos\simplevisor\shvvmx.c @ 379]
@rdi              struct _SHV_VP_DATA * VpData = 0xffffe000`1760a000
@r8d              unsigned long i = 0x11

The offending line of code seems to be the __readmsr below

    //
    // Initialize all the VMX-related MSRs by reading their value
    //
    for (i = 0; i < RTL_NUMBER_OF(VpData->MsrData); i++)
    {
        VpData->MsrData[i].QuadPart = __readmsr(MSR_IA32_VMX_BASIC + i);
    }

Driver blocked from loading

I'm running win7 pro x64 inside vmware. Test signing is on.

C:\>sc start sv
[SC] StartService FAILED 1275:

This driver has been blocked from loading

What's interesting is that MemoryMon works fine:

C:\>sc start mm

SERVICE_NAME: mm
        TYPE               : 1  KERNEL_DRIVER
        STATE              : 4  RUNNING
                                (STOPPABLE, NOT_PAUSABLE, IGNORES_SHUTDOWN)
        WIN32_EXIT_CODE    : 0  (0x0)
        SERVICE_EXIT_CODE  : 0  (0x0)
        CHECKPOINT         : 0x0
        WAIT_HINT          : 0x0
        PID                : 0
        FLAGS              :

Any idea what's the problem?

AMD support

If I understand correctly this hypervisor only supports intel?
Is there any plans to support amd aswell?

Is this line code right?

Hi, the 'shvvmx.c' line 131. Is the code "ShvOsGetPhysicalAddress(&VpData->Epdpt)" right ? I think maybe the code "ShvOsGetPhysicalAddress(VpData->Epdpt)" is right. ;)

ShvUtilConvertGdtEntry confusion

I'm quite new to segmentation, so please bare with me.

To get a segment descriptor entry from GDT we have to access the GDT like an array. Each entry in the GDT is 8 bytes, according to the Intel SDM. To my understanding we can therefore access the GDT like:

PSEGMENT_DESCRIPTOR32 Table = ( PSEGMENT_DESCRIPTOR32 )GdtBase;
PSEGMENT_DESCRIPTOR32 Segment = &GdtBase[ Selector.Index ];

Or, what this is equivalent to:

UINTPTR GdtBase = ..;
PSEGMENT_DESCRIPTOR32 Segment;
Segment = ( PSEGMENT_DESCRIPTOR32 )( GdtBase + ( Selector.Index * 8 ) );

Now, while learning, I read the source to a bunch of different hypervisors. Specifically - Gbhv. Gbhv gets segment descriptors from GDT using the exact method above.
https://github.com/Gbps/gbhv/blob/master/gbhv/vmx.c#L178

OsSegmentDescriptor = (PSEGMENT_DESCRIPTOR_64)(((UINT64)GdtRegister.BaseAddress) + (SegmentSelector.Index << 3));

The bitshift to the left by 3 is the same as multiplication by 8, so this is basically exactly the same as the code I wrote above. However, you do it completely differently in SimpleVisor, and I'm very confused as to why.

https://github.com/ionescu007/SimpleVisor/blob/master/shvutil.c#L50

gdtEntry = (PKGDTENTRY64)((uintptr_t)GdtBase + (Selector & ~RPL_MASK));

I understand the Selector & ~RPL_MASK part. You're masking away Rpl & Table bits to extract the index from the selector. But you are not multiplying it by the size of a descriptor (8). Since you're casting GdtBase to a uintptr_t - an integer, this is using integer arithmetic (duh), so it's not accessing the entry in the GDT properly. I'm super confused, because I've personally ran SimpleVisor in the past on both a VMware guest, and on my host system - and it worked. Why? Am I missing something, or is this simply a bug?

Enabling interrupts in VMEXIT?

I'm trying to implement a vmcall to read memory from another process, but I get BSOD with DRIVER_IRQL_NOT_LESS_OR_EQUAL.

Arg1: 0000023170e8e050, memory referenced
Arg2: 00000000000000ff, IRQL
Arg3: 0000000000000000, value 0 = read operation, 1 = write operation
Arg4: fffff800f1ef1773, address which referenced memory

It says IRQL is 0xFF, but when I check with KeGetCurrentIrql() it gives me 0(PASSIVE_LEVEL)?

The vmcall is made from the usermode app -> causes vmexit -> which executes vmcall handler.

I store in RCX the call index(VMCallFuncIndex), RDX containing a usermode pointer to a structure of data for the memory i/o request, R8 as current process(GetCurrentProcessId() currently for testing),

	case vmcall_read_memory:
	{
		/*
		KIRQL irql_lvl = KeGetCurrentIrql();
		DbgPrint("IRQL_LVL = %d", (ULONG)irql_lvl); //PASSIVE_LEVEL
		*/
		DbgPrint("Attaching to PID: %d\r\n", VpState->VpRegs->R8);
		PEPROCESS local, remote;
		if (!NT_SUCCESS(PsLookupProcessByProcessId((HANDLE)VpState->VpRegs->R8, &local)))
			local = NULL;
		if (local) {
			sIOReq req;
			KAPC_STATE apc_state;
			KeStackAttachProcess(local, &apc_state);
			RtlCopyMemory(&req, (void*)VpState->VpRegs->Rdx, sizeof(sIOReq));
			KeUnstackDetachProcess(&apc_state);
			VpState->VpRegs->Rax = 0;
			DbgPrint("target pid == %d\r\n", req.remote_pid);
			DbgPrint("success\r\n");
		}
		else
			DbgPrint("local == nullptr\r\n");

The code looks correct to me, so i'm not sure what is wrong.
(1 hour later)
So I opened up the crash dump in windbg and the first thing I noticed is:
FAILURE_ID_HASH_STRING: km:disabled_interrupt_fault_stackptr_error_hypervisor!vmxhandlevmcall
Which makes me speculate: Are interrupts disabled?
So I searched already opened issues on SV, and found this:
#3

So I decided to try it myself:

switch (VMCallFuncIndex) {
	case vmcall_read_memory:
	{
		/*
		KIRQL irql_lvl = KeGetCurrentIrql();
		DbgPrint("IRQL_LVL = %d", (ULONG)irql_lvl); //PASSIVE_LEVEL
		*/
		KIRQL old_irql = KeRaiseIrqlToDpcLevel();
		_enable();
		DbgPrint("Attaching to PID: %d\r\n", VpState->VpRegs->R8);
		PEPROCESS local, remote;
		if (!NT_SUCCESS(PsLookupProcessByProcessId((HANDLE)VpState->VpRegs->R8, &local)))
			local = NULL;
		if (local) {
			sIOReq req;
			KAPC_STATE apc_state;
			KeStackAttachProcess(local, &apc_state);
			RtlCopyMemory(&req, (void*)VpState->VpRegs->Rdx, sizeof(sIOReq));
			KeUnstackDetachProcess(&apc_state);
			VpState->VpRegs->Rax = 0;
			DbgPrint("target pid == %d\r\n", req.remote_pid);
			DbgPrint("success\r\n");
		}
		else
			DbgPrint("local == nullptr\r\n");
		_disable();
		KeLowerIrql(old_irql);
		return;

But I still get BSOD, however while it's still the same old DRIVER_IRQL_NOT_LESS_OR_EQUAL, this time it shows the IRQL as being 0x2.

Arg1: 0000026f1c1ee0c0, memory referenced
Arg2: 0000000000000002, IRQL
Arg3: 0000000000000000, value 0 = read operation, 1 = write operation
Arg4: fffff800a6511783, address which referenced memory

It shows the faulting IP as being:

hypervisor!VmxHandleVMCall+a3 [c:\users\yuuar\source\repos\vt-x\hypervisor\source.c @ 519]
fffff800`a6511783 0f1001          movups  xmm0,xmmword ptr [rcx]

which seems to be this line:

RtlCopyMemory(&req, (void*)VpState->VpRegs->Rdx, sizeof(sIOReq));

So i'm not sure what's going on.

SimpleVisor: Booting OS

Hello,
i read that Simplevisor doesn't support the booting of Operating Systems right now. Could you explain what problems could occur?
Right now i am experimenting with SimpleVisor. I am loading the hypervisor (as Unrestricted Guest) in UEFI. But as soon as the kernel is running it crashes.

EDIT: it might be a memory problem, because it crashes randomly. Sometimes right at the start or at login screen.

crash under my laptop

compiled and run, it crashes under windows 10 x64 on my laptop, the kernel dump is attached.
CPU: i5-7200U
Memory: 8G
BIOS: LENOVO R0IET38W (1.16 ), UEFI

032018-10203-01.zip

seems it run out of pages, but don't know why. I've tested on another laptop its ok.

Cannot open include file

Maybe I'm too new to Visual Studio, but I replaced all includes of EDK to where I have EDK stored, got rid of all inherited values, but still getting an error from not being able to include, "Cannot open include file: 'C:\Users\aione\Documents\GitHub\VisualUefi\edk2..\EDK-II\BaseLib\vshacks.h': No such file or directory", which I created a system wide environment variable for EDK named $(EDK_PATH), since it seemed like a good easy way to fix it as well as use it in the future whenever I need, but it is still throwing errors as if there is some hidden include that is inheriting it.

ShvVmxEntryHandler does not enable interrupts

I couldn't help but notice in the ShvVmxEntryHandler function you state in your comment that you want to receive clock and IPI interrupts to occur and as a result you raise the IRQL appropriately.

However, on each VMEXIT the value of the RFLAGS register is set to 0x2 (as stated in 27.5.3 of Intel System Programming Manual Volume 3). As a result if you want to be able to receive interrupts while in VMX root mode you need to enable interrupts after raising the IRQL.

Using SimpleVisor to run dynamic recompiled code emulating non-x86-64 code

I see no other way for discussing how it may be possible for SimpleVisor to run dynamic recompiled code emulating non-x86-64 code.

I have written an emulator which runs some PSP programs (based on a customized MIPS32 ISA) and I would like to extend some of my realizations to other guest ISAs.

The emulator is using an HLE (High Level Emulation) principle: dynamically recompiling a user-land guest code into a native host code; kernel and hardware relative guest code are directly compiled from native host source so there is no need to emulate any functionality or hardware at lower level. Basically, a syscall will call a native host function instead of trying to emulate guest instructions step by step inside the syscall.

The dynamic compiler emits x86-64 instructions and uses its own ABI if I can say this way: up to 12 GPR registers are available for the integer register allocator. By not trying to comply with the usual Windows 64-bit ABI, I can allow faster emulation. The key is the chains of basic blocks is totally built by the dynarec so the usual ABI is not needed to be saved and restored between host basic blocks (only when calling a syscall). Some details can be found here and there.

I have different fields I would like to address with a hypervisor like yours and check if it is possible:

  1. To execute the chains of the generated code inside a dedicated logical processor. A call to a guest syscall will exit to native Windows code to execute a functionality or recompile a new guest code. Idealistically I want that generated code being inside the first virtual 4GB address range to keep the ICache array with 32-bit function pointers as entries since most ISAs I want to emulate have 32-bit pointers. I sometimes wonder if this logical processor may need its own memory mapping or not. Is that possible with SimpleVisor or would it be better to keep the same memory mapping as the running Windows program?

  2. To get a perfect memory emulation which mimics the guest memory mapping. I used some Windows specific tricks to be able to have a very fast memory access. While it may be enough for emulating PSP , it may not for other architectures. Another possibility I can see is to use fs segment when running generated code in its logical processor (no sure if gs can also be used for another purpose as long as logical processor doesn't exit, or can it ?). This way, fs segment may map the whole 4GB of the guest memory (also called dcache), and a simple MOV or MOVBE can be done with a FS prefix to access this guest memory. If gs can also be used, it could also map the huge icache (for each guest address, it maps a potential recompiled basic block to jump into, or to recompiler code to create a new basic block) and would allow very fast execution of chains of host basic blocks.

For those two points, do you think SimpleVisor may help?

Best regards.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.