pub struct WindowsProcess<'a, Driver>{ /* private fields */ }os-windows only.Expand description
A Windows process.
A process in Windows is represented by the _EPROCESS structure,
which contains metadata about its execution state, memory layout,
and handles.
§Implementation Details
Corresponds to _EPROCESS.
Implementations§
Source§impl<'a, Driver> WindowsProcess<'a, Driver>
impl<'a, Driver> WindowsProcess<'a, Driver>
Sourcepub fn new(
vmi: VmiState<'a, WindowsOs<Driver>>,
process: ProcessObject,
) -> WindowsProcess<'a, Driver>
pub fn new( vmi: VmiState<'a, WindowsOs<Driver>>, process: ProcessObject, ) -> WindowsProcess<'a, Driver>
Creates a new Windows process.
Sourcepub fn create_time(&self) -> Result<u64, VmiError>
pub fn create_time(&self) -> Result<u64, VmiError>
Returns the creation time of the process.
§Implementation Details
Corresponds to _EPROCESS.CreateTime.
Sourcepub fn is_wow64(&self) -> Result<bool, VmiError>
pub fn is_wow64(&self) -> Result<bool, VmiError>
Checks if the process is a WoW64 process.
§Implementation Details
Corresponds to _EPROCESS.WoW64Process != NULL.
Sourcepub fn peb(&self) -> Result<Option<WindowsPeb<'a, Driver>>, VmiError>
pub fn peb(&self) -> Result<Option<WindowsPeb<'a, Driver>>, VmiError>
Returns the process environment block (PEB).
§Implementation Details
The function first reads the _EPROCESS.WoW64Process field to determine
if the process is a 32-bit process. If the field is NULL, the process
is 64-bit. Otherwise, the function reads the _EWOW64PROCESS.Peb field
to get the 32-bit PEB.
Examples found in repository?
320fn print_process_parameters(process: &WindowsProcess<Driver>) -> Result<(), VmiError> {
321 let peb = match process.peb() {
322 Ok(Some(peb)) => peb,
323 Ok(None) => {
324 println!(" (No PEB)");
325 return Ok(());
326 }
327 Err(err) => {
328 println!("Failed to get PEB: {}", handle_error(err)?);
329 return Ok(());
330 }
331 };
332
333 let current_directory = match peb.current_directory() {
334 Ok(current_directory) => current_directory,
335 Err(err) => handle_error(err)?,
336 };
337
338 let dll_path = match peb.dll_path() {
339 Ok(dll_path) => dll_path,
340 Err(err) => handle_error(err)?,
341 };
342
343 let image_path_name = match peb.image_path_name() {
344 Ok(image_path_name) => image_path_name,
345 Err(err) => handle_error(err)?,
346 };
347
348 let command_line = match peb.command_line() {
349 Ok(command_line) => command_line,
350 Err(err) => handle_error(err)?,
351 };
352
353 println!(" Current Directory: {current_directory}");
354 println!(" DLL Path: {dll_path}");
355 println!(" Image Path Name: {image_path_name}");
356 println!(" Command Line: {command_line}");
357
358 Ok(())
359}More examples
412 fn PspInsertProcess(&mut self, vmi: &VmiContext<WindowsOs<Driver>>) -> Result<(), VmiError> {
413 //
414 // NTSTATUS
415 // PspInsertProcess (
416 // _In_ PEPROCESS NewProcess,
417 // _In_ PEPROCESS Parent,
418 // _In_ ULONG DesiredAccess,
419 // _In_ ULONG CreateFlags,
420 // ...
421 // );
422 //
423
424 let NewProcess = vmi.os().function_argument(0)?;
425 let Parent = vmi.os().function_argument(1)?;
426
427 let process = vmi.os().process(ProcessObject(Va(NewProcess)))?;
428 let process_id = process.id()?;
429
430 let parent_process = vmi.os().process(ProcessObject(Va(Parent)))?;
431 let parent_process_id = parent_process.id()?;
432
433 // We rely heavily on the 2nd argument to be the parent process object.
434 // If that ever changes, this assertion should catch it.
435 //
436 // So far it is verified that it works for Windows 7 up to Windows 11
437 // (23H2, build 22631).
438 debug_assert_eq!(parent_process_id, process.parent_id()?);
439
440 let name = process.name()?;
441 let image_base = process.image_base()?;
442 let peb = process.peb()?;
443
444 tracing::info!(
445 %process_id,
446 name,
447 %image_base,
448 ?peb,
449 );
450
451 Ok(())
452 }Sourcepub fn native_peb(&self) -> Result<Option<WindowsPeb<'a, Driver>>, VmiError>
pub fn native_peb(&self) -> Result<Option<WindowsPeb<'a, Driver>>, VmiError>
Returns the native process environment block (PEB).
§Implementation Details
Corresponds to _EPROCESS.Peb.
Sourcepub fn session(&self) -> Result<Option<WindowsSession<'a, Driver>>, VmiError>
pub fn session(&self) -> Result<Option<WindowsSession<'a, Driver>>, VmiError>
Returns the session of the process.
Examples found in repository?
More examples
362fn enumerate_processes(vmi: &VmiState<WindowsOs<Driver>>) -> Result<(), VmiError> {
363 for process in vmi.os().processes()? {
364 let process = process?;
365
366 let pid = process.id()?; // `_EPROCESS.UniqueProcessId`
367 let object = process.object()?; // `_EPROCESS` pointer
368 let name = process.name()?; // `_EPROCESS.ImageFileName`
369 let session = process.session()?; // `_EPROCESS.Session`
370
371 println!("Process @ {object}, PID: {pid}");
372 println!(" Name: {name}");
373 if let Some(session) = session {
374 println!(" Session: {}", session.id()?); // `_MM_SESSION_SPACE.SessionId`
375 }
376
377 println!(" Threads:");
378 enumerate_threads(&process)?;
379
380 println!(" Regions:");
381 enumerate_regions(&process)?;
382
383 println!(" PEB:");
384 print_process_parameters(&process)?;
385
386 println!(" Handles:");
387 enumerate_handle_table(&process)?;
388 }
389
390 Ok(())
391}Sourcepub fn token(&self) -> Result<WindowsToken<'a, Driver>, VmiError>
pub fn token(&self) -> Result<WindowsToken<'a, Driver>, VmiError>
Returns the primary access token of the process.
§Implementation Details
Corresponds to _EPROCESS.Token (with reference count masked out).
Sourcepub fn handle_table(
&self,
) -> Result<Option<WindowsHandleTable<'a, Driver>>, VmiError>
pub fn handle_table( &self, ) -> Result<Option<WindowsHandleTable<'a, Driver>>, VmiError>
Returns the handle table of the process.
§Implementation Details
Corresponds to _EPROCESS.ObjectTable.
Examples found in repository?
176fn enumerate_handle_table(process: &WindowsProcess<Driver>) -> Result<(), VmiError> {
177 const OBJ_PROTECT_CLOSE: u32 = 0x00000001;
178 const OBJ_INHERIT: u32 = 0x00000002;
179 const OBJ_AUDIT_OBJECT_CLOSE: u32 = 0x00000004;
180
181 static LABEL_PROTECTED: [&str; 2] = ["", " (Protected)"];
182 static LABEL_INHERIT: [&str; 2] = ["", " (Inherit)"];
183 static LABEL_AUDIT: [&str; 2] = ["", " (Audit)"];
184
185 // Get the handle table from `_EPROCESS.ObjectTable`.
186 let handle_table = match process.handle_table() {
187 Ok(Some(handle_table)) => handle_table,
188 Ok(None) => {
189 println!(" (No handle table)");
190 return Ok(());
191 }
192 Err(err) => {
193 tracing::error!(%err, "Failed to get handle table");
194 return Ok(());
195 }
196 };
197
198 // Iterate over `_HANDLE_TABLE_ENTRY` items.
199 for handle_entry in handle_table.iter()? {
200 let (handle, entry) = match handle_entry {
201 Ok(entry) => entry,
202 Err(err) => {
203 println!("Failed to get handle entry: {}", handle_error(err)?);
204 continue;
205 }
206 };
207
208 let attributes = match entry.attributes() {
209 Ok(attributes) => attributes,
210 Err(err) => {
211 println!("Failed to get attributes: {}", handle_error(err)?);
212 continue;
213 }
214 };
215
216 let granted_access = match entry.granted_access() {
217 Ok(granted_access) => granted_access,
218 Err(err) => {
219 println!("Failed to get granted access: {}", handle_error(err)?);
220 continue;
221 }
222 };
223
224 let object = match entry.object() {
225 Ok(Some(object)) => object,
226 Ok(None) => {
227 // [`WindowsHandleTable::iter`] should only return entries with
228 // valid objects, so this should not happen.
229 println!("<NULL>");
230 continue;
231 }
232 Err(err) => {
233 println!("Failed to get object: {}", handle_error(err)?);
234 continue;
235 }
236 };
237
238 let type_name = match object.type_name() {
239 Ok(type_name) => type_name,
240 Err(err) => handle_error(err)?,
241 };
242
243 let full_path = match object.full_path() {
244 Ok(Some(path)) => path,
245 Ok(None) => String::from("<no-path>"),
246 Err(err) => handle_error(err)?,
247 };
248
249 println!(
250 " {:04x}: Object: {:x} GrantedAccess: {:08x}{}{}{} Entry: {}",
251 handle,
252 object.va().0,
253 granted_access,
254 LABEL_PROTECTED[((attributes & OBJ_PROTECT_CLOSE) != 0) as usize],
255 LABEL_INHERIT[((attributes & OBJ_INHERIT) != 0) as usize],
256 LABEL_AUDIT[((attributes & OBJ_AUDIT_OBJECT_CLOSE) != 0) as usize],
257 entry.va(),
258 );
259
260 println!(" Type: {type_name}, Path: {full_path}");
261 }
262
263 Ok(())
264}Sourcepub fn lookup_object<T>(&self, handle: u64) -> Result<Option<T>, VmiError>where
T: FromWindowsObject<'a, Driver>,
pub fn lookup_object<T>(&self, handle: u64) -> Result<Option<T>, VmiError>where
T: FromWindowsObject<'a, Driver>,
Looks up the object associated with the given handle and attempts to convert it to the specified type.
Resolves a handle value through the process handle table
and converts the resulting WindowsObject using the
FromWindowsObject trait.
Returns Ok(None) if the handle table is unavailable,
the handle is invalid, the entry has no associated object,
or the object is not of the requested type.
§Examples
// Look up the raw object.
let object = process.lookup_object::<WindowsObject<_>>(handle)?;
// Look up and convert to a specific type.
let process = current_process.lookup_object::<WindowsProcess<_>>(handle)?;
let file = current_process.lookup_object::<WindowsFileObject<_>>(handle)?;Examples found in repository?
375 fn NtWriteFile(&mut self, vmi: &VmiContext<WindowsOs<Driver>>) -> Result<(), VmiError> {
376 //
377 // NTSTATUS
378 // NtWriteFile (
379 // _In_ HANDLE FileHandle,
380 // _In_opt_ HANDLE Event,
381 // _In_opt_ PIO_APC_ROUTINE ApcRoutine,
382 // _In_opt_ PVOID ApcContext,
383 // _Out_ PIO_STATUS_BLOCK IoStatusBlock,
384 // _In_reads_bytes_(Length) PVOID Buffer,
385 // _In_ ULONG Length,
386 // _In_opt_ PLARGE_INTEGER ByteOffset,
387 // _In_opt_ PULONG Key
388 // );
389 //
390
391 let FileHandle = vmi.os().function_argument(0)?;
392
393 let file_object = match vmi
394 .os()
395 .current_process()?
396 .lookup_object::<WindowsFileObject<_>>(FileHandle)?
397 {
398 Some(file_object) => file_object,
399 None => {
400 tracing::warn!(FileHandle = %Hex(FileHandle), "No object found");
401 return Ok(());
402 }
403 };
404
405 let path = file_object.full_path()?;
406 tracing::info!(%path);
407
408 Ok(())
409 }More examples
11pub fn NtWriteFile<Driver>(
12 vmi: &VmiContext<WindowsOs<Driver>>,
13) -> Result<Action<<WindowsOs<Driver> as VmiOs>::Architecture>, VmiError>
14where
15 Driver: VmiRead,
16 Driver::Architecture: ArchAdapter<Driver>,
17{
18 //
19 // NTSTATUS
20 // NTAPI
21 // NtWriteFile(
22 // _In_ HANDLE FileHandle,
23 // _In_opt_ HANDLE Event,
24 // _In_opt_ PIO_APC_ROUTINE ApcRoutine,
25 // _In_opt_ PVOID ApcContext,
26 // _Out_ PIO_STATUS_BLOCK IoStatusBlock,
27 // _In_reads_bytes_(Length) PVOID Buffer,
28 // _In_ ULONG Length,
29 // _In_opt_ PLARGE_INTEGER ByteOffset,
30 // _In_opt_ PULONG Key
31 // );
32 //
33
34 let FileHandle = vmi.os().function_argument(0)?;
35
36 // Check if we have to look for the object in the kernel handle table
37 // or the current process handle table.
38 let owning_process = match vmi.os().is_kernel_handle(FileHandle)? {
39 true => vmi.os().system_process()?,
40 false => vmi.os().current_process()?,
41 };
42
43 let file_object = match owning_process.lookup_object::<WindowsFileObject<_>>(FileHandle)? {
44 Some(file_object) => file_object,
45 None => {
46 tracing::error!(handle = %Hex(FileHandle), "cannot find file object");
47 return Ok(Action::default());
48 }
49 };
50
51 let path = file_object.full_path()?;
52 tracing::info!(handle = %Hex(FileHandle), path);
53
54 Ok(Action::default())
55}Sourcepub fn vad_root(&self) -> Result<Option<WindowsRegion<'a, Driver>>, VmiError>
pub fn vad_root(&self) -> Result<Option<WindowsRegion<'a, Driver>>, VmiError>
Returns the root of the virtual address descriptor (VAD) tree.
§Implementation Details
Corresponds to _EPROCESS.VadRoot->BalancedRoot for Windows 7 and
_EPROCESS.VadRoot->Root for Windows 8.1 and later.
Sourcepub fn vad_hint(&self) -> Result<Option<WindowsRegion<'a, Driver>>, VmiError>
pub fn vad_hint(&self) -> Result<Option<WindowsRegion<'a, Driver>>, VmiError>
Returns the VAD hint node.
The VAD hint is an optimization used by Windows to speed up VAD lookups. This method returns the address of the hint node in the VAD tree.
§Implementation Details
Corresponds to _EPROCESS.VadRoot->NodeHint for Windows 7 and
_EPROCESS.VadRoot->Hint for Windows 8.1 and later.
Trait Implementations§
Source§impl<'a, Driver> From<WindowsProcess<'a, Driver>> for WindowsObject<'a, Driver>
impl<'a, Driver> From<WindowsProcess<'a, Driver>> for WindowsObject<'a, Driver>
Source§fn from(value: WindowsProcess<'a, Driver>) -> WindowsObject<'a, Driver>
fn from(value: WindowsProcess<'a, Driver>) -> WindowsObject<'a, Driver>
Source§impl<'a, Driver> FromWindowsObject<'a, Driver> for WindowsProcess<'a, Driver>
impl<'a, Driver> FromWindowsObject<'a, Driver> for WindowsProcess<'a, Driver>
Source§fn from_object(
object: WindowsObject<'a, Driver>,
) -> Result<Option<WindowsProcess<'a, Driver>>, VmiError>
fn from_object( object: WindowsObject<'a, Driver>, ) -> Result<Option<WindowsProcess<'a, Driver>>, VmiError>
WindowsObject into a specific object type.Source§impl<'a, Driver> VmiOsProcess<'a, Driver> for WindowsProcess<'a, Driver>
impl<'a, Driver> VmiOsProcess<'a, Driver> for WindowsProcess<'a, Driver>
Source§fn parent_id(&self) -> Result<ProcessId, VmiError>
fn parent_id(&self) -> Result<ProcessId, VmiError>
Returns the parent process ID.
§Implementation Details
Corresponds to _EPROCESS.InheritedFromUniqueProcessId.
Source§fn architecture(&self) -> Result<VmiOsImageArchitecture, VmiError>
fn architecture(&self) -> Result<VmiOsImageArchitecture, VmiError>
Returns the architecture of the process.
§Implementation Details
The function reads the _EPROCESS.WoW64Process field to determine if the
process is a 32-bit process. If the field is NULL, the process is 64-bit.
Otherwise, the process is 32-bit.
Source§fn translation_root(&self) -> Result<Pa, VmiError>
fn translation_root(&self) -> Result<Pa, VmiError>
Returns the process’s page table translation root.
§Implementation Details
Corresponds to _KPROCESS.DirectoryTableBase.
Source§fn user_translation_root(&self) -> Result<Pa, VmiError>
fn user_translation_root(&self) -> Result<Pa, VmiError>
Returns the user-mode page table translation root.
If KPTI is disabled, this function will return the same value as
translation_root.
§Implementation Details
Corresponds to _KPROCESS.UserDirectoryTableBase.
Source§fn image_base(&self) -> Result<Va, VmiError>
fn image_base(&self) -> Result<Va, VmiError>
Returns the base address of the process image.
§Implementation Details
Corresponds to _EPROCESS.SectionBaseAddress.
Source§fn regions(
&self,
) -> Result<impl Iterator<Item = Result<WindowsRegion<'a, Driver>, VmiError>> + use<'a, Driver>, VmiError>
fn regions( &self, ) -> Result<impl Iterator<Item = Result<WindowsRegion<'a, Driver>, VmiError>> + use<'a, Driver>, VmiError>
Returns an iterator over the process’s memory regions (VADs).
§Implementation Details
The function iterates over the VAD tree of the process.
Source§fn lookup_region(
&self,
address: Va,
) -> Result<Option<WindowsRegion<'a, Driver>>, VmiError>
fn lookup_region( &self, address: Va, ) -> Result<Option<WindowsRegion<'a, Driver>>, VmiError>
Returns the memory region (VAD) containing the given address.
Searches the VAD tree to find the VAD node that covers the given
virtual address within the process’s address space. Returns None
if no VAD covers the address.
§Implementation Details
The functionality is similar to the Windows kernel’s internal
MiLocateAddress() function.
Source§fn threads(
&self,
) -> Result<impl Iterator<Item = Result<<<WindowsProcess<'a, Driver> as VmiOsProcess<'a, Driver>>::Os as VmiOs>::Thread<'a>, VmiError>> + use<'a, Driver>, VmiError>
fn threads( &self, ) -> Result<impl Iterator<Item = Result<<<WindowsProcess<'a, Driver> as VmiOsProcess<'a, Driver>>::Os as VmiOs>::Thread<'a>, VmiError>> + use<'a, Driver>, VmiError>
Source§impl<Driver> VmiVa for WindowsProcess<'_, Driver>
impl<Driver> VmiVa for WindowsProcess<'_, Driver>
Auto Trait Implementations§
impl<'a, Driver> !RefUnwindSafe for WindowsProcess<'a, Driver>
impl<'a, Driver> !Send for WindowsProcess<'a, Driver>
impl<'a, Driver> !Sync for WindowsProcess<'a, Driver>
impl<'a, Driver> !UnwindSafe for WindowsProcess<'a, Driver>
impl<'a, Driver> Freeze for WindowsProcess<'a, Driver>
impl<'a, Driver> Unpin for WindowsProcess<'a, Driver>
impl<'a, Driver> UnsafeUnpin for WindowsProcess<'a, Driver>
Blanket Implementations§
Source§impl<T> ArchivePointee for T
impl<T> ArchivePointee for T
Source§type ArchivedMetadata = ()
type ArchivedMetadata = ()
Source§fn pointer_metadata(
_: &<T as ArchivePointee>::ArchivedMetadata,
) -> <T as Pointee>::Metadata
fn pointer_metadata( _: &<T as ArchivePointee>::ArchivedMetadata, ) -> <T as Pointee>::Metadata
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
Source§fn in_current_span(self) -> Instrumented<Self> ⓘ
fn in_current_span(self) -> Instrumented<Self> ⓘ
Source§impl<T> LayoutRaw for T
impl<T> LayoutRaw for T
Source§fn layout_raw(_: <T as Pointee>::Metadata) -> Result<Layout, LayoutError>
fn layout_raw(_: <T as Pointee>::Metadata) -> Result<Layout, LayoutError>
Source§impl<T, N1, N2> Niching<NichedOption<T, N1>> for N2
impl<T, N1, N2> Niching<NichedOption<T, N1>> for N2
Source§unsafe fn is_niched(niched: *const NichedOption<T, N1>) -> bool
unsafe fn is_niched(niched: *const NichedOption<T, N1>) -> bool
Source§fn resolve_niched(out: Place<NichedOption<T, N1>>)
fn resolve_niched(out: Place<NichedOption<T, N1>>)
out indicating that a T is niched.