replacemem/
replacemem.rs

1//! # Purpose
2//! 
3//! This example is a CLI application that can find and replace arbitrary
4//! data in an arbitrary process, using the raminspect library as a backend.
5//! 
6//! # Usage
7//! 
8//! `sudo cargo run --example replacemem --release -- <pid> <search term> <replacement>`
9//!
10//! Or if you want to install this as a command line application, you may build it using this command:
11//! 
12//! `cargo build --release --example replacemem`
13//!
14//! And then copy the output to /usr/bin like so:
15//! 
16//! `sudo cp target/release/examples/replacemem /usr/bin/replacemem`
17//! 
18//! And then use the resulting executable like this after you refresh your shell:
19//! 
20//! `replacemem <pid> <string search term> <string replacement>`
21
22fn exit_err(msg: &str) -> ! {
23    eprintln!("Error: {}", msg);
24    eprintln!("Program usage: replacemem pidnumber \"searchterm\" \"replacement\"");
25    std::process::exit(1);
26}
27
28fn main() {
29    use raminspect::RamInspector;
30    let mut args = std::env::args();
31    let pid_parse_err = "Expected a number as the first argument";
32
33    // Skip the first argument which is the program name on Unix systems
34    args.next();
35    
36    let pid = args.next().unwrap_or_else(|| exit_err(pid_parse_err)).parse::<i32>().unwrap_or_else(|_| {
37        exit_err(pid_parse_err)
38    });
39
40    let search_term = args.next().unwrap_or_else(|| exit_err("Expected three arguments."));
41    let replacement_term = args.next().unwrap_or_else(|| exit_err("Expected three arguments."));
42
43    if args.next().is_some() {
44        exit_err("Expected no more than three arguments.");
45    }
46
47    use raminspect::RamInspectError;
48    fn inspect_process(pid: i32, search_term: &str, replacement_term: &str) -> Result<(), RamInspectError> {
49        unsafe {
50            let mut inspector = RamInspector::new(pid)?;
51            for (result_addr, memory_region) in inspector.search_for_term(search_term.as_bytes())? {
52                if !memory_region.writable() {
53                    continue;
54                }
55
56                inspector.queue_write(result_addr, replacement_term.as_bytes());
57            }
58            
59            inspector.flush().unwrap();
60        }
61
62        Ok(())
63    }
64
65    if let Err(error) = inspect_process(pid, &search_term, &replacement_term) {
66        exit_err(&format!("{:?}", error));
67    }
68}