windows_bridge/file_transfer/
mod.rs1mod bridge;
2mod recipe;
3
4use vmi::{
5 Va, VmiContext, VmiError,
6 arch::amd64::{Amd64, Registers},
7 driver::VmiFullDriver,
8 os::windows::WindowsOs,
9 utils::{injector::RecipeExecutor, shellcode::KernelRecipeData},
10};
11
12#[expect(unused_imports)]
13pub use self::bridge::{FileTransferBridge, FileTransferStatus};
14use self::recipe::file_transfer_recipe;
15
16#[expect(
18 clippy::large_enum_variant,
19 reason = "only a handful of transfers exist at a time, so boxing the recipe \
20 executor would add an allocation without improving readability"
21)]
22enum FileTransferState<Driver>
23where
24 Driver: VmiFullDriver<Architecture = Amd64>,
25{
26 Pending,
28
29 Executing(RecipeExecutor<WindowsOs<Driver>, KernelRecipeData<WindowsOs<Driver>>>),
31}
32
33pub struct FileTransfer<Driver>
35where
36 Driver: VmiFullDriver<Architecture = Amd64>,
37{
38 handle: u64,
40
41 file_object: Va,
43
44 path: String,
46
47 state: FileTransferState<Driver>,
49}
50
51impl<Driver> FileTransfer<Driver>
52where
53 Driver: VmiFullDriver<Architecture = Amd64>,
54{
55 pub fn new(handle: u64, file_object: Va, path: String) -> Self {
57 Self {
58 handle,
59 file_object,
60 path,
61 state: FileTransferState::Pending,
62 }
63 }
64
65 pub fn handle(&self) -> u64 {
67 self.handle
68 }
69
70 pub fn file_object(&self) -> Va {
72 self.file_object
73 }
74
75 pub fn path(&self) -> &str {
77 &self.path
78 }
79
80 pub fn start(&mut self) {
82 assert!(
83 matches!(self.state, FileTransferState::Pending),
84 "file transfer started more than once"
85 );
86
87 self.state =
88 FileTransferState::Executing(RecipeExecutor::new(file_transfer_recipe(self.handle)));
89 }
90
91 pub fn execute(
93 &mut self,
94 vmi: &VmiContext<'_, WindowsOs<Driver>>,
95 ) -> Result<Option<Registers>, VmiError> {
96 let executor = match &mut self.state {
97 FileTransferState::Executing(executor) => executor,
98 FileTransferState::Pending => panic!("pending file transfer cannot execute"),
99 };
100
101 executor.execute(vmi)
102 }
103
104 pub fn done(&self) -> bool {
106 match &self.state {
107 FileTransferState::Pending => false,
108 FileTransferState::Executing(executor) => executor.done(),
109 }
110 }
111}