Read And Write Process memory on

Hey, everybody.

I wanted to know if it was possible to read to a certain memory address an integer, string etc...

For example I have an address which is the following 556b035c2df1 and which has the value 76.

I want to read to this address ( 0x556b035c2df1) and that it returns its value (76).

In the same way, I want to write to this same address and I want to change its value.
For example 76 becomes 90.

I'm on Linux and I don't necessarily want to go through ptrace.

How did you get that memory address?

WIth GameConqueror

Try:

fn main() {
    unsafe  {
        let addr = 0x556b035c2df1;
        let ptr: *const u64 = &addr;   
        println!("{}", *ptr);

        *(ptr as *mut u64) = 1;
        println!("{}", *ptr);
    }
}

The address is odd number so I guess the "value" OP wanted would be i8/u8 type. But regardlessly, the address would be the virtual address of the scanned process. So it's normally not possible to read from the outside of that process, without the OS-level helper like scanmem which is the GameConqueror depends on, or those Intel processor security bugs.

1 Like

What about winapi::um::processthreadsapi::OpenProcess?

Aha, he's on linux. Or any APIs like that?

Yes for the moment I use GameConqueror to read addresses.

For example in C I had coded this program which allowed me to read and write to a memory address :

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/stat.h>
#include <sys/ptrace.h>
#include <errno.h>
#include <string.h>
#include <fcntl.h>
#include <stdlib.h>

struct StockPid
{
    pid_t pid;
    char buff[512];
    FILE *pid_pipe;
} stockthepid;

void Func_StockPid(const char *processtarget)
{
    stockthepid.pid_pipe = popen(processtarget, "r");
    fgets(stockthepid.buff, 512, stockthepid.pid_pipe);
    stockthepid.pid = strtoul(stockthepid.buff, NULL, 10);

    if (stockthepid.pid == 0)
    {
        printf("App Var is not launch ! \n");
        pclose(stockthepid.pid_pipe);
        exit(-1);
    }
    else
    {
        printf("App Var is running - PID NUMBER -> {%d} \n", stockthepid.pid);
        pclose(stockthepid.pid_pipe);
    }
}

void ReadProcessMemory(unsigned long address, int pid) {

    int buf = 0;

    int err_code = ptrace(PTRACE_ATTACH, stockthepid.pid, NULL, NULL);

    if (err_code == -1)
    {
        printf("%s\n", "error 1");
        exit(-1);
    }
    wait(NULL);

    printf("Read the adress of the process \n");
    for (int i = 0; i < 1; i++) 
    {
       buf = ptrace(PTRACE_PEEKDATA, stockthepid.pid, address + i * sizeof(int), NULL);
         if (buf == -1)
        {
            printf("%s\n", "error 2");
            exit(-1);
        }

        printf("%d\n", buf);
       
    }
    err_code = ptrace(PTRACE_DETACH, stockthepid.pid, NULL, NULL);
    if (err_code == -1)
    {
        printf("%s\n", "error 3");
        exit(-1);
    } 
}

void WriteProcessMemory(unsigned long address, int pid) {
    int WhatValue = 0;
    int buf = 0;

    printf("Enter the new Value !\n");
    scanf("%d", &WhatValue);

    int err_code = ptrace(PTRACE_ATTACH, stockthepid.pid, NULL, NULL);
    if (err_code == -1)
    {
        printf("%s\n", "error 1");
        exit(-1);
    }

    wait(NULL);
    printf("Write the new value ! \n");
    for(int i = 0; i < 1; i++) {
        buf = ptrace(PTRACE_POKEDATA, stockthepid.pid, address + i * sizeof(int), WhatValue);
        if (buf == -1)
        {
            printf("%s\n", "error 2");
            exit(-1);
        }
        printf("The new value has just been added! \n");
    } 
    err_code = ptrace(PTRACE_DETACH, stockthepid.pid, NULL, NULL);
    if (err_code == -1) 
    {
        printf("%s\n", "error 3");
        exit(-1);
    }
}



int main()
{
    Func_StockPid("pidof -s ac_client");
    ReadProcessMemory(0x81d80ed4de, stockthepid.pid);
    WriteProcessMemory(0x81d80ed4de, stockthepid.pid);
    return 0;
} 

I know how to get the pid with rust but I don't know how to read and write to a memory address.

You can conjure up a pointer from an integer (e.g. 0x556b035c2df1 as *mut u8) then write to it like any other raw pointer.

You probably already know, but this operation is wildly unsafe... It assumes you've got access to the memory at that address (OSs usually make sure one process can't access another process's memory, for example), and that the item behind the pointer is the same type as you are using. You also don't want to invalidate assumptions made by the game (e.g. the game uses the value as the player's x position so it must always be a finite value, but you write a floating point NaN to it).

after several hours of research I don't think I can use ptrace with rust on linux at the moment.

Do you know if it is possible to integrate C code directly on my rust file?

Or else I could create a .so library in C that will allow me to read and write in memory, which I would apply directly from my rust program.

You may want to try:

https://github.com/Tommoa/rs-process-memory

What makes you say this? The nix crate exposes a wrapper for using ptrace from Rust.

You could use the cpp crate.

Although this shouldn't be necessary. Any code you can call from C, you can also call from Rust. There are various resources on the internet on using C APIs from Rust code (e.g. Foreign Function Interface from the nomicon).

Yes I saw but unfortunately I can't find tutos that show how to use it. I'll try to do it on my own.

Concerning cpp crate I thank you. But you're right, I should be able to rewrite my C code in rust.

Well, I think I'm beginning to understand how ptrace works with rust.

I still have a little problem, I have this error that shows up in the 'address' field.

mismatched types

expected *-ptr, found i64

note: expected raw pointer *mut std::ffi::c_void.
found type i64rustc(E0308)

and this is my code:

fn read_process_memory(address: i64, pid: i32) {
    let x = get_pid("fakeApp", 0);
    let y = Pid::from_raw(x);

    

    ptrace::attach(y);
    ptrace::read(y, address);
}

What did you find inadequate about rs-process-memory? It seems to adress the exact use case you want.

The Rust API is a direct mirror of the C one, so you should be able to refer to tutorials in C. You'd need to translate the syntax and names, but the resulting Rust code will be quite similar.

You'll need to cast the address to a *mut c_void, which is written as address as *mut c_void in Rust.

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.