1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300
//!
//! # memflow
//!
//! Machine introspection made easy
//!
//! ## Introduction
//!
//! memflow is a library that enables introspection of various machines (hardware, virtual machines,
//! memory dumps) in a generic fashion. There are 2 primary types of objects in memflow - _Connectors_
//! and _OS layers_. Connector provides raw access to physical memory of a machine. Meanwhile, OS
//! layer builds a higher level abstraction over running operating system, providing access to running
//! processes, input events, etc. These objects are incredibly flexible as they can be chained together
//! to gain access to a process running multiple levels of virtualization deep (see figure below).
//!
//! ```text
//! +-----------+ +-----------+
//! | native OS | | leechcore |
//! +-+---------+ +-+---------+
//! | |
//! | +-----------+ | +----------+
//! +->| QEMU VM | +->| Win32 OS |
//! +-+---------+ +-+--------+
//! | |
//! | +----------+ | +-----------+
//! +->| Win32 OS | +->| lsass.exe |
//! +-+--------+ +-----------+
//! |
//! | +-----------+
//! +->| Hyper-V |
//! +-+---------+
//! |
//! | +----------+
//! +->| Linux OS |
//! +-+--------+
//! |
//! | +-----------+
//! +->| SSHD Proc |
//! +-----------+
//!
//! (Example chains of access. For illustrative purposes only - Hyper-V Connector and Linux OS are not yet available)
//! ```
//!
//! As a library user, you do not have to worry about delicacies of chaining - everything is provided,
//! batteries included. See one of our [examples](memflow/examples/process_list.rs) on how simple it is to
//! build a chain (excluding parsing). All Connectors and OS layers are dynamically loadable with common
//! interface binding them.
//!
//! All of this flexibility is provided with very robust and efficient backend - memory interface is
//! batchable and divisible, which gets taken advantage of by our throughput optimized virtual address
//! translation pipeline that is able to walk the entire process virtual address space in under a second.
//! Connectors and OS layers can be composed with the vast library of generic caching mechanisms, utility
//! functions and data structures.
//!
//! The memflow ecosystem is not bound to just Rust - Connector and OS layer functions are linked together
//! using C ABI, thus users can write code that interfaces with them in other languages, such as C, C++, Zig,
//! etc. In addition, these plugins can too be implemented in foreign languages - everything is open.
//!
//! Overall, memflow is the most robust, efficient and flexible solution out there for machine introspection.
//!
//! # Structure
//!
//! memflow is separated into modules that are concerned with different parts of the ecosystem.
//! [mem](crate::mem) module is concerned with memory interfacing, [os](crate::os) module is
//! conerned with OS abstractions, [architecture](crate::architecture) module defines
//! specification of a computer architecture, as well as several built-in architectures,
//! [types](crate::types) concerns itself with data types used throughout memflow, while
//! [plugins](crate::plugins) module defines the dynamically loadable plugin types.
//!
//! ## Getting started
//!
//! To quickly get started with the memflow library, simply include its prelude:
//!
//! ```
//! use memflow::prelude::v1::*;
//! ```
//!
//! Afterwards, you will want to build a memflow object using the plugin inventory:
//!
//! ```
//! # use memflow::prelude::v1::*;
//! # fn main() -> Result<()> {
//! let inventory = Inventory::scan();
//! # let inventory = inventory.with_workspace()?;
//!
//! let conn = inventory.create_connector("dummy", None, None)?;
//! # Ok(())
//! # }
//!
//! ```
//!
//! ## Traits
//!
//! While Connectors and OS layers are the primary user facing objects, functionality of these
//! objects is provided through a set of traits.
//!
//! ### Core traits
//!
//! [MemoryView](crate::mem::memory_view::MemoryView) is the primary trait of issuing read and
//! write operations. Required functions are a bit intimidating, because memflow wants IO to be
//! batchable, which enables impressive performance, however, there are several helpers available
//! for performing simple read and write operations.
//!
//! [Os](crate::os::root::Os) and [OsInner](crate::os::root::OsInner) are the traits that deal with
//! higher level OS abstractions. They enable access to [Processes](crate::os::process::Process)
//! together with their MemoryViews. The reason for OsInner existance is lack of GATs, however,
//! this complexity should be removed as soon as the feature is
//! [stabilized](https://github.com/rust-lang/rust/pull/96709).
//!
//! [PhysicalMemory](crate::mem::phys_mem::PhysicalMemory) trait is implemented by connectors. It
//! embeds special metadata which is used by our memory caches, however is not much different from
//! MemoryView. Users performing physical reads may use the
//! [phys_view](crate::mem::phys_mem::PhysicalMemory::phys_view) function to access a view to this
//! physical address space and gain access to the helper methods.
//!
//! [VirtualTranslate](crate::mem::virt_translate::VirtualTranslate) trait is optionally provided
//! by processes in order to translate virtual addresses into physical ones. This is a lower level
//! trait.
//!
//! ### Class diagrams
//!
//! ```text
//! +----------------------------+ +----------------------------+
//! | | | |
//! | Connector | | OS Layer |
//! | | | |
//! | +------------------------+ | | +------------------------+ |
//! | | PhysicalMemory | | | | OsInner | |
//! | +------------------------+ | | +------------------------+ |
//! | | | |
//! | +------------------------+ | | +------------------------+ |
//! | | Clone | | | | Clone | |
//! | +------------------------+ | | +------------------------+ |
//! | | | |
//! | Optional: | | Optional: |
//! | | | |
//! | +------------------------+ | | +------------------------+ |
//! | | ConnectorCpuState | | | | MemoryView | |
//! | +------------------------+ | | +------------------------+ |
//! | | | |
//! +----------------------------+ | +------------------------+ |
//! | | VirtualTranslate | |
//! | +------------------------+ |
//! | |
//! | +------------------------+ |
//! | | PhysicalMemory | |
//! | +------------------------+ |
//! | |
//! | +------------------------+ |
//! | | OsKeyboard | |
//! +----------------------------+ | +------------------------+ |
//! | | +----------------------------+
//! | IntoProcessInstance |
//! | |
//! | +------------------------+ | +----------------------------+
//! | | Process | | | |
//! | +------------------------+ | | ProcessInstance |
//! | | | |
//! | +------------------------+ | | +------------------------+ |
//! | | MemoryView | | | | Process | |
//! | +------------------------+ | | +------------------------+ |
//! | | | |
//! | +------------------------+ | | +------------------------+ |
//! | | Clone | | | | MemoryView | |
//! | +------------------------+ | | +------------------------+ |
//! | | | |
//! | Optional: | | Optional: |
//! | | | |
//! | +------------------------+ | | +------------------------+ |
//! | | VirtualTranslate | | | | VirtualTranslate | |
//! | +------------------------+ | | +------------------------+ |
//! | | | |
//! +----------------------------+ +----------------------------+
//! ```
//!
//! # Philosophy
//!
//! The core idea of memflow is to generalize where possible, specialize when needed.
//!
//! Best practice of writing memflow functions is to write them generically - use `impl Trait`
//! notation to define the type of object needed. This will allow for your code to work on both
//! dynamically loaded plugins, as well as custom, statically linked, and potentially more
//! efficient memory/OS objects.
//!
//! For instance, if you want to perform a memory read, define the function as follows:
//!
//! ```
//! use memflow::prelude::v1::*;
//! # use memflow::dummy::{DummyMemory, DummyOs};
//!
//! // Define the function with `impl Trait` notation
//! fn special_read(mem: &mut impl MemoryView) -> Result<u64> {
//! mem.read(Address::from(0x42)).data()
//! }
//!
//! // Use it with plugin object
//! let mut inventory = Inventory::scan();
//! # let mut inventory = inventory.with_workspace().unwrap();
//! let args = str::parse(":4m").unwrap();
//! let conn = inventory.create_connector("dummy", None, Some(&args))
//! .unwrap();
//!
//! assert!(special_read(&mut conn.into_phys_view()).is_ok());
//!
//! // Use it with statically built connector
//! let mut mem = DummyMemory::new(size::mb(4));
//!
//! assert!(special_read(&mut mem.phys_view()).is_ok());
//!
//! // Use it with statically built process
//! let mut proc = DummyOs::quick_process(size::mb(4), &[]);
//!
//! assert!(special_read(&mut proc).is_ok());
//! ```
//#![warn(missing_docs)]
// due to the fact that umem equals u64 when compiling with a x86_64 target clippy issues false-positives on these conversions.
// targets other than x86_64 still might require those.
#![allow(clippy::unnecessary_cast)]
// this issue is triggered due to an issue in bitmask 1.x
// since upgrading to 2.x broke code generation via cglue-bindgen / cbindgen
// we are allowing this lint temporarily
#![allow(clippy::bad_bit_mask)]
// no-std-compat
#![cfg_attr(not(feature = "std"), no_std)]
extern crate no_std_compat as std;
#[macro_use]
extern crate bitflags;
#[macro_use]
extern crate smallvec;
pub mod error;
#[macro_use]
pub mod types;
pub mod architecture;
pub mod mem;
pub mod connector;
#[cfg(feature = "plugins")]
pub mod plugins;
pub mod os;
pub mod iter;
// forward declare
#[doc(hidden)]
pub mod derive {
pub use ::memflow_derive::*;
}
#[doc(hidden)]
pub mod cglue {
pub use ::cglue::prelude::v1::*;
}
#[doc(hidden)]
#[cfg(feature = "abi_stable")]
pub mod abi_stable {
pub use ::abi_stable::*;
}
#[doc(hidden)]
pub mod dataview {
pub use ::dataview::*;
pub use ::memflow_derive::Pod;
}
#[doc(hidden)]
#[cfg(any(feature = "dummy_mem", test))]
pub mod dummy;
// TODO: modules should be cleanly seperated here and only necessary types should be exported
#[doc(hidden)]
#[allow(ambiguous_glob_reexports)]
pub mod prelude {
pub mod v1 {
pub use crate::architecture::*;
pub use crate::cglue::*;
pub use crate::connector::*;
pub use crate::dataview::*;
pub use crate::derive::*;
pub use crate::error::*;
pub use crate::iter::*;
pub use crate::mem::*;
pub use crate::os::*;
#[cfg(feature = "plugins")]
pub use crate::plugins::os::*;
#[cfg(feature = "plugins")]
pub use crate::plugins::*;
pub use crate::types::*;
}
pub use v1::*;
}