This repository has been archived by the owner on Sep 1, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 30
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
18 changed files
with
1,704 additions
and
6 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,18 +1,41 @@ | ||
#![no_main] | ||
#![no_std] | ||
|
||
use log::*; | ||
use uefi::prelude::*; | ||
extern crate alloc; | ||
|
||
use { | ||
log::*, | ||
uefi::prelude::*, | ||
hypervisor::vmm::is_hypervisor_present, | ||
crate::{virtualize::virtualize_system, capture::{capture_registers, GuestRegisters}}, | ||
}; | ||
|
||
pub mod virtualize; | ||
|
||
#[entry] | ||
fn main(_image_handle: Handle, mut system_table: SystemTable<Boot>) -> Status { | ||
com_logger::builder().filter(LevelFilter::Debug).setup(); | ||
// Initialize the COM2 port logger with level filter set to Info. | ||
com_logger::builder().base(0x2f8).filter(LevelFilter::Trace).setup(); | ||
|
||
uefi_services::init(&mut system_table).unwrap(); | ||
|
||
info!("Hello, world!"); | ||
info!("The Matrix is an illusion"); | ||
|
||
// Capture the register values to be used as an initial state of the VM. | ||
let mut regs = GuestRegisters::default(); | ||
unsafe { capture_registers(&mut regs) } | ||
|
||
// Since we captured RIP just above, the VM will start running from here. | ||
// Check if our hypervisor is already loaded. If so, done, otherwise, continue | ||
// installing the hypervisor. | ||
if !is_hypervisor_present() { | ||
debug!("Virtualizing the system"); | ||
virtualize_system(®s, &system_table); | ||
} | ||
|
||
info!("The hypervisor has been installed successfully!"); | ||
|
||
system_table.boot_services().stall(10_000_000); | ||
//system_table.boot_services().stall(10_000_000); | ||
|
||
Status::SUCCESS | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
use { | ||
alloc::alloc::{alloc_zeroed, handle_alloc_error}, | ||
core::{alloc::Layout, arch::global_asm}, | ||
hypervisor::{ | ||
intel::{ | ||
capture::GuestRegisters, page::Page | ||
}, | ||
vmm::start_hypervisor | ||
}, | ||
log::debug, | ||
uefi::{ | ||
proto::loaded_image::LoadedImage, | ||
table::{Boot, SystemTable}, | ||
}, | ||
}; | ||
|
||
pub fn virtualize_system(regs: &GuestRegisters, system_table: &SystemTable<Boot>) { | ||
let boot_service = system_table.boot_services(); | ||
|
||
// Open the loaded image protocol to get the current image base and image size. | ||
let loaded_image = boot_service. | ||
open_protocol_exclusive::<LoadedImage>(boot_service.image_handle()) | ||
.unwrap(); | ||
|
||
// Get the current image base and image size. | ||
let (image_base, image_size) = loaded_image.info(); | ||
|
||
let image_base = image_base as usize; | ||
|
||
let image_range = image_base..image_base + image_size as usize; | ||
debug!("Image base: {:#x?}", image_range); | ||
|
||
// Prevent relocation by zapping the Relocation Table in the PE header. UEFI | ||
// keeps the list of runtime drivers and applies patches into their code and | ||
// data according to relocation information, as address translation switches | ||
// from physical-mode to virtual-mode when the OS starts. This causes a problem | ||
// with us because the host part keeps running under physical-mode, as the | ||
// host has its own page tables. Relocation ends up breaking the host code. | ||
// The easiest way is prevented this from happening is to nullify the relocation | ||
// table. | ||
unsafe { | ||
*((image_base + 0x128) as *mut u32) = 0; | ||
*((image_base + 0x12c) as *mut u32) = 0; | ||
} | ||
|
||
// Allocate separate stack space. This is never freed. | ||
let layout = Layout::array::<Page>(0x10).unwrap(); | ||
|
||
let stack = unsafe { alloc_zeroed(layout) }; | ||
|
||
if stack.is_null() { | ||
handle_alloc_error(layout); | ||
} | ||
|
||
let stack_base = stack as u64 + layout.size() as u64 - 0x10; | ||
debug!("Stack range: {:#x?}", stack_base..stack as u64); | ||
|
||
unsafe { switch_stack(regs, start_hypervisor as usize, stack_base) }; | ||
} | ||
|
||
extern "efiapi" { | ||
/// Jumps to the landing code with the new stack pointer. | ||
fn switch_stack(regs: &GuestRegisters, landing_code: usize, stack_base: u64) -> !; | ||
} | ||
|
||
global_asm!(r#" | ||
// The module containing the `switch_stack` function. | ||
// Jumps to the landing code with the new stack pointer. | ||
// | ||
// fn switch_stack(regs: &GuestRegisters, landing_code: usize, stack_base: u64) -> ! | ||
.global switch_stack | ||
switch_stack: | ||
xchg bx, bx | ||
mov rsp, r8 | ||
jmp rdx | ||
"#); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,90 @@ | ||
use core::arch::global_asm; | ||
|
||
extern "efiapi" { | ||
/// Captures current general purpose registers, RFLAGS, RSP, and RIP. | ||
pub fn capture_registers(registers: &mut GuestRegisters); | ||
} | ||
|
||
/// The collection of the guest general purpose register values. | ||
#[derive(Clone, Copy, Debug, Default)] | ||
#[repr(C)] | ||
pub struct GuestRegisters { | ||
rax: u64, | ||
rbx: u64, | ||
rcx: u64, | ||
rdx: u64, | ||
rdi: u64, | ||
rsi: u64, | ||
rbp: u64, | ||
r8: u64, | ||
r9: u64, | ||
r10: u64, | ||
r11: u64, | ||
r12: u64, | ||
r13: u64, | ||
r14: u64, | ||
r15: u64, | ||
rflags: u64, | ||
rsp: u64, | ||
rip: u64, | ||
} | ||
|
||
global_asm!(r#" | ||
// The module containing the `capture_registers` function. | ||
// Offsets to each field in the GuestRegisters struct. | ||
.set registers_rax, 0x0 | ||
.set registers_rbx, 0x8 | ||
.set registers_rcx, 0x10 | ||
.set registers_rdx, 0x18 | ||
.set registers_rdi, 0x20 | ||
.set registers_rsi, 0x28 | ||
.set registers_rbp, 0x30 | ||
.set registers_r8, 0x38 | ||
.set registers_r9, 0x40 | ||
.set registers_r10, 0x48 | ||
.set registers_r11, 0x50 | ||
.set registers_r12, 0x58 | ||
.set registers_r13, 0x60 | ||
.set registers_r14, 0x68 | ||
.set registers_r15, 0x70 | ||
.set registers_rflags, 0x78 | ||
.set registers_rsp, 0x80 | ||
.set registers_rip, 0x88 | ||
// Captures current general purpose registers, RFLAGS, RSP, and RIP. | ||
// | ||
// extern "efiapi" fn capture_registers(registers: &mut GuestRegisters) | ||
.global capture_registers | ||
capture_registers: | ||
// Capture general purpose registers. | ||
mov [rcx + registers_rax], rax | ||
mov [rcx + registers_rbx], rbx | ||
mov [rcx + registers_rcx], rcx | ||
mov [rcx + registers_rdx], rdx | ||
mov [rcx + registers_rsi], rsi | ||
mov [rcx + registers_rdi], rdi | ||
mov [rcx + registers_rbp], rbp | ||
mov [rcx + registers_r8], r8 | ||
mov [rcx + registers_r9], r9 | ||
mov [rcx + registers_r10], r10 | ||
mov [rcx + registers_r11], r11 | ||
mov [rcx + registers_r12], r12 | ||
mov [rcx + registers_r13], r13 | ||
mov [rcx + registers_r14], r14 | ||
mov [rcx + registers_r15], r15 | ||
// Capture RFLAGS, RSP, and RIP. | ||
pushfq | ||
pop rax | ||
mov [rcx + registers_rflags], rax | ||
mov rax, rsp | ||
add rax, 8 | ||
mov [rcx + registers_rsp], rax | ||
mov rax, [rsp] | ||
mov [rcx + registers_rip], rax | ||
ret | ||
"#); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
// pub mod hooks; | ||
pub mod mtrr; | ||
pub mod paging; |
Oops, something went wrong.