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.