Fading Coder

One Final Commit for the Last Sprint

Home > Tech > Content

Reading Cross-Process Memory Data for Android Mobile Game Reverse Engineering

Tech 1

Reading Target Process Memory

To read memory from a target Android game, we first need the app's PID, which we already know how to dynamically retrieve. We will use a Linux system call to read cross-process memory, demonstrated with a shooter game example.

Memory Reading via process_vm_readv Syscall

Linux provides the process_vm_readv system call accessed via the __NR_process_vm_readv call number. This system call enables direct memory transfer between separate processes, elimintaing extra data copying steps and keeping overhead low for memory reading tasks.

process_vm_readv requires the following arguments:

  1. PID of the target process to read memory from
  2. Pointer to a local struct iovec array describing output buffers in the current process
  3. Number of iovec entries in the local array
  4. Pointer to a remote struct iovec array describing memory regions to read in the target process
  5. Number of iovec entries in the remote array
  6. Unused flags, set to 0 for this use case

Practical Implementation Example

With PID already obtained, the only missing information is the target memory address holding the value we want to read. We can use Game Guardian to locate the address of the in-game score variable:

  1. Launch the game and search for the initial score (usually 0) in Game Guardian
  2. Defeat enemies to change the score, then search for the new updated score
  3. Repeat the refinement process until you are left with a single address that matches the current score value

In this test example, the resulting address from Game Guardian is 13168330 in hexadecimal, so we use 0x13168330 as the target address in code. We also need to specify the number of bytes to reead: for 64-bit Android 12, we read 8 bytes for an integer value in this example.

The base function for reading an integer from the target process is:

int read_target_int(pid_t target_pid, long long target_addr) {
    struct iovec local_iov, remote_iov;
    int result_buf;

    local_iov.iov_base = &result_buf;
    local_iov.iov_len = 8;

    remote_iov.iov_base = (void *)target_addr;
    remote_iov.iov_len = 8;

    syscall(__NR_process_vm_readv,
            target_pid,
            &local_iov,
            1,
            &remote_iov,
            1,
            0);

    return result_buf;
}

Call the function with your obtained PID and target address to get the score:

long long score_addr = 0x13168330;
int current_score = read_target_int(target_pid, score_addr);
printf(

Related Articles

Understanding Strong and Weak References in Java

Strong References Strong reference are the most prevalent type of object referencing in Java. When an object has a strong reference pointing to it, the garbage collector will not reclaim its memory. F...

Comprehensive Guide to SSTI Explained with Payload Bypass Techniques

Introduction Server-Side Template Injection (SSTI) is a vulnerability in web applications where user input is improper handled within the template engine and executed on the server. This exploit can r...

Implement Image Upload Functionality for Django Integrated TinyMCE Editor

Django’s Admin panel is highly user-friendly, and pairing it with TinyMCE, an effective rich text editor, simplifies content management significantly. Combining the two is particular useful for bloggi...

Leave a Comment

Anonymous

◎Feel free to join the discussion and share your thoughts.