int ptrace_writestring(pid_t pid, unsigned char *dest, char *str){ return ptrace_writedata(pid, dest, (unsigned char *)str, strlen(str)+ 1); }
long arch_ptrace(struct task_struct *child, long request, unsigned long addr, unsigned long data) { unsigned long addr2 = current->thread.kregs->u_regs[UREG_I4]; void __user *addr2p; const struct user_regset_view *view; struct pt_regs __user *pregs; struct fps __user *fps; int ret; view = task_user_regset_view(current); addr2p = (void __user *) addr2; pregs = (struct pt_regs __user *) addr; fps = (struct fps __user *) addr; switch(request) { case PTRACE_GETREGS: { ret = copy_regset_to_user(child, view, REGSET_GENERAL, 32 * sizeof(u32), 4 * sizeof(u32), &pregs->psr); if (!ret) copy_regset_to_user(child, view, REGSET_GENERAL, 1 * sizeof(u32), 15 * sizeof(u32), &pregs->u_regs[0]); break; } case PTRACE_SETREGS: { ret = copy_regset_from_user(child, view, REGSET_GENERAL, 32 * sizeof(u32), 4 * sizeof(u32), &pregs->psr); if (!ret) copy_regset_from_user(child, view, REGSET_GENERAL, 1 * sizeof(u32), 15 * sizeof(u32), &pregs->u_regs[0]); break; } case PTRACE_GETFPREGS: { ret = copy_regset_to_user(child, view, REGSET_FP, 0 * sizeof(u32), 32 * sizeof(u32), &fps->regs[0]); if (!ret) ret = copy_regset_to_user(child, view, REGSET_FP, 33 * sizeof(u32), 1 * sizeof(u32), &fps->fsr); if (!ret) { if (__put_user(0, &fps->fpqd) || __put_user(0, &fps->flags) || __put_user(0, &fps->extra) || clear_user(fps->fpq, sizeof(fps->fpq))) ret = -EFAULT; } break; } case PTRACE_SETFPREGS: { ret = copy_regset_from_user(child, view, REGSET_FP, 0 * sizeof(u32), 32 * sizeof(u32), &fps->regs[0]); if (!ret) ret = copy_regset_from_user(child, view, REGSET_FP, 33 * sizeof(u32), 1 * sizeof(u32), &fps->fsr); break; } case PTRACE_READTEXT: case PTRACE_READDATA: ret = ptrace_readdata(child, addr, addr2p, data); if (ret == data) ret = 0; else if (ret >= 0) ret = -EIO; break; case PTRACE_WRITETEXT: case PTRACE_WRITEDATA: ret = ptrace_writedata(child, addr2p, addr, data); if (ret == data) ret = 0; else if (ret >= 0) ret = -EIO; break; default: if (request == PTRACE_SPARC_DETACH) request = PTRACE_DETACH; ret = ptrace_request(child, request, addr, data); break; } return ret; }
int inject_remote_process(pid_t target_pid, const char *library_path, const char *function_name, const char *param, size_t param_size){ /* [1]通过远程进程pid,ATTACH到远程进程。 [2]获取远程进程寄存器值,并保存,以便注入完成后恢复进程原有状态。 [3]获取远程进程系统调用mmap、dlopen、dlsym调用地址。 [4]调用远程进程mmap分配一段存储空间,并在空间中写入so库路径以及函数调用参数。 [5]执行远程进程dlopen,加载so库。 [6]执行远程进程dlsym,获取so库中需要执行的函数地址。 [7]执行远程进程中的函数。 [7]恢复远程进程寄存器。 [8]DETACH远程进程。 * */ int ret = -1; void*mmap_addr, *dlopen_addr, *dlsym_addr, *dlclose_addr; void*local_handle, *remote_handle, *dlhandle; unsigned char* map_base; unsigned char* dlopen_param1_ptr, *dlsym_param2_ptr, *saved_r0_pc_ptr, *inject_param_ptr, *remote_code_ptr, *local_code_ptr; struct pt_regs regs, original_regs; extern unsigned int _dlopen_addr_s, _dlopen_param1_s, _dlopen_param2_s, _dlsym_addr_s, _dlsym_param2_s, _dlclose_addr_s, _inject_start_s, _inject_end_s, _inject_function_param_s, _saved_cpsr_s, _saved_r0_pc_s; unsigned int code_length; long parameters[10]; printf("[+] Injecting process: %d\n", target_pid ); if (ptrace_attach(target_pid)== -1) return EXIT_SUCCESS; if (ptrace_getregs(target_pid, ®s)== -1) goto exit; /* save original registers */ memcpy(&original_regs, ®s, sizeof(regs)); mmap_addr = get_remote_addr(target_pid, "/system/lib/libc.so", (void*)mmap); printf("[+] Remote mmap address: %x\n", mmap_addr ); /* call mmap */ parameters[0] = 0; // addr parameters[1] = 0x4000; // size parameters[2] = PROT_READ | PROT_WRITE | PROT_EXEC; // prot parameters[3] = MAP_ANONYMOUS | MAP_PRIVATE; // flags parameters[4] = 0; //fd parameters[5] = 0; //offset printf("[+] Calling mmap in target process.\n" ); if (ptrace_call(target_pid, (unsigned int)mmap_addr, parameters, 6, ®s) == -1) goto exit; if (ptrace_getregs(target_pid, ®s)== -1) goto exit; printf("[+] Target process returned from mmap, return value=%x, pc=%x \n", regs.ARM_r0, regs.ARM_pc ); map_base = (unsigned char*)regs.ARM_r0; /*------------------------------------------------------------------------------------------------------*/ dlopen_addr = get_remote_addr(target_pid, linker_path, (void*)dlopen); dlsym_addr = get_remote_addr(target_pid, linker_path, (void*)dlsym); dlclose_addr = get_remote_addr(target_pid, linker_path, (void*)dlclose); printf("[+] Get imports: dlopen: %x, dlsym: %x, dlclose: %x\n", dlopen_addr, dlsym_addr, dlclose_addr ); remote_code_ptr = map_base + 0x3C00; local_code_ptr = (unsigned char*)&_inject_start_s; _dlopen_addr_s = (unsigned int)dlopen_addr; _dlsym_addr_s = (unsigned int)dlsym_addr; _dlclose_addr_s = (unsigned int)dlclose_addr; printf("[+] Inject code start: %x, end: %x\n", local_code_ptr, &_inject_end_s ); code_length = (unsigned int)&_inject_end_s - (unsigned int)&_inject_start_s; dlopen_param1_ptr = local_code_ptr + code_length + 0x20; dlsym_param2_ptr = dlopen_param1_ptr + MAX_PATH; // 偏移 saved_r0_pc_ptr = dlsym_param2_ptr + MAX_PATH; //偏移 inject_param_ptr = saved_r0_pc_ptr + MAX_PATH; //偏移 /* dlopen parameter 1: library name */ strcpy((char*)dlopen_param1_ptr, library_path); _dlopen_param1_s = REMOTE_ADDR(dlopen_param1_ptr, local_code_ptr, remote_code_ptr); printf("[+] _dlopen_param1_s: %x\n", _dlopen_param1_s ); /* dlsym parameter 2: function name */ strcpy((char*)dlsym_param2_ptr, function_name); _dlsym_param2_s = REMOTE_ADDR(dlsym_param2_ptr, local_code_ptr, remote_code_ptr); printf("[+] _dlsym_param2_s: %x\n", _dlsym_param2_s ); /* saved cpsr */ _saved_cpsr_s = original_regs.ARM_cpsr; /* saved r0-pc */ memcpy(saved_r0_pc_ptr, &(original_regs.ARM_r0), 16 * 4); // r0 ~ r15 _saved_r0_pc_s = REMOTE_ADDR(saved_r0_pc_ptr, local_code_ptr, remote_code_ptr); printf("[+] _saved_r0_pc_s: %x\n", _saved_r0_pc_s ); /* Inject function parameter */ memcpy(inject_param_ptr, param, param_size); _inject_function_param_s = REMOTE_ADDR(inject_param_ptr, local_code_ptr, remote_code_ptr); printf("[+] _inject_function_param_s: %x\n", _inject_function_param_s ); printf("[+] Remote shellcode address: %x\n", remote_code_ptr ); ptrace_writedata(target_pid, remote_code_ptr, local_code_ptr, 0x400); memcpy(®s, &original_regs, sizeof(regs)); regs.ARM_sp= (long)remote_code_ptr; regs.ARM_pc= (long)remote_code_ptr; printf("[+] recovery regs.\n"); ptrace_setregs(target_pid, ®s); printf("[+] detach.\n"); ptrace_detach(target_pid); // inject succeeded printf("[+] inject succeeded\n"); ret = 0; exit: return ret; }