use vmi::{
VmiContext,
arch::amd64::Amd64,
driver::VmiRead,
os::windows::WindowsOs,
trace::Hex,
utils::{
bridge::{BridgeHandler, BridgePacket, BridgeResponse},
shellcode::{EncodedStatus, Status, impl_bridge_contract, impl_stage},
},
};
#[derive(Clone, Copy, PartialEq, Eq)]
pub struct KernelFileStage(u8);
impl_stage!(KernelFileStage);
impl KernelFileStage {
pub const NONE: Self = Self(0x00);
pub const CREATE: Self = Self(0x01);
pub const WRITE: Self = Self(0x02);
}
impl std::fmt::Debug for KernelFileStage {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
let name = match *self {
Self::NONE => "None",
Self::CREATE => "Create",
Self::WRITE => "Write",
_ => return self.0.fmt(f),
};
f.write_str(name)
}
}
pub type KernelFileStatus = Status<KernelFileStage>;
#[derive(Debug, Default)]
pub struct KernelFileBridge;
impl_bridge_contract!(KernelFileBridge);
impl KernelFileBridge {
const METHOD_EXIT: u16 = 0xffff;
fn handle_packet(&self, packet: BridgePacket) -> Option<BridgeResponse<EncodedStatus>> {
match packet.method() {
Self::METHOD_EXIT => self.handle_exit(packet),
_ => self.handle_unknown(packet),
}
}
fn handle_exit(&self, packet: BridgePacket) -> Option<BridgeResponse<EncodedStatus>> {
let status = KernelFileStatus::decode(packet.value1());
tracing::debug!(
?status,
native_code = %Hex(status.native_code()),
"shellcode completed"
);
Some(BridgeResponse::default().with_output(packet.value1()))
}
fn handle_unknown(&self, packet: BridgePacket) -> Option<BridgeResponse<EncodedStatus>> {
tracing::warn!(
request = %Hex(packet.request()),
method = %Hex(packet.method()),
value1 = %Hex(packet.value1()),
value2 = %Hex(packet.value2()),
value3 = %Hex(packet.value3()),
value4 = %Hex(packet.value4()),
"unknown bridge method"
);
None
}
}
impl<Driver> BridgeHandler<WindowsOs<Driver>> for KernelFileBridge
where
Driver: VmiRead<Architecture = Amd64>,
{
type Output = EncodedStatus;
const REQUEST: u16 = 0x0002;
#[tracing::instrument(name = "kernel_file", skip_all)]
fn handle(
&mut self,
_vmi: &VmiContext<'_, WindowsOs<Driver>>,
packet: BridgePacket,
) -> Option<BridgeResponse<EncodedStatus>> {
debug_assert_eq!(
packet.request(),
<Self as BridgeHandler<WindowsOs<Driver>>>::REQUEST
);
self.handle_packet(packet)
}
}