- Notifications
You must be signed in to change notification settings - Fork104
Lightweight Intel VT-x Hypervisor.
License
jonomango/hv
Folders and files
Name | Name | Last commit message | Last commit date | |
---|---|---|---|---|
Repository files navigation
hv
is an x86-64Intel VT-xhypervisor that aims to be simple and lightweight, while still following the Intel SDM as closely as possible.This allows it to evade detections that take advantage of common hypervisor bugs, such as impropervm-exit handling. Other detections, such as timing checks, aremostly mitigated, although stayingfully undetected is nearly impossible.
To clone the repo:
git clone--recursive https://github.com/jonomango/hv.git
hv
is a Windows driver built with MSVC. It requiresVisual Studio and theWDK for compilation.
Once compiled, simply loadhv.sys
anyway you'd like (either by using the Windows Service Control Manageror a manual mapper) and it will immediately virtualize the system. To check ifhv
iscurrently running, try to execute the ping hypercall and see if it responds appropriately. Unloadingthe driver will result inhv::stop()
being called, which will devirtualize the system.
hv
has a full hypercall interface that can be used from both ring-0 and ring-3. It relies on theVMCALL
instruction and has a particular calling convention that must be followed. Check outum/hv.asm for how this can be implemented.
Additionally, hypercalls will not function correctly unless provided with the correcthypercall_key. This can be easily modifiedin the source code and is used to ensure that malicious guests cannot execute any hypercalls.
Example of executing theping
hypercall:
// setup the hypercall inputhv::hypercall_input input;input.code = hv::hypercall_ping;input.key = hv::hypercall_key;// execute the hypercallautoconst value = hv::vmx_vmcall(input);if (value == hv::hypervisor_signature)printf("pong!\n");
Extending the hypercall interface is pretty simple. Add your new hypercall handler tohv/hypercalls.h andhv/hypercalls.cpp, then modifyemulate_vmcall() to callyour added function.
Below is a list of important functions that can be safely called from root-mode,which can be used by includingintrospection.h
. It is important to note thatany code that lies outside of the hypervisor (i.e. kernel code) cannot be calledfrom root-mode, and the following functions should be used instead.
// get the KPCR of the current guest (this pointer should stay constant per-vcpu)PKPCRcurrent_guest_kpcr();// get the ETHREAD of the current guestPETHREADcurrent_guest_ethread();// get the EPROCESS of the current guestPEPROCESScurrent_guest_eprocess();// get the PID of the current guestuint64_tcurrent_guest_pid();// get the kernel CR3 of the current guestcr3current_guest_cr3();// get the image file name (up to 15 chars) of the current guest processboolcurrent_guest_image_file_name(char (&name)[16]);// get the CPL (current privilege level) of the current guestuint16_tcurrent_guest_cpl();// attempt to read the memory at the specified guest virtual address from root-modesize_tread_guest_virtual_memory(cr3 guest_cr3,void* gva,void* buffer,size_t size);// attempt to read the memory at the specified guest virtual address from root-modesize_tread_guest_virtual_memory(void* gva,void* buffer,size_t size);// attempt to read the memory at the specified guest physical address from root-modeboolread_guest_physical_memory(uint64_t gpa,void* buffer,size_t size);
hv
has a simple printf-style logger that can be used from both root-mode orguest-mode. It can be found inlogger.h
and the logs can be retrieved throughtheflush_logs
hypercall. Different log types can be omitted by simply modifyingthe defines inlogger.h
.
// 3 different log types are supported:HV_LOG_INFO("Hello world!");HV_LOG_ERROR("Error on line %i.",69);HV_LOG_VERBOSE("Junk... %s","More junk...");
The logger supports a small subset of printf-style formatting:
%s c-style strings%i or %d 32-bit signed integer%u 32-bit unsigned integer%x 32-bit unsigned integer (printed in hex, lowercase)%X 32-bit unsigned integer (printed in hex, uppercase)%p 64-bit unsigned integer (printed in hex)
Below is an example of reading the logs, which can be done from ring-0 or ring-3.
// read the logs into a bufferuint32_t count =512;hv::logger_msg msgs[512];hv::flush_logs(count, msgs);// print every log messagefor (uint32_t i =0; i < count; ++i)printf("%s\n", msgs[i].data);
About
Lightweight Intel VT-x Hypervisor.