ARM下的injectso

 

https://bitbucket.org/tewilove/injectso/src/41afcf79b9c4/injectso.c

 

#include <errno.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <dlfcn.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/ptrace.h>

#if !defined(__ANDROID__) || (!defined(__arm__) && !defined(__thumb__))
#error "ARM Android only!"
#endif

static void die(int ln) {
        char temp[256];
        snprintf(temp, sizeof(temp), "failed at %d: %s\n", ln, strerror(errno));
        fprintf(stderr, temp);
        exit(-1);
}

static void usage(FILE *fp, const char *self) {
        fprintf(fp, "Usage:\n");
        fprintf(fp, "%s <pid> <so>\n", self);
}

static void* get_module_base_addr(pid_t pid, const char* name) {
        FILE *fp;
        char path[32];
        long addr = -1;
        char buffer[1024];
        char *temp;

        if (pid == -1)
                snprintf(path, sizeof(path), "/proc/self/maps");
        else
                snprintf(path, sizeof(path), "/proc/%d/maps", pid);
        fp = fopen(path, "r");
        if (!fp)
                return (void *)(-1);
        while (fgets(buffer, sizeof(buffer), fp)) {
                if (strstr(buffer, name)) {
                        temp = strtok(buffer, "-");
                        addr = strtoul(temp, NULL, 16);
                        if(addr == 0x8000) {
                                addr = 0;
                        }
                        break;
                }
        }
        fclose(fp);
        return (void*) addr;
}

static void *find_my_dlopen() {
        void *handle = dlopen("libdl.so", RTLD_NOW);
        if (!handle)
                die(__LINE__);
        void *symbol = dlsym(handle, "dlopen");
        if (!symbol)
                die(__LINE__);
        return symbol;
}

static int find_symbol_offset(pid_t pid, const char *ref) {
        void *mine = get_module_base_addr(-1, ref);
        if (!mine)
                return -1;
        void *theirs = get_module_base_addr(pid, ref);
        if (!theirs)
                return -1;
        return (int)(mine) - (int)(theirs);
}

static void *find_foreign_dlopen(pid_t pid, void *my_dlopen) {
        int offset = find_symbol_offset(pid, "/system/bin/linker");
        if (offset == -1)
                offset = find_symbol_offset(pid, "/system/lib/libc.so");
        if (offset == -1)
                die(__LINE__);
        int result = (int) my_dlopen + offset;
        return (void *) result;
}

// memcpy like
static void ptrace_peek(pid_t pid, void* dest, const void* src, size_t n) {
        int i;
        long *d = (long *) dest, *s = (long *) src;
        n /= sizeof(long);
        for (i = 0; i < n; i++) {
                d[i] = ptrace(PTRACE_PEEKTEXT, pid, s + i, NULL);
                if (errno)
                        die(__LINE__);
        }
}

static void ptrace_poke(pid_t pid, void* dest, const void* src, size_t n) {
        int i;
        long *d = (long *) dest, *s = (long *) src;
        for (i = 0; i < n / sizeof(long); i++) {
                if (ptrace(PTRACE_POKETEXT, pid, d + i, (void *) s[i]) == -1) {
                        die(__LINE__);
                }
        }
}

static int injectso(pid_t pid, const char *so) {
        void *p_dlopen = NULL;
        void *my_dlopen, *foreign_dlopen;
        int err, status, len;
        char old_stack[512], new_stack[512];
        struct pt_regs old_regs, new_regs;

        my_dlopen = find_my_dlopen();
        printf("my dlopen = %p\n", my_dlopen);
        foreign_dlopen = find_foreign_dlopen(pid, my_dlopen);
        printf("foreign dlopen = %p\n", foreign_dlopen);
        printf("attaching...\n");
        err = ptrace(PTRACE_ATTACH, pid, NULL, NULL);
        if (err < 0)
                die(__LINE__);
        if (waitpid(pid, &status, 0) < 0)
                die(__LINE__);
        printf("getting regs...\n");
        err = ptrace(PTRACE_GETREGS, pid, NULL, &old_regs);
        if (err < 0)
                die(__LINE__);
        printf("pc=%08x, sp=%08x, lr=%08x, cpsr=%08x\n", old_regs.ARM_pc, old_regs.ARM_sp, old_regs.ARM_lr, old_regs.ARM_cpsr);
        printf("reading foreign stack...\n");
        ptrace_peek(pid, old_stack, (void *) old_regs.ARM_sp, sizeof(old_stack));
        len = strlen(so);
        memset(new_stack, 0, sizeof(new_stack));
        memcpy(new_stack, so, len);
        memcpy(&new_regs, &old_regs, sizeof(struct pt_regs));
        printf("writing foreign stack...\n");
        ptrace_poke(pid, (void *) old_regs.ARM_sp, new_stack, sizeof(new_stack));
        // = psz_path
        new_regs.ARM_r0 = old_regs.ARM_sp;
        new_regs.ARM_r1 = RTLD_NOW;
        new_regs.ARM_sp += sizeof(new_stack);
        // trigger a SIGE*** after cont
        new_regs.ARM_lr = 0;
        new_regs.ARM_pc = (long) foreign_dlopen;
        if (new_regs.ARM_pc & 1)
                new_regs.ARM_cpsr |= PSR_T_BIT;
        else
                new_regs.ARM_cpsr &= ~PSR_T_BIT;
        printf("setting regs...\n");
        err = ptrace(PTRACE_SETREGS, pid, NULL, &new_regs);
        if (err < 0)
                die(__LINE__);
        printf("resuming...\n");
        err = ptrace(PTRACE_CONT, pid, NULL, NULL);
        if (err < 0)
                die(__LINE__);
        if (waitpid(pid, &status, 0) < 0)
                die(__LINE__);
        printf("restoring foreign stack...\n");
        ptrace_poke(pid, (void *) old_regs.ARM_sp, old_stack, sizeof(old_stack));
        printf("restoring old regs...\n");
        err = ptrace(PTRACE_SETREGS, pid, NULL, &old_regs);
        if (err < 0)
                die(__LINE__);
        err = ptrace(PTRACE_DETACH, pid, NULL, NULL);
        if (err < 0)
                die(__LINE__);

        return 0;
}

int main(int argc, char *argv[]) {
        if (argc != 3) {
                usage(stderr, argv[0]);
                exit(-1);
        }
        pid_t pid = strtoul(argv[1], NULL, 10);
        return injectso(pid, argv[2]);
}

你可能感兴趣的:(ARM,injectso)