int ptrace_call_wrapper(pid_t target_pid, const char * func_name, void * func_addr, long * parameters, int param_num, struct pt_regs * regs) { LOGD("Calling [%s] in target process <%d> \n", func_name,target_pid); if (ptrace_call(target_pid, (uint32_t)func_addr, parameters, param_num, regs) < 0) { return -1; } if (ptrace_getregs(target_pid, regs) < 0) { return -1; } return 0; }
int ptrace_call_wrapper(pid_t target_pid, const char * func_name, void * func_addr, long * parameters, int param_num, struct pt_regs * regs) { DEBUG_PRINT("[+] Calling %s in target process.\n", func_name); if (ptrace_call(target_pid, (uint32_t)func_addr, parameters, param_num, regs) == -1) return -1; if (ptrace_getregs(target_pid, regs) == -1) return -1; DEBUG_PRINT("[+] Target process returned from %s, return value=%x, pc=%x \n", func_name, ptrace_retval(regs), ptrace_ip(regs)); return 0; }
int main(int argc, char* argv[]) { int pid; struct link_map *map; struct elf_info einfo; extern dl_fl_t ldl; void *handle = NULL; long proc = 0; long hooker_fopen = 0; char pathfile[100]; if (argc != 4) { LOGE("illegal arguments, injection reject"); return -1; } LOGD("inject begin"); pid = find_pid_of(argv[1]); ptrace_attach(pid); ptrace_find_dlinfo(pid); handle = ptrace_dlopen(pid, str_contact(argv[2], HOOK_LIB), 1); printf("ptrace_dlopen handle %p\n", handle); proc = (long) ptrace_dlsym(pid, handle, "hook"); printf("main = %lx\n", proc); ptrace_arg arg; arg.s = argv[3]; arg.type = PAT_STR; static char buffer[0x1000]; strcpy(buffer, argv[1]); strcat(buffer, "#"); strcat(buffer, argv[3]); arg.s = buffer; printf("arg.s=%s\n", arg.s); ptrace_call(pid, proc, 1, &arg); ptrace_detach(pid); LOGD("inject end"); exit(0); return 0; }
void call_dl_open (int pid, unsigned long addr, char *libname) { void *pRLibName; struct user_regs_struct regs; /* 先找个空间存放要装载的共享库名,我们可以简单的把它放入堆栈 */ pRLibName = ptrace_push (pid, libname, strlen (libname) + 1); /* 设置参数到寄存器 */ ptrace_readreg (pid, ®s); regs.eax = (unsigned long) pRLibName; regs.ecx = 0x0; regs.edx = RTLD_LAZY; ptrace_writereg (pid, ®s); /* 调用_dl_open */ ptrace_call (pid, addr); puts ("call _dl_open ok"); }
/* write the assembler code into target proc, * and invoke it to execute */ int writecode_to_targetproc( pid_t target_pid, // target process pid const char *library_path, // the path of .so that will be // upload to target process const char *function_name, // .so init fucntion e.g. hook_init void *param, // the parameters of init function size_t param_size ) // number of parameters { int ret = -1; void *mmap_addr, *dlopen_addr, *dlsym_addr, *dlclose_addr; void *local_handle, *remote_handle, *dlhandle; uint8_t *map_base; uint8_t *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 global variable in the assembler code extern uint32_t _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; uint32_t code_length; long parameters[10]; // make target_pid as its child process and stop if ( ptrace_attach( target_pid ) == -1 ) return -1; // get the values of 18 registers from target_pid if ( ptrace_getregs( target_pid, ®s ) == -1 ) goto exit; // save original registers memcpy( &original_regs, @regs, sizeof(regs) ); // get mmap address from target_pid // the mmap is the address of mmap in the cur process mmap_addr = get_remote_addr( target_pid, "/system/lib/libc.so", (void *)mmap ); // set mmap parameters 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 // execute the mmap in target_pid if ( ptrace_call( target_pid, (uint32_t)mmap_addr, parameters, 6, ®s) == -1 ) goto exit; // get the return values of mmap <in r0> if ( ptrace_getregs( target_pid, ®s) == -1 ) goto exit; // get the start address for assembler code map_base = (uint8_t *)regs.ARM_r0; // get the address of dlopen, dlsym and dlclose in target process dlopen_addr = get_remote_addr( target_pid, "/system/bin/linker", (void *)dlopen ); dlsym_addr = get_remote_addr( target_pid, "/system/bin/linker", (void *)dlsym ); dlclose_addr = get_remote_addr( target_pid, "/system/bin/linker", (void *)dlclose ); // set the start address for assembler code in target process remote_code_ptr = map_base + 0x3C00; // set the start address for assembler code in cur process local_code_ptr = (uint8_t *)&_inject_start_s; // set global variable of assembler code // and these address is in the target process _dlopen_addr_s = (uint32_t)dlopen_addr; _dlsym_addr_s = (uint32_t)dlsym_addr; _dlclose_addr_s = (uint32_t)dlclose_addr; code_length = (uint32_t)&_inject_end_s - (uint32_t)&_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; // save library path to assembler code global variable strcpy( dlopen_param1_ptr, library_path ); _dlopen_param1_s = REMOTE_ADDR( dlopen_param1_ptr, local_code_ptr, remote_code_ptr ); // save function name to assembler code global variable strcpy( dlsym_param2_ptr, function_name ); _dlsym_param2_s = REMOTE_ADDR( dlsym_param2_ptr, local_code_ptr, remote_code_ptr ); // save cpsr to assembler code global variable _saved_cpsr_s = original_regs.ARM_cpsr; // save r0-r15 to assembler code global variable 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 ); // save function parameters to assembler code global variable memcpy( inject_param_ptr, param, param_size ); _inject_function_param_s = REMOTE_ADDR( inject_param_ptr, local_code_ptr, remote_code_ptr ); // write the assembler code into target process // now the values of global variable is in the target process space ptrace_writedata( target_pid, remote_code_ptr, local_code_ptr, 0x400 ); memcpy( ®s, &original_regs, sizeof(regs) ); // set sp and pc to the start address of assembler code regs.ARM_sp = (long)remote_code_ptr; regs.ARM_pc = (long)remote_code_ptr; // set registers for target process ptrace_setregs( target_pid, ®s ); // make the target_pid is not a child process of cur process // and make target_pid continue to running ptrace_detach( target_pid ); // now finish it successfully ret = 0; exit: return ret; }
/** * inject shared library to target process */ int inject_remote_process( pid_t target_pid, const char *library_path, const char *function_name, void *param, size_t param_size ) { int ret = -1; void *mmap_addr, *dlopen_addr, *dlsym_addr, *dlclose_addr; void *local_handle, *remote_handle, *dlhandle; uint8_t *map_base; uint8_t *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; // declared in shellcode.s extern uint32_t _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, _hook_entry_addr_s; uint32_t code_length; long parameters[10]; DEBUG_PRINT( "[+] 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 ); DEBUG_PRINT( "[+] 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 DEBUG_PRINT( "[+] Calling mmap in target process.\n" ); if ( ptrace_call( target_pid, (uint32_t)mmap_addr, parameters, 6, ®s ) == -1 ) goto exit; if ( ptrace_getregs( target_pid, ®s ) == -1 ) goto exit; DEBUG_PRINT( "[+] Target process returned from mmap, return value=%x, pc=%x \n", regs.ARM_r0, regs.ARM_pc ); map_base = (uint8_t *)regs.ARM_r0; // get address of dlopen(), dlsym() and dlclose() in target process 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 ); DEBUG_PRINT( "[+] Get imports: dlopen: %x, dlsym: %x, dlclose: %x\n", dlopen_addr, dlsym_addr, dlclose_addr ); remote_code_ptr = map_base + 0x3C00; local_code_ptr = (uint8_t *)&_inject_start_s; _dlopen_addr_s = (uint32_t)dlopen_addr; _dlsym_addr_s = (uint32_t)dlsym_addr; _dlclose_addr_s = (uint32_t)dlclose_addr; DEBUG_PRINT( "[+] Inject code start: %x, end: %x\n", local_code_ptr, &_inject_end_s ); code_length = (uint32_t)&_inject_end_s - (uint32_t)&_inject_start_s; dlopen_param1_ptr = local_code_ptr + code_length + 0x20; // 0x20 == 32 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( dlopen_param1_ptr, library_path ); _dlopen_param1_s = REMOTE_ADDR( dlopen_param1_ptr, local_code_ptr, remote_code_ptr ); DEBUG_PRINT( "[+] _dlopen_param1_s: %x\n", _dlopen_param1_s ); /* dlsym parameter 2: function name */ strcpy( dlsym_param2_ptr, function_name ); _dlsym_param2_s = REMOTE_ADDR( dlsym_param2_ptr, local_code_ptr, remote_code_ptr ); DEBUG_PRINT( "[+] _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 ); DEBUG_PRINT( "[+] _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 ); DEBUG_PRINT( "[+] _inject_function_param_s: %x\n", _inject_function_param_s ); DEBUG_PRINT( "[+] 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; // change pc to execute instructions at remote_code_ptr regs.ARM_pc = (long)remote_code_ptr; DEBUG_PRINT( "[+] hook_entry address: %x\n", _hook_entry_addr_s); ptrace_setregs( target_pid, ®s ); ptrace_detach( target_pid ); // inject succeeded ret = 0; exit: return ret; }
void injectSo(pid_t pid,char* so_path, char* function_name,char* parameter) { struct pt_regs old_regs,regs; long mmap_addr, dlopen_addr, dlsym_addr, dlclose_addr; //save old regs ptrace(PTRACE_GETREGS, pid, NULL, &old_regs); memcpy(®s, &old_regs, sizeof(regs)); //get remote addres printf("getting remote addres:\n"); mmap_addr = get_remote_addr(pid, libc_path, (void *)mmap); dlopen_addr = get_remote_addr( pid, libc_path, (void *)dlopen ); dlsym_addr = get_remote_addr( pid, libc_path, (void *)dlsym ); dlclose_addr = get_remote_addr( pid, libc_path, (void *)dlclose ); printf("mmap_addr=%p dlopen_addr=%p dlsym_addr=%p dlclose_addr=%p\n", (void*)mmap_addr,(void*)dlopen_addr,(void*)dlsym_addr,(void*)dlclose_addr); long parameters[10]; //mmap parameters[0] = 0; //address parameters[1] = 0x4000; //size parameters[2] = PROT_READ | PROT_WRITE | PROT_EXEC; //WRX parameters[3] = MAP_ANONYMOUS | MAP_PRIVATE; //flag parameters[4] = 0; //fd parameters[5] = 0; //offset ptrace_call(pid, mmap_addr, parameters, 6, ®s); ptrace(PTRACE_GETREGS, pid, NULL, ®s); long map_base = regs.ARM_r0; printf("map_base = %p\n", (void*)map_base); //dlopen printf("save so_path = %s to map_base = %p\n", so_path, (void*)map_base); putdata(pid, map_base, so_path, strlen(so_path) + 1); parameters[0] = map_base; parameters[1] = RTLD_NOW| RTLD_GLOBAL; ptrace_call(pid, dlopen_addr, parameters, 2, ®s); ptrace(PTRACE_GETREGS, pid, NULL, ®s); long handle = regs.ARM_r0; printf("handle = %p\n",(void*) handle); //dlsym printf("save function_name = %s to map_base = %p\n", function_name, (void*)map_base); putdata(pid, map_base, function_name, strlen(function_name) + 1); parameters[0] = handle; parameters[1] = map_base; ptrace_call(pid, dlsym_addr, parameters, 2, ®s); ptrace(PTRACE_GETREGS, pid, NULL, ®s); long function_ptr = regs.ARM_r0; printf("function_ptr = %p\n", (void*)function_ptr); //function_call printf("save parameter = %s to map_base = %p\n", parameter, (void*)map_base); putdata(pid, map_base, parameter, strlen(parameter) + 1); parameters[0] = map_base; ptrace_call(pid, function_ptr, parameters, 1, ®s); //dlcose parameters[0] = handle; ptrace_call(pid, dlclose_addr, parameters, 1, ®s); //restore old regs ptrace(PTRACE_SETREGS, pid, NULL, &old_regs); }
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; }