您的位置:首页 > 其它

ARM下的injectso

2013-03-19 14:56 811 查看
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