Skip to content

Commit

Permalink
feat(utils): add bridge module and integrate with injector
Browse files Browse the repository at this point in the history
  • Loading branch information
wbenny committed Dec 13, 2024
1 parent 03997eb commit 21a12eb
Show file tree
Hide file tree
Showing 8 changed files with 476 additions and 55 deletions.
2 changes: 2 additions & 0 deletions crates/vmi-utils/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ default = [
"arch-amd64",
"os-windows",
"bpm",
"bridge",
"injector",
"interceptor",
"ptm"
Expand All @@ -49,6 +50,7 @@ os-windows = [
]

bpm = []
bridge = []
injector = []
interceptor = []
ptm = []
174 changes: 174 additions & 0 deletions crates/vmi-utils/src/bridge/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,174 @@
//! Bridge utilities.
mod packet;
mod response;

use vmi_core::{VmiContext, VmiDriver, VmiOs};

pub use self::{packet::BridgePacket, response::BridgeResponse};

/// A bridge dispatcher.
pub trait BridgeDispatch<Driver, Os, T = ()>
where
Driver: VmiDriver,
Os: VmiOs<Driver>,
{
/// Dispatch the request.
fn dispatch(
&mut self,
vmi: &VmiContext<'_, Driver, Os>,
packet: BridgePacket,
) -> Option<BridgeResponse<T>>;
}

/// A bridge handler.
pub trait BridgeHandler<Driver, Os, T = ()>: BridgeDispatch<Driver, Os, T>
where
Driver: VmiDriver,
Os: VmiOs<Driver>,
{
/// Marker for an empty handler.
///
/// Set to `true` in the implementation for the `()` type.
const EMPTY: bool = false;

/// The magic number.
const MAGIC: u32;

/// The request code.
const REQUEST: u16;

/// The first verification value.
///
/// # Architecture-specific
///
/// - **AMD64**: `RAX`
const VERIFY_VALUE1: Option<u64> = None;

/// The second verification value.
///
/// # Architecture-specific
///
/// - **AMD64**: `RBX`
const VERIFY_VALUE2: Option<u64> = None;

/// The third verification value.
///
/// # Architecture-specific
///
/// - **AMD64**: `RCX`
const VERIFY_VALUE3: Option<u64> = None;

/// The fourth verification value.
///
/// # Architecture-specific
///
/// - **AMD64**: `RDX`
const VERIFY_VALUE4: Option<u64> = None;
}

macro_rules! impl_bridge_dispatch {
($($ty:ident),*) => {
#[allow(non_snake_case)]
impl<Driver, Os, T, $($ty),*> BridgeDispatch<Driver, Os, T> for ($($ty),*,)
where
Driver: VmiDriver,
Os: VmiOs<Driver>,
$($ty: BridgeHandler<Driver, Os, T>),*
{
fn dispatch(&mut self, vmi: &VmiContext<'_, Driver, Os>, packet: BridgePacket) -> Option<BridgeResponse<T>> {
let ($($ty),*,) = self;

$(
if packet.request() == <$ty as BridgeHandler<Driver, Os, T>>::REQUEST {
return $ty.dispatch(vmi, packet);
}
)*

None
}
}
};
}

impl<Driver, Os, T> BridgeDispatch<Driver, Os, T> for ()
where
Driver: VmiDriver,
Os: VmiOs<Driver>,
{
fn dispatch(
&mut self,
_vmi: &VmiContext<'_, Driver, Os>,
_packet: BridgePacket,
) -> Option<BridgeResponse<T>> {
None
}
}

impl<Driver, Os, T> BridgeHandler<Driver, Os, T> for ()
where
Driver: VmiDriver,
Os: VmiOs<Driver>,
{
const EMPTY: bool = true;
const MAGIC: u32 = 0;
const REQUEST: u16 = 0;
}

impl_bridge_dispatch!(B1);
impl_bridge_dispatch!(B1, B2);
impl_bridge_dispatch!(B1, B2, B3);
impl_bridge_dispatch!(B1, B2, B3, B4);
impl_bridge_dispatch!(B1, B2, B3, B4, B5);
impl_bridge_dispatch!(B1, B2, B3, B4, B5, B6);
impl_bridge_dispatch!(B1, B2, B3, B4, B5, B6, B7);
impl_bridge_dispatch!(B1, B2, B3, B4, B5, B6, B7, B8);
impl_bridge_dispatch!(B1, B2, B3, B4, B5, B6, B7, B8, B9);
impl_bridge_dispatch!(B1, B2, B3, B4, B5, B6, B7, B8, B9, B10);
impl_bridge_dispatch!(B1, B2, B3, B4, B5, B6, B7, B8, B9, B10, B11);
impl_bridge_dispatch!(B1, B2, B3, B4, B5, B6, B7, B8, B9, B10, B11, B12);
impl_bridge_dispatch!(B1, B2, B3, B4, B5, B6, B7, B8, B9, B10, B11, B12, B13);
impl_bridge_dispatch!(B1, B2, B3, B4, B5, B6, B7, B8, B9, B10, B11, B12, B13, B14);
impl_bridge_dispatch!(B1, B2, B3, B4, B5, B6, B7, B8, B9, B10, B11, B12, B13, B14, B15);
impl_bridge_dispatch!(B1, B2, B3, B4, B5, B6, B7, B8, B9, B10, B11, B12, B13, B14, B15, B16);

/// A bridge.
pub struct Bridge<Driver, Os, B, T = ()>
where
Driver: VmiDriver,
Os: VmiOs<Driver>,
B: BridgeDispatch<Driver, Os, T>,
{
handlers: B,
_phantom: std::marker::PhantomData<(Driver, Os, T)>,
}

impl<Driver, Os, B, T> Bridge<Driver, Os, B, T>
where
Driver: VmiDriver,
Os: VmiOs<Driver>,
B: BridgeDispatch<Driver, Os, T>,
{
/// Create a new bridge.
pub fn new(handlers: B) -> Self {
Self {
handlers,
_phantom: std::marker::PhantomData,
}
}
}

impl<Driver, Os, B, T> BridgeDispatch<Driver, Os, T> for Bridge<Driver, Os, B, T>
where
Driver: VmiDriver,
Os: VmiOs<Driver>,
B: BridgeDispatch<Driver, Os, T>,
{
fn dispatch(
&mut self,
vmi: &VmiContext<'_, Driver, Os>,
packet: BridgePacket,
) -> Option<BridgeResponse<T>> {
self.handlers.dispatch(vmi, packet)
}
}
81 changes: 81 additions & 0 deletions crates/vmi-utils/src/bridge/packet.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
/// Bridge packet.
#[derive(Debug, Default)]
pub struct BridgePacket {
magic: u32,
request: u16,
method: u16,
value1: u64,
value2: u64,
value3: u64,
value4: u64,
}

impl BridgePacket {
/// Create a new packet with the given request and method.
pub fn new(magic: u32, request: u16, method: u16) -> Self {
Self {
magic,
request,
method,
value1: 0,
value2: 0,
value3: 0,
value4: 0,
}
}

/// Set the first value of the packet.
pub fn with_value1(self, value1: u64) -> Self {
Self { value1, ..self }
}

/// Set the second value of the packet.
pub fn with_value2(self, value2: u64) -> Self {
Self { value2, ..self }
}

/// Set the third value of the packet.
pub fn with_value3(self, value3: u64) -> Self {
Self { value3, ..self }
}

/// Set the fourth value of the packet.
pub fn with_value4(self, value4: u64) -> Self {
Self { value4, ..self }
}

/// Get the magic number of the packet.
pub fn magic(&self) -> u32 {
self.magic
}

/// Get the request of the packet.
pub fn request(&self) -> u16 {
self.request
}

/// Get the method of the packet.
pub fn method(&self) -> u16 {
self.method
}

/// Get the first value of the packet.
pub fn value1(&self) -> u64 {
self.value1
}

/// Get the second value of the packet.
pub fn value2(&self) -> u64 {
self.value2
}

/// Get the third value of the packet.
pub fn value3(&self) -> u64 {
self.value3
}

/// Get the fourth value of the packet.
pub fn value4(&self) -> u64 {
self.value4
}
}
104 changes: 104 additions & 0 deletions crates/vmi-utils/src/bridge/response.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
/// A response from the bridge.
#[derive(Debug)]
pub struct BridgeResponse<T = ()> {
value1: Option<u64>,
value2: Option<u64>,
value3: Option<u64>,
value4: Option<u64>,
result: Option<T>,
}

impl<T> Default for BridgeResponse<T> {
fn default() -> Self {
Self {
value1: None,
value2: None,
value3: None,
value4: None,
result: None,
}
}
}

impl<T> BridgeResponse<T> {
/// Create a new response with the given value.
pub fn new(value1: u64) -> Self {
Self {
value1: Some(value1),
value2: None,
value3: None,
value4: None,
result: None,
}
}

/// Get the first value of the response.
pub fn value1(&self) -> Option<u64> {
self.value1
}

/// Get the second value of the response.
pub fn value2(&self) -> Option<u64> {
self.value2
}

/// Get the third value of the response.
pub fn value3(&self) -> Option<u64> {
self.value3
}

/// Get the fourth value of the response.
pub fn value4(&self) -> Option<u64> {
self.value4
}

/// Get the result of the response.
pub fn result(&self) -> Option<&T> {
self.result.as_ref()
}

/// Convert the response into a result.
pub fn into_result(self) -> Option<T> {
self.result
}

/// Set the first value of the response.
pub fn with_value1(self, value1: u64) -> Self {
Self {
value1: Some(value1),
..self
}
}

/// Set the second value of the response.
pub fn with_value2(self, value2: u64) -> Self {
Self {
value2: Some(value2),
..self
}
}

/// Set the third value of the response.
pub fn with_value3(self, value3: u64) -> Self {
Self {
value3: Some(value3),
..self
}
}

/// Set the fourth value of the response.
pub fn with_value4(self, value4: u64) -> Self {
Self {
value4: Some(value4),
..self
}
}

/// Set the result of the response.
pub fn with_result(self, result: T) -> Self {
Self {
result: Some(result),
..self
}
}
}
Loading

0 comments on commit 21a12eb

Please sign in to comment.