mod amd64;
mod context;
use vmi_core::{
AccessContext, Architecture, Pa, Va, VmiCore, VmiError, VmiState, driver::VmiRead,
os::VmiOsImage as _,
};
pub use self::{
amd64::{WindowsExceptionVector, WindowsInterrupt, WindowsPageTableEntry},
context::{
CONTEXT_AMD64, CONTEXT_X86, FLOATING_SAVE_AREA, KDESCRIPTOR_AMD64, KDESCRIPTOR_X86,
KSPECIAL_REGISTERS_AMD64, KSPECIAL_REGISTERS_X86, M128A, MAXIMUM_SUPPORTED_EXTENSION,
SIZE_OF_80387_REGISTERS, WindowsContext, WindowsRegistersAdapter, WindowsSpecialRegisters,
XSAVE_FORMAT,
},
};
use crate::{PeImage as _, WindowsImage, WindowsKernelInformation, WindowsOs, WindowsOsExt};
pub trait ArchAdapter<Driver>: Architecture
where
Driver: VmiRead<Architecture = Self>,
{
fn find_kernel(
vmi: &VmiCore<Driver>,
registers: &<Driver::Architecture as Architecture>::Registers,
) -> Result<Option<WindowsKernelInformation>, VmiError>;
fn syscall_argument(vmi: VmiState<WindowsOs<Driver>>, index: u64) -> Result<u64, VmiError>;
fn function_argument(vmi: VmiState<WindowsOs<Driver>>, index: u64) -> Result<u64, VmiError>;
fn function_return_value(vmi: VmiState<WindowsOs<Driver>>) -> Result<u64, VmiError>;
fn kernel_image_base(vmi: VmiState<WindowsOs<Driver>>) -> Result<Va, VmiError>;
fn is_page_present_or_transition(
vmi: VmiState<WindowsOs<Driver>>,
address: Va,
) -> Result<bool, VmiError>;
fn current_kpcr(vmi: VmiState<WindowsOs<Driver>>) -> Va;
fn dtb_to_root(value: u64) -> Pa;
}
pub trait StructLayout {
const ADDRESS_WIDTH: u64;
fn read_va<Driver>(
vmi: VmiState<WindowsOs<Driver>>,
ctx: impl Into<AccessContext>,
) -> Result<Va, VmiError>
where
Driver: VmiRead,
Driver::Architecture: ArchAdapter<Driver>;
fn read_unicode_string<Driver>(
vmi: VmiState<WindowsOs<Driver>>,
ctx: impl Into<AccessContext>,
) -> Result<String, VmiError>
where
Driver: VmiRead,
Driver::Architecture: ArchAdapter<Driver>;
}
pub struct StructLayout32;
impl StructLayout for StructLayout32 {
const ADDRESS_WIDTH: u64 = 4;
fn read_va<Driver>(
vmi: VmiState<WindowsOs<Driver>>,
ctx: impl Into<AccessContext>,
) -> Result<Va, VmiError>
where
Driver: VmiRead,
Driver::Architecture: ArchAdapter<Driver>,
{
vmi.core().read_va32(ctx)
}
fn read_unicode_string<Driver>(
vmi: VmiState<WindowsOs<Driver>>,
ctx: impl Into<AccessContext>,
) -> Result<String, VmiError>
where
Driver: VmiRead,
Driver::Architecture: ArchAdapter<Driver>,
{
vmi.os().read_unicode_string32_in(ctx)
}
}
pub struct StructLayout64;
impl StructLayout for StructLayout64 {
const ADDRESS_WIDTH: u64 = 8;
fn read_va<Driver>(
vmi: VmiState<WindowsOs<Driver>>,
ctx: impl Into<AccessContext>,
) -> Result<Va, VmiError>
where
Driver: VmiRead,
Driver::Architecture: ArchAdapter<Driver>,
{
vmi.core().read_va64(ctx)
}
fn read_unicode_string<Driver>(
vmi: VmiState<WindowsOs<Driver>>,
ctx: impl Into<AccessContext>,
) -> Result<String, VmiError>
where
Driver: VmiRead,
Driver::Architecture: ArchAdapter<Driver>,
{
vmi.os().read_unicode_string64_in(ctx)
}
}
pub(crate) fn image_codeview<Driver>(
image: &WindowsImage<Driver>,
) -> Result<Option<WindowsKernelInformation>, VmiError>
where
Driver: VmiRead,
Driver::Architecture: ArchAdapter<Driver>,
{
let debug_directory = match image.debug_directory()? {
Some(debug_directory) => debug_directory,
None => return Ok(None),
};
let codeview = match debug_directory.codeview()? {
Some(codeview) => codeview,
None => return Ok(None),
};
let nt_headers = image.nt_headers()?;
Ok(Some(WindowsKernelInformation {
base_address: image.base_address(),
version_major: nt_headers.optional_header.major_operating_system_version(),
version_minor: nt_headers.optional_header.minor_operating_system_version(),
codeview,
}))
}