Unsafe Rust — Modify memory of another process 😖

A couple of weeks ago, i posted an article about using Cheat Engine to modify the memory of the game Metal Slug 3. However, Cheat Engine…

Unsafe Rust — Modify memory of another process 😖
crete the project

A few weeks ago, I shared an article about using Cheat Engine to inspect and modify the memory of the game Metal Slug 3. However, Cheat Engine is primarily designed for inspection and may not be very convenient if you want to automate the process of modifying the game’s memory. Today, we will tackle this challenge by writing a simple program in Rust to freeze a memory address.🦀 😘

No need to worry if you missed the previous post; this one will focus on the FFI part, which is unrelated to Cheat Engine.

How?

We’ll utilize the Win32 API’s WriteProcessMemory to write the desired value to that process.

As the API is in another language, we’ll need to perform FFI (Foreign Function Interface) in Rust. Luckily, Microsoft has generously exposed the entire Win32 API in Rust through the “windows-sys” crate, saving us the trouble of doing it ourselves.

Let’s go

Let create the project using these commands:

cargo new metal_slug_3_trainer 
cd metal_slug_3_trainer 
code .

These commands should create the project and open that project in your VsCode.

Dependencies

We’ll require two crates as dependencies in our codebase. The first one, as mentioned earlier, is “windows-sys.” The second one is “sysinfo,” which we use to retrieve the process ID from the process name.

Open the cargo.toml and add these lines to your [dependencies] section:

sysinfo = "0.26.4" 
windows-sys = { version = "0.42.0", features = [ 
"Win32_System_Diagnostics_Debug", 
"Win32_Foundation", 
"Win32_System_Threading", 
] }

These features are mandatory, as indicated in the sysinfo documentation here and here.

The Handle

Let’s take a quick look at the signature of WriteProcessMemory.

WriteProcessMemory signature

The first parameter is the Handle. What exactly is a Handle, and how do we obtain it? In a general sense, a handle is a reference or pointer to a particular entity. In this case, it’s a pointer to the memory of our process.

First parameter

We will use the function OpenProcess to retrieve the handle.

OpenProcess function

Now, back to the code. we will call the function like this:

Retrieving the handle

The document of WriteProcessMemory states The handle must have PROCESS_VM_WRITE and PROCESS_VM_OPERATION access to the process. You can set the parameter as PROCESS_ALL_ACCESS like my code or can set it like this PROCESS_VM_WRITE | PROCESS_VM_OPERATION

The second parameter is set to 0 because we have no intention to create any child process.

The process_id parameter can be retrieved by using the crate sysinfo which i mentioned above like this.

Create a function to get process id from process name
Invoking the function

“neoragex” here is the process name, i also used the nth(0) because the given name could returns many processes. Since neoragex has only one process, the first one found should be the one we needed.

The remaining parameters…

lpBaseAddress is the pointer to the address of the process we want to write, we can create it like this

Second parameter

lpBuffer is the pointer to the buffer we want to write, we do the same thing but a bit different here

Third parameter

nSize because our buffer is 4 bytes (0xFF 0x07 0x00 0x00), the value for this parameter is 4.

lpNumberOfBytesWritten this is an out value indicates how many bytes were written, we don't need it in this case so i will set it to NULL.

Finally

With all the parameters available, we can call the function like this:

Calling the function

But this only writes the memory once, if we want to freeze the memory, a loop is required

freezing the memory

Conclusion

Doing FFI (Foreign Function Interface) for the first time might seem a bit peculiar, wouldn’t you agree? However, it can be quite enjoyable, too.

You can access the source code for this post on GitHub. Feel free to explore and even add some fun features like switching to a random gun every 3 seconds — it’s all about enhancing the experience! Enjoy coding! 😄