use std::prelude::v1::*;
use super::{Win32Kernel, Win32KernelInfo};
use crate::offsets::Win32Offsets;
#[cfg(feature = "symstore")]
use crate::offsets::SymbolStore;
use crate::offsets::offset_builder_with_kernel_info;
use memflow::architecture::ArchitectureIdent;
use memflow::cglue::forward::ForwardMut;
use memflow::error::Result;
use memflow::mem::{
phys_mem::CachedPhysicalMemory, virt_translate::CachedVirtualTranslate, DirectTranslate,
PhysicalMemory, VirtualTranslate2,
};
use memflow::types::{Address, DefaultCacheValidator};
pub struct Win32KernelBuilder<T, TK, VK> {
connector: T,
arch: Option<ArchitectureIdent>,
kernel_hint: Option<Address>,
dtb: Option<Address>,
#[cfg(feature = "symstore")]
symbol_store: Option<SymbolStore>,
build_page_cache: Box<dyn FnOnce(T, ArchitectureIdent) -> TK>,
build_vat_cache: Box<dyn FnOnce(DirectTranslate, ArchitectureIdent) -> VK>,
}
impl<T> Win32KernelBuilder<T, T, DirectTranslate>
where
T: PhysicalMemory,
{
pub fn new(connector: T) -> Win32KernelBuilder<T, T, DirectTranslate> {
Win32KernelBuilder {
connector,
arch: None,
kernel_hint: None,
dtb: None,
#[cfg(feature = "symstore")]
symbol_store: Some(SymbolStore::default()),
build_page_cache: Box::new(|connector, _| connector),
build_vat_cache: Box::new(|vat, _| vat),
}
}
}
impl<'a, T, TK, VK> Win32KernelBuilder<T, TK, VK>
where
T: PhysicalMemory,
TK: 'static + PhysicalMemory + Clone,
VK: 'static + VirtualTranslate2 + Clone,
{
pub fn build(mut self) -> Result<Win32Kernel<TK, VK>> {
let mut kernel_scanner = Win32KernelInfo::scanner(self.connector.forward_mut());
if let Some(arch) = self.arch {
kernel_scanner = kernel_scanner.arch(arch);
}
if let Some(kernel_hint) = self.kernel_hint {
kernel_scanner = kernel_scanner.kernel_hint(kernel_hint);
}
if let Some(dtb) = self.dtb {
kernel_scanner = kernel_scanner.dtb(dtb);
}
let kernel_info = kernel_scanner.scan()?;
let offsets = self.build_offsets(&kernel_info)?;
let vat = DirectTranslate::new();
let kernel_connector = (self.build_page_cache)(self.connector, kernel_info.os_info.arch);
let kernel_vat = (self.build_vat_cache)(vat, kernel_info.os_info.arch);
Ok(Win32Kernel::new(
kernel_connector,
kernel_vat,
offsets,
kernel_info,
))
}
#[cfg(feature = "symstore")]
fn build_offsets(&self, kernel_info: &Win32KernelInfo) -> Result<Win32Offsets> {
let mut builder = offset_builder_with_kernel_info(kernel_info);
if let Some(store) = &self.symbol_store {
builder = builder.symbol_store(store.clone());
} else {
builder = builder.no_symbol_store();
}
builder.build()
}
#[cfg(not(feature = "symstore"))]
fn build_offsets(&self, kernel_info: &Win32KernelInfo) -> Result<Win32Offsets> {
offset_builder_with_kernel_info(&kernel_info).build()
}
pub fn arch(mut self, arch: ArchitectureIdent) -> Self {
self.arch = Some(arch);
self
}
pub fn kernel_hint(mut self, kernel_hint: Address) -> Self {
self.kernel_hint = Some(kernel_hint);
self
}
pub fn dtb(mut self, dtb: Address) -> Self {
self.dtb = Some(dtb);
self
}
#[cfg(feature = "symstore")]
pub fn symbol_store(mut self, symbol_store: SymbolStore) -> Self {
self.symbol_store = Some(symbol_store);
self
}
#[cfg(feature = "symstore")]
pub fn no_symbol_store(mut self) -> Self {
self.symbol_store = None;
self
}
pub fn build_default_caches(
self,
) -> Win32KernelBuilder<
T,
CachedPhysicalMemory<'a, T, DefaultCacheValidator>,
CachedVirtualTranslate<DirectTranslate, DefaultCacheValidator>,
> {
Win32KernelBuilder {
connector: self.connector,
arch: self.arch,
kernel_hint: self.kernel_hint,
dtb: self.dtb,
#[cfg(feature = "symstore")]
symbol_store: self.symbol_store,
build_page_cache: Box::new(|connector, arch| {
CachedPhysicalMemory::builder(connector)
.arch(arch)
.build()
.unwrap()
}),
build_vat_cache: Box::new(|vat, arch| {
CachedVirtualTranslate::builder(vat)
.arch(arch)
.build()
.unwrap()
}),
}
}
pub fn build_page_cache<TKN, F: FnOnce(T, ArchitectureIdent) -> TKN + 'static>(
self,
func: F,
) -> Win32KernelBuilder<T, TKN, VK>
where
TKN: PhysicalMemory,
{
Win32KernelBuilder {
connector: self.connector,
arch: self.arch,
kernel_hint: self.kernel_hint,
dtb: self.dtb,
#[cfg(feature = "symstore")]
symbol_store: self.symbol_store,
build_page_cache: Box::new(func),
build_vat_cache: self.build_vat_cache,
}
}
pub fn build_vat_cache<VKN, F: FnOnce(DirectTranslate, ArchitectureIdent) -> VKN + 'static>(
self,
func: F,
) -> Win32KernelBuilder<T, TK, VKN>
where
VKN: VirtualTranslate2,
{
Win32KernelBuilder {
connector: self.connector,
arch: self.arch,
kernel_hint: self.kernel_hint,
dtb: self.dtb,
#[cfg(feature = "symstore")]
symbol_store: self.symbol_store,
build_page_cache: self.build_page_cache,
build_vat_cache: Box::new(func),
}
}
}