Source Code ReadProcessMemory for Linux equivalent

Swift Games Accounts
  • This site uses cookies. By continuing to use this site, you are agreeing to our use of cookies. Learn more.
  • ► You must register to download attachments!
Jul 6, 2013
Your RAM

This is for people that are new to Linux and generally game hacking/programming, code is written in C.
When one is coming from Windows he will probably be used to ReadProcessMemory, an easy to use function for reading memory in another process.
Well on Linux there is no readprocessmemory, but a function that gives you even more control called ptrace.

First we are going to include some some files and define some funciton prototypes.


#define _GNU_SOURCE


#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <stdarg.h>
#include <dirent.h>
#include <unistd.h>
#include <errno.h>

#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ptrace.h>
#include <sys/wait.h>

#include <fcntl.h>

#define PROC_DIRECTORY "/proc/"   
#define CASE_SENSITIVE    1
#define EXACT_MATCH       1
#define INEXACT_MATCH     0

typedef struct LinuxProc_s{

    char*    ProcMemPath;
    pid_t    ProcId;

} LinuxProc_t;

int attach(LinuxProc_t target);
int detach(LinuxProc_t target);
int Read(LinuxProc_t Process, int32_t nsize, void* address, void* buffer);
int Write(int32_t nsize, void* address, void* buffer);
pid_t GetPIDbyName(const char* cchrptr_ProcessName, int intCaseSensitiveness, int intExactMatch);
int IsNumeric(const char* ccharptr_CharacterList);
LinuxProc_t LinuxProcFromID(pid_t pid);

/proc/ is the directory where all the process information is stored in linux, there is two ways to modify/read memory from another process. the first way is by reading the mem file and the second way is to use the ptrace function used for debugging.
We are going to use the ptrace mehtod because its easier, reading the mem file is harder because /proc/$pid/mem shows the contents of $pid's memory mapped the same way as in the process, i.e., the byte at offset x in the pseudo-file is the same as the byte at address x in the process. If an address is unmapped in the process, reading from the corresponding offset in the file returns EIO (Input/output error). For example, since the first page in a process is never mapped (so that dereferencing a NULL pointer fails cleanly rather than unintendedly accessing actual memory), reading the first byte of /proc/$pid/mem always yield an I/O error.
The way to find out what parts of the process memory are mapped is to read /proc/$pid/maps. But for now we will keep it at ptrace.

I created a LinuxProc_t structure to store all process specific stuff in one struct per process.
For now we will just add the mem file path (we arent gonna use it) and the process id.

#include "LinuxMemory.h"

int IsNumeric(const char* ccharptr_CharacterList)
    for ( ; *ccharptr_CharacterList; ccharptr_CharacterList++)
        if (*ccharptr_CharacterList < '0' || *ccharptr_CharacterList > '9')
            return 0;
    return 1;

int strcmp_ws(const char *s1, const char *s2, int intCaseSensitive)
    if (intCaseSensitive)
        return !strcmp(s1, s2);
        return !strcasecmp(s1, s2);

int strstr_ws(const char* haystack, const char* needle, int intCaseSensitive)
    if (intCaseSensitive)
        return (int) strstr(haystack, needle);
        return (int) strcasestr(haystack, needle);

pid_t GetPIDbyName(const char* cchrptr_ProcessName, int intCaseSensitiveness, int intExactMatch)
    int ipid = -1;
    char chrarry_CommandLinePath[800]  ;
    char chrarry_NameOfProcess[500]  ;
    char* chrptr_StringToCompare = NULL ;
    struct dirent* de_DirEntity = NULL ;
    DIR* dir_proc = NULL ;

    int (*CompareFunction) (const char*, const char*, int) ;

    if (intExactMatch)
        CompareFunction = &strcmp_ws;
        CompareFunction = &strstr_ws;

    dir_proc = opendir(PROC_DIRECTORY) ;
    if (dir_proc == NULL)
        perror("Couldn't open the " PROC_DIRECTORY " directory") ;
        return  -2 ;

    // Loop while not NULL
    while ((de_DirEntity = readdir(dir_proc)) )
        // Skip non numeric entries
        if (de_DirEntity->d_type == DT_DIR)
            if (IsNumeric(de_DirEntity->d_name))
                strcpy(chrarry_CommandLinePath, PROC_DIRECTORY) ;
                strcat(chrarry_CommandLinePath, de_DirEntity->d_name) ;
                strcat(chrarry_CommandLinePath, "/cmdline") ;
                FILE* fd_CmdLineFile = fopen (chrarry_CommandLinePath, "rt") ;  // open the file for reading text
                if (fd_CmdLineFile)
                    fscanf(fd_CmdLineFile, "%s", chrarry_NameOfProcess) ; // read from /proc/<NR>/cmdline
                    fclose(fd_CmdLineFile);  // close the file prior to exiting the routine

                    if (strrchr(chrarry_NameOfProcess, '/'))
                        chrptr_StringToCompare = strrchr(chrarry_NameOfProcess, '/') +1 ;
                        chrptr_StringToCompare = chrarry_NameOfProcess ;

                    if ( CompareFunction(chrptr_StringToCompare, cchrptr_ProcessName, intCaseSensitiveness) ) 
                        ipid = atoi(de_DirEntity->d_name);
                        closedir(dir_proc) ;
                        return ipid;
    closedir(dir_proc) ;
    return ipid ;

int attach(LinuxProc_t target)
    int status;

    /* attach, to the target application, which should cause a SIGSTOP */
    if (ptrace(PTRACE_ATTACH, target, NULL, NULL) == -1L) {
        fprintf(stderr, "error: failed to attach to %d, %s, Try running as root\n", target,
        return 0;

    /* wait for the SIGSTOP to take place. */
    if (waitpid(target, &status, 0) == -1 || !WIFSTOPPED(status)) {
                "error: there was an error waiting for the target to stop.\n");
        fprintf(stdout, "info: %s\n", strerror(errno));
        return 0;

    /* everything looks okay */
    return 1;


int detach(LinuxProc_t target)
    return ptrace(PTRACE_DETACH, target, NULL, 0) == 0;

int Read(LinuxProc_t Process, int32_t nsize, void* address, void* buffer)
    long  _DEBUGINT  = 0;

    _DEBUGINT = ptrace(PTRACE_PEEKDATA,Process.ProcId,address,0);
    printf("Output from ptrace : %i", _DEBUGINT); // currently just reads one word, but later i will add more data types.

    return 1;

LinuxProc_t LinuxProcFromID(pid_t pid)
    char mem_file_name[1000];
    LinuxProc_t ProcStruct;

    sprintf(mem_file_name, "/proc/%d/mem", pid);

    ProcStruct.ProcId = pid;
    ProcStruct.ProcMemPath = mem_file_name;

    return ProcStruct;

As you can see i created two wrapper functions for strstr and strcmp. Ive also added a function that checks if a string is numeric or not by checking if its between byte '0' and '9'.
What we need to do first is find the process id by name:
- loop through every file in /proc/
- check if the process has an id
- get the command line for the process (what was used to start the program)
- the cmdline contains the procname

then all we need to do is use ptrace on the process with PTRACE_PEEKDATA, which returns one word.

An example of usage:
#include <stdio.h>
#include <stdlib.h>

#include "LinuxMemory.h"

int main()
    LinuxProc_t CodeBlocks;
    /* Fill structure */
    CodeBlocks = LinuxProcFromID((pid_t)GetPIDbyName("codeblocks",0,0));
    printf("Process ID : %i\n", CodeBlocks.ProcId);
    void* address = 0x8b6b3000;
    return 0;

Hope this helped some people out.

Last edited: