Reading/writing another program’s memory manually

We keep going deeper into memory reading and writing, but this time no external software, we will learn how to read and write from and to another process (virtual) memory by ourselves.

I have written two programs in C that I will present you and explain step by step. The first one (let’s call it the legitimate program) loads two variables in memory (an integer and a string) and the other one (let’s call it the hacktool) opens the first program’s memory, reads it, prompts the user for a new string to replace into the other program’s memory and replace the memory. Both program allow you to repeat the operation to perform your tests.

Required C code:

Here is the code of the first legitimate program allowing you to load 2 variables in memory:

#include 
#include 
#include 

#define MAX_LENGTH_STRING 100

int main()
{
    // Initialising our variables
    int varNum = 0, varExit = 0;
    char varString[MAX_LENGTH_STRING] = "";
    // Giving a value to our integer type variable to find it in memory afterwards
    printf("Enter a number to load in memory: ");
    scanf("%d", &varNum);
    // Giving a value to our char type variable to find it in memory afterwards
    printf("Enter a string to load in memory: ");
    scanf("%s", &varString);
    // Infinite loop to check the variable values after modification in memory
    while (varExit != 1) {
        printf("\n\n");
        printf("varNum (address = 0x%X) = %d\n", &varNum, varNum);
        printf("varString (address = 0x%X) = \"%s\"\n", &varString, varString);
        printf("\nEnter 1 to exit or 0 to loop: ");
        scanf("%d", &varExit);
    }
    return 0;
}

As you can see it is quite simple, the user is just prompted to enter a number that is stored in an integer variable and a string also stored in memory. The program then prints it on the string along with the memory address.

The other program is the one reading the first program’s memory and allowing us to modify the value directly into its variable. Here is its code, commented so you can understand what is happening:

#include 
#include 
#include 
#include 

#define MAX_LENGTH_STRING 100

int main( void )
{
    // Initialising the variable
    DWORD processID = 0; // I use the DWORD type to fully comply with microsoft MSDN official help
    int addrToRead = 0, bytesRead = 0, bytesWritten = 0, varExit = 0;
    char strToRead[MAX_LENGTH_STRING] = "", newStrToSet[MAX_LENGTH_STRING] = "";

    // Prompting the user for the process ID (can be found in the task manager or could be automated with EnumProcesses)
    printf("PID to read: ");
    scanf("%d", &processID);
    // Prompting the user for the memory area to read (we will see in a further tutorial how to locate the addresses of interest)
    printf("Address in virtual memory to read: ");
    scanf("%X", &addrToRead);

    // Opening the process of interest with the permissions required (read/write memory are essential to our exercise)
    HANDLE hProcess = OpenProcess( PROCESS_QUERY_INFORMATION | PROCESS_VM_READ | PROCESS_VM_WRITE, FALSE, processID );
    if ( NULL != hProcess ) {
        printf("[ OK ] Process %d successfully opened\n\n", processID);
        while (varExit != 1) {
            // Reading the memory and sending the data to the address of our variable strToRead
            ReadProcessMemory(hProcess, addrToRead, &strToRead, MAX_LENGTH_STRING, &bytesRead);
            printf("String at address 0x%X : %s (%d bytes read)\n", addrToRead, strToRead, bytesRead);
            // Prompting the user for the new string to replace in memory
            printf("Enter the new string to replace: ");
            scanf("%s", &newStrToSet);
            printf("Writing new data to memory...\n");
            // Writing the new string to memory
            WriteProcessMemory(hProcess, addrToRead, &newStrToSet, MAX_LENGTH_STRING, &bytesWritten);
            printf("Done! (%d bytes written)\n", bytesWritten);
            // With the loop it is possible to re read the memory from this program
            printf("\nEnter 1 to exit or 0 to loop: ");
            scanf("%d", &varExit);
        }
    } else {
        // In case the process could not be opened (like if you don't have the permissions)
        printf("[ ERROR ] Failed to open process");
        return 1;
    }
    return 0;
}

Straightforward, basically we open the process, we read the memory at the specified address, prompt the user for a new string, replace the string in memory and we can loop to re read and print in the console the memory.

Demonstration:

I start the first legitimate program and enter as number the date of today and my name as string:

vars-in-mem

I now start the hacktool program and gives it the process ID of the legitimate program as well as the address of the variable I am interested in modifying (the string, my name in this example). The program then read the data at the specified memory address and prints it before asking me a new string to replace the other one. I enter my new string and confirm, the program writes it to the memory.

var-modified-in-memory

If I go back in the legitimate program and enter 0 so the program prints on the screen the value of the variables it shows me the modified string:

proof-modified-in-memory

Documentation:

To write this program, I used the functions provided by the operating system windows, using the functions OpenProcess, ReadProcessMemory and WriteProcessMemory.

You can access the official documentation of these functions by clicking on them.

Conclusion & future tutorials:

We have seen that reading and writing to another program’s memory is possible and how to do it manually without using external programs.

It doesn’t look like it, but with this simple knowledge you could already do some game cheating programs that would give you unlimited health points, ammunations or other. You can also make a program that detects if the windows calculator is opened and always prints a wrong result and many other funny things.

However, for advanced game cheating this technique will not be sufficient as many competitive games have security mechanisms forbidding another program to read their memory. In the next tutorials we will have a look at how these security work and what are the options to bypass them. We will try these options and make a program that could read and write the memory even of protected programs. This technique is only detected by the most sophisticated anti cheating systems but I will give you hints and direction so you can find a way to make it undetectable (at least for some time…).

Leave a Reply

Your email address will not be published. Required fields are marked *