wraith/km_client/
ioctl.rs

1//! IOCTL definitions shared between kernel and usermode
2
3/// IOCTL code structure
4#[derive(Debug, Clone, Copy)]
5pub struct IoctlCode(pub u32);
6
7impl IoctlCode {
8    /// create IOCTL code from components
9    pub const fn new(device_type: u32, function: u32, method: u32, access: u32) -> Self {
10        Self((device_type << 16) | (access << 14) | (function << 2) | method)
11    }
12
13    /// create for custom device type
14    pub const fn custom(function: u32, method: u32, access: u32) -> Self {
15        Self::new(0x8000, function, method, access)
16    }
17
18    /// create buffered IOCTL
19    pub const fn buffered(function: u32, access: u32) -> Self {
20        Self::custom(function, 0, access) // METHOD_BUFFERED = 0
21    }
22
23    /// get raw code
24    pub const fn code(&self) -> u32 {
25        self.0
26    }
27}
28
29/// IOCTL access modes
30pub mod access {
31    pub const ANY: u32 = 0;
32    pub const READ: u32 = 1;
33    pub const WRITE: u32 = 2;
34    pub const READ_WRITE: u32 = 3;
35}
36
37/// predefined IOCTL codes (must match kernel module)
38pub mod codes {
39    use super::IoctlCode;
40    use super::access;
41
42    pub const READ_MEMORY: IoctlCode = IoctlCode::buffered(0x800, access::READ_WRITE);
43    pub const WRITE_MEMORY: IoctlCode = IoctlCode::buffered(0x801, access::READ_WRITE);
44    pub const GET_MODULE_BASE: IoctlCode = IoctlCode::buffered(0x802, access::READ);
45    pub const ALLOCATE_MEMORY: IoctlCode = IoctlCode::buffered(0x803, access::READ_WRITE);
46    pub const FREE_MEMORY: IoctlCode = IoctlCode::buffered(0x804, access::READ_WRITE);
47    pub const PROTECT_MEMORY: IoctlCode = IoctlCode::buffered(0x805, access::READ_WRITE);
48    pub const QUERY_PROCESS: IoctlCode = IoctlCode::buffered(0x806, access::READ);
49    pub const COPY_PHYSICAL: IoctlCode = IoctlCode::buffered(0x807, access::READ_WRITE);
50    pub const MAP_PHYSICAL: IoctlCode = IoctlCode::buffered(0x808, access::READ_WRITE);
51    pub const UNMAP_PHYSICAL: IoctlCode = IoctlCode::buffered(0x809, access::READ_WRITE);
52}
53
54/// read memory request structure
55#[repr(C)]
56#[derive(Debug, Clone, Copy)]
57pub struct ReadMemoryRequest {
58    pub process_id: u32,
59    pub address: u64,
60    pub size: u32,
61}
62
63/// write memory request structure
64#[repr(C)]
65#[derive(Debug, Clone, Copy)]
66pub struct WriteMemoryRequest {
67    pub process_id: u32,
68    pub address: u64,
69    pub size: u32,
70    // data follows in buffer
71}
72
73/// get module base request
74#[repr(C)]
75#[derive(Debug, Clone, Copy)]
76pub struct GetModuleBaseRequest {
77    pub process_id: u32,
78    pub module_name_offset: u32,
79    pub module_name_length: u32,
80}
81
82/// get module base response
83#[repr(C)]
84#[derive(Debug, Clone, Copy)]
85pub struct GetModuleBaseResponse {
86    pub base_address: u64,
87    pub size: u64,
88}
89
90/// allocate memory request
91#[repr(C)]
92#[derive(Debug, Clone, Copy)]
93pub struct AllocateMemoryRequest {
94    pub process_id: u32,
95    pub size: u64,
96    pub protection: u32,
97    pub preferred_address: u64,
98}
99
100/// allocate memory response
101#[repr(C)]
102#[derive(Debug, Clone, Copy)]
103pub struct AllocateMemoryResponse {
104    pub allocated_address: u64,
105    pub actual_size: u64,
106}
107
108/// free memory request
109#[repr(C)]
110#[derive(Debug, Clone, Copy)]
111pub struct FreeMemoryRequest {
112    pub process_id: u32,
113    pub address: u64,
114}
115
116/// protect memory request
117#[repr(C)]
118#[derive(Debug, Clone, Copy)]
119pub struct ProtectMemoryRequest {
120    pub process_id: u32,
121    pub address: u64,
122    pub size: u64,
123    pub new_protection: u32,
124}
125
126/// protect memory response
127#[repr(C)]
128#[derive(Debug, Clone, Copy)]
129pub struct ProtectMemoryResponse {
130    pub old_protection: u32,
131}
132
133/// copy physical memory request
134#[repr(C)]
135#[derive(Debug, Clone, Copy)]
136pub struct CopyPhysicalRequest {
137    pub physical_address: u64,
138    pub size: u32,
139    pub write: u8,
140}
141
142/// map physical memory request
143#[repr(C)]
144#[derive(Debug, Clone, Copy)]
145pub struct MapPhysicalRequest {
146    pub physical_address: u64,
147    pub size: u64,
148}
149
150/// map physical memory response
151#[repr(C)]
152#[derive(Debug, Clone, Copy)]
153pub struct MapPhysicalResponse {
154    pub mapped_address: u64,
155}
156
157/// query process info request
158#[repr(C)]
159#[derive(Debug, Clone, Copy)]
160pub struct QueryProcessRequest {
161    pub process_id: u32,
162}
163
164/// query process info response
165#[repr(C)]
166#[derive(Debug, Clone, Copy)]
167pub struct QueryProcessResponse {
168    pub base_address: u64,
169    pub peb_address: u64,
170    pub cr3: u64,
171    pub is_wow64: u8,
172}
173
174/// generic IOCTL request wrapper
175pub struct IoctlRequest<T> {
176    pub code: IoctlCode,
177    pub data: T,
178}
179
180impl<T> IoctlRequest<T> {
181    pub fn new(code: IoctlCode, data: T) -> Self {
182        Self { code, data }
183    }
184}
185
186/// generic IOCTL response wrapper
187pub struct IoctlResponse<T> {
188    pub bytes_returned: u32,
189    pub data: T,
190}