GithubHelp home page GithubHelp logo

read-process-memory's Introduction

GitHub Actions Build status Cirrus CI Build status crates.io

A crate to read memory from another process. Code originally taken from the rbspy project. This crate has now returned home to the rbspy GitHub organization. :)

Example

This example re-executes itself as a child process in order to have a separate process to use for demonstration purposes. If you need to read memory from a process that you are spawning, your usage should look very similar to this:

use std::convert::TryInto;
use std::env;
use std::io::{self, BufReader, BufRead, Read, Result};
use std::process::{Command, Stdio};

use read_process_memory::{
  Pid,
  ProcessHandle,
  CopyAddress,
  copy_address,
};

fn main() -> Result<()> {
    if env::args_os().len() > 1 {
      // We are the child.
      return in_child();
    }
    // Run this executable again so we have a child process to read.
    let mut child = Command::new(env::current_exe()?)
        .stdin(Stdio::piped())
        .stdout(Stdio::piped())
        .arg("child")
        .spawn()?;

    // Get a ProcessHandle to work with.
    let handle: ProcessHandle = (&child).try_into().unwrap();

    // The child process will print the address to read from on stdout.
    let mut stdout = BufReader::new(child.stdout.take().unwrap());
    let mut addr_string = String::new();
    stdout.read_line(&mut addr_string)?;
    let address = usize::from_str_radix(addr_string.trim(), 16).unwrap();

    // Try to read 10 bytes from that address
    let bytes = copy_address(address, 10, &handle)?;
    println!("Read: {:?}", bytes);

    // Tell the child to exit by closing its stdin.
    drop(child.stdin.take());
    // And wait for it to exit.
    child.wait()?;
    Ok(())
}

fn in_child() -> Result<()> {
    // Allocate a 10-byte Vec for the parent to read.
    let readable_bytes: Vec<u8> = vec![
        0xc0, 0x72, 0x80, 0x79, 0xeb, 0xf1, 0xbc, 0x87, 0x06, 0x14,
    ];
    // Print the address of the Vec to stdout so the parent can find it.
    println!("{:x}", readable_bytes.as_ptr() as usize);
    // Now wait to exit until the parent closes our stdin, to give
    // it time to read the memory.
    let mut buf = Vec::new();
    // We don't care if this succeeds.
    drop(io::stdin().read_to_end(&mut buf));
    Ok(())
}

How it works

Here's a summary, with some C pseudocode, of how the read-process-memory crate works under the hood on each of the platforms it supports. The three inputs are:

  • PID: the process ID to read from
  • LENGTH: how much memory to read
  • ADDRESS: the address to read from

Linux:

Uses process_vm_readv

void* TARGET = (void*) 0x123412341324;
struct iovec local;
local.iov_base = calloc(LENGTH, sizeof(char));
local.iov_len = LENGTH;
struct iovec remote;
remote[0].iov_base = TARGET;
remote[0].iov_len = LENGTH;
process_vm_readv(PID, local, 2, remote, 1, 0);

Mac OS:

Uses vm_read_overwrite

mach_port_name_t task;
task_for_pid(mach_task_self(), PID, &task)
vm_size_t read_len = LENGTH;
char result[LENGTH];
vm_read_overwrite(task, TARGET, LENGTH, &result, &read_len)

FreeBSD:

Uses ptrace. This one stops the process to read from it.

// attach
int wait_status = 0;
attach_status = ptrace(PT_ATTACH, PID, null, 0);
waitpid(PID, &wait_status, 0);
WIFSTOPPED(wait_status)
char result[LENGTH];
desc = PtraceIoDesc {
  piod_op: PIOD_READ_D,
  piod_offs: TARGET;
  piod_addr: &result;
  piod_len: LENGTH,
};
// read data
ptrace(PT_IO, PID, &desc, 0);
// detach
ptrace(PT_DETACH, PID, null, 0);

Windows:

Uses ReadProcessMemory:

char result[LENGTH];
ReadProcessMemory(PID, ADDRESS, &result, LENGTH, null);

read-process-memory's People

Contributors

acj avatar akhramov avatar benfred avatar cryze avatar fitzgen avatar hargonix avatar jvns avatar luser avatar omarabid avatar p1n3appl3 avatar pythonspeed avatar sebageek avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

read-process-memory's Issues

Unclear ownership semantics cause leaks

Let's say you are on Windows and use the TryFrom<Pid> to get a ProcessHandle. This internally opens the process handle associated with that Pid. However there's no Drop implementation, so this handle gets leaked. Similar leaks might happen on other platforms.

Cast to Pid on Monterey M1

Hi there! This might be silly of me. Very new to rust. But I can't get the example to work properly

When I run exactly the same code as on the main page it crashes and gives me this:

Error: Os { code: 0, kind: Uncategorized, message: "Undefined error: 0" }

I've debugged and that happens on the TryInto
let handle: ProcessHandle = (&child).try_into().unwrap();

I run macOS Monterey with M1 chip.

Shorten name

I believe the name of this repo could be shortened to read-proc or dump-proc or something similar. It helps keep typing down and works better with crates.io

Add osx CI if possible

Not sure if the weird task stuff that this library does will be allowed in the Travis environment, but ideally we'd have some good expectation of non-brokenness.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.