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