natechoe.dev The blog Contact info Other links The github repo

Directly modifying memory values in Linux

This is going to be a pretty short post detailing a pretty cool thing that you can do in Linux. If you have access to a Linux system right now, run ls /proc. You should see several things, but what we care about now are the directories of the form /proc/[PID]

You see, /proc is a pseudo-filesystem, meaning that its contents aren't actually stored on disk, but rather created dynamically with each read. If you run ls /proc/[PID] to see the contents of one of these directories, or ls /proc/self to see the contents of this directory for the current process, you'll see several pieces of information about the process itself. For example, /proc/[PID]/environ contains the environment variables of any given process.

Perhaps the 2 most interesting files in here are /proc/[PID]/maps and /proc/[PID]/mem. /proc/[PID]/maps shows the memory map of that process, including (among other things) the address spaces that each map takes up, and the permissions that the current process has on it. If you cat out one of these files, you may notice that you have quite a few privileges on many processes. This means that you can open /proc/[PID]/mem, the actual memory of that process, and just change a few values in there. To demonstrate this, I wrote 2 programs.

printvalue.c:

#include <stdio.h>
#include <unistd.h>

int main() {
	int i = 5;
	for (;;) {
		printf("Value at %p for process %d: %d\n", &i, getpid(), i);
		sleep(1);
	}
}

changevalue.c:

#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>

int main() {
	int pid;
	void *addr;
	int newval;
	printf("Enter the pid: ");
	scanf("%d", &pid);
	printf("Enter the pointer: ");
	scanf("%p", &addr);
	printf("Enter the new value: ");
	scanf("%d", &newval);

	char path[20];
	sprintf(path, "/proc/%d/mem", pid);

	int fd = open(path, O_RDWR);
	lseek(fd, (unsigned long long) addr, SEEK_SET);
	write(fd, &newval, sizeof(newval));
}

After compiling and running printvalue.c, you might get something like this:

Value at 0x7ffeaceef7e4 for process 25720: 5
Value at 0x7ffeaceef7e4 for process 25720: 5
Value at 0x7ffeaceef7e4 for process 25720: 5
...

Then after running changevalue.c and putting in input similar to

Enter the pid: 25720
Enter the pointer: 0x7ffeaceef7e4
Enter the new value: 10

You'll see that the output of printvalue.c has changed!

...
Value at 0x7ffeaceef7e4 for process 25720: 5
Value at 0x7ffeaceef7e4 for process 25720: 5
Value at 0x7ffeaceef7e4 for process 25720: 5
Value at 0x7ffeaceef7e4 for process 25720: 10
Value at 0x7ffeaceef7e4 for process 25720: 10
Value at 0x7ffeaceef7e4 for process 25720: 10
...

That's it, just a neat thing that you can do in Linux.