简体   繁体   中英

Reading process memory and printing instruction opcodes in Android

I have been trying to read ARM instruction Opcode of another process but I encounter complications.

Basically I compile my code as a executable using ndk and then I run the executeable using adb shell.

Heres the code I used for trying to achieve my objective:

static void skeleton_daemon()
{
    pid_t pid;

    /* Fork off the parent process */
    pid = fork();

    /* An error occurred */
    if (pid < 0)
        exit(EXIT_FAILURE);

    /* Success: Let the parent terminate */
    if (pid > 0)
        exit(EXIT_SUCCESS);

    /* On success: The child process becomes session leader */
    if (setsid() < 0)
        exit(EXIT_FAILURE);

    /* Catch, ignore and handle signals */
    //TODO: Implement a working signal handler */
    signal(SIGCHLD, SIG_IGN);
    signal(SIGHUP, SIG_IGN);

    /* Fork off for the second time*/
    pid = fork();

    /* An error occurred */
    if (pid < 0)
        exit(EXIT_FAILURE);

    /* Success: Let the parent terminate */
    if (pid > 0)
        exit(EXIT_SUCCESS);

    /* Set new file permissions */
    umask(0);

    /* Change the working directory to the root directory */
    /* or another appropriated directory */
    chdir("/");

    /* Close all open file descriptors */
    int x;
    for (x = sysconf(_SC_OPEN_MAX); x>=0; x--)
    {
        close (x);
    }

    /* Open the log file */
    openlog ("ELOS", LOG_PID, LOG_DAEMON);
}

// --------------------------------------------------------------------------

    void readMem(int pid, const char* address, int len) {
    
    unsigned long addr = strtoul(address, NULL, 16);
    
    char* mem_dir = (char*) malloc(50);
    sprintf(mem_dir, "/proc/%d/mem", pid);
    
    syslog(LOG_NOTICE, "Opening %s and going to address %02X", mem_dir, addr);
    
    int fd_proc_mem = open(mem_dir, O_RDWR);
    if (fd_proc_mem == -1) {
        syslog(LOG_NOTICE, "Opening failed!");
        exit(1);
        }
        
    char* buff = (char*) malloc(len);
    
    lseek(fd_proc_mem, addr, SEEK_SET);
    read (fd_proc_mem, buff , len);
    
    syslog(LOG_NOTICE, "Data at %02X in process %d is: %02X\n", addr, pid, buff);
    
    free(buff);
    free(mem_dir);
}
int main() {

skeleton_daemon();
    void* mybuf;
    
    while (1)
    {
        syslog (LOG_NOTICE, "First daemon starts.");

        readMem(6743, "0C133E64", 4); // pid = 6743, address to read = 0C133E64 (shared lib base address + instruction offset), length = 4

        break;
    }

    syslog (LOG_NOTICE, "First daemon terminated.");
    closelog();

    return EXIT_SUCCESS;

}

On executing via adb the results are as follows:



11-24 15:31:14.263 11166 11166 I ELOS    : First daemon starts.
11-24 15:31:14.266 11166 11166 I ELOS    : Opening /proc/6743/mem and going to address C133E64
11-24 15:31:14.266 11166 11166 I ELOS    : Data at C133E64 in process 6743 is: B6C9A0B8
11-24 15:31:14.267 11166 11166 I ELOS    : First daemon terminated.

11-24 15:31:18.122 11176 11176 I ELOS    : First daemon starts.
11-24 15:31:18.124 11176 11176 I ELOS    : Opening /proc/6743/mem and going to address C133E64
11-24 15:31:18.124 11176 11176 I ELOS    : Data at C133E64 in process 6743 is: B6C1A0B8
11-24 15:31:18.125 11176 11176 I ELOS    : First daemon terminated.

11-24 15:31:25.689 11194 11194 I ELOS    : First daemon starts.
11-24 15:31:25.692 11194 11194 I ELOS    : Opening /proc/6743/mem and going to address C133E64
11-24 15:31:25.692 11194 11194 I ELOS    : Data at C133E64 in process 6743 is: B6D1A0B8
11-24 15:31:25.693 11194 11194 I ELOS    : First daemon terminated.

The result is different in every execution. Why is that so?

Ok so here is how I got it working..


uint32_t reverse_bytes(uint32_t bytes)
{
    uint32_t aux = 0;
    uint8_t byte;
    int i;

    for(i = 0; i < 32; i+=8)
    {
        byte = (bytes >> i) & 0xff;
        aux |= byte << (32 - 8 - i);
    }
    return aux;
}


void Attach(pid_t pid, unsigned long addr, unsigned long data = 0, bool iswrite = false) {
     
    //First, attach to the process
    errno = 0;
    if (ptrace(PTRACE_ATTACH, pid, NULL, NULL) == -1) {
        
        syslog(LOG_NOTICE, "Stuck at Attach: %s", strerror(errno));
        exit(1);
    }

    //Now, attaching doesn't mean we can read the value straight away
    //We have to wait for the process to stop
    int status;
    //waitpid() returns -1 on failure
    if (waitpid(pid, &status, 0) == -1 || !WIFSTOPPED(status)) {
        //Failed, read the value of errno or strerror(errno)
        syslog(LOG_NOTICE, "Stuck at waitpid: %s", strerror(errno));
        exit(1);
    }


    if (iswrite == true){
        memWrite(pid, addr, data);
    } else {
        memRead(pid, addr);
    }
    
    //Now, we have to detach from the process
    ptrace(PTRACE_DETACH, pid, NULL, NULL);        
}

    void  memRead(pid_t pid, unsigned long addr) {

    errno = 0; 
    unsigned long value = ptrace(PTRACE_PEEKDATA, pid, addr, NULL);
    unsigned long tmp = reverse_bytes(value); // for some reason the bytes show up reversed, so I used this func to re order them

    if (value == -1 && errno != 0) {

        syslog(LOG_NOTICE, "Bytes reading Failed: %s", strerror(errno));
        exit(1);

    } else {
        
        syslog(LOG_NOTICE, "Bytes at %Lu: %08X ", addr, tmp);
    }

}

void  memWrite(pid_t pid, unsigned long addr, unsigned long data) {

    syslog(LOG_NOTICE, "----- Original Bytes ----- ");
    memRead(pid, addr);

    data = reverse_bytes(data);
    unsigned long value2 = ptrace(PTRACE_POKETEXT, pid, (void *)addr, (void *)data);
    if (value2 == -1 && errno != 0) {
        syslog(LOG_NOTICE, "Modification Failed: %s", strerror(errno));
        exit(1);
    } else {
        syslog(LOG_NOTICE, "---- Modified Bytes ----- ");
        memRead(pid, addr);
    }
    //Now, we have to detach from the process
    
}

Well, it does work now... But I wonder whether why patching only for the first time works. Patching on the offset again fails.

Example:

Orig hex -> 011041E2 (SUB r1, r1, #1)
Patching for first time -> 011081E2 (ADD r1, r1, #1) [Works, function behavior changes]
Patching 2nd time -> 641081E2 (ADD r1, r1, #100) [Patch succeeds but function does not behave accordingly, behavior is similar to when patched for first time]

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM