use vmi::{
VmiContext,
arch::amd64::Amd64,
driver::VmiRead,
os::windows::WindowsOs,
trace::Hex,
utils::{
bridge::{BridgeHandler, BridgePacket, BridgeResponse},
shellcode::impl_bridge_contract,
},
};
#[derive(Debug, Default)]
pub struct MsgboxBridge;
impl_bridge_contract!(MsgboxBridge);
impl MsgboxBridge {
const METHOD_EXIT: u16 = 0xffff;
fn handle_packet(&self, packet: BridgePacket) -> Option<BridgeResponse<u64>> {
match packet.method() {
Self::METHOD_EXIT => self.handle_exit(packet),
_ => self.handle_unknown(packet),
}
}
fn handle_exit(&self, packet: BridgePacket) -> Option<BridgeResponse<u64>> {
let result = packet.value1();
tracing::debug!(result, "shellcode completed");
Some(BridgeResponse::default().with_output(packet.value1()))
}
fn handle_unknown(&self, packet: BridgePacket) -> Option<BridgeResponse<u64>> {
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 MsgboxBridge
where
Driver: VmiRead<Architecture = Amd64>,
{
type Output = u64;
const REQUEST: u16 = 0x0001;
#[tracing::instrument(name = "msgbox", skip_all)]
fn handle(
&mut self,
_vmi: &VmiContext<'_, WindowsOs<Driver>>,
packet: BridgePacket,
) -> Option<BridgeResponse<u64>> {
debug_assert_eq!(
packet.request(),
<Self as BridgeHandler<WindowsOs<Driver>>>::REQUEST
);
self.handle_packet(packet)
}
}