Overview
We usually call code injection, the main static and dynamic two ways:
Static injection, for executable files, such as modify Elf,dex files, and other related tools are also many, such as Ida, Apktool and so on;
Dynamic injection, can also be called process injection, for the process, such as modifying the process register, memory value, etc.;
The biggest difference between dynamic and static is that dynamic does not need to change the source files, but requires high permissions (usually root), and the required technical content is higher.
Basic ideas
The key point is to have the target loaded into a custom dynamic library so that when so is loaded, so can load other modules, DEX files, etc.
The specific injection process is generally as follows:
1) Attach on the target process;
2) Let the execution process of the target process jump to the MMAP function to allocate memory space;
3) load injection so;
4) Finally, the execution process of the target process jumps to the injected code execution. Lets the target process jump to code execution in the injected so.
Reference:
Http://ele7enxxh.com/Android-Shared-Library-Injection.html
Http://ele7enxxh.com/Android-Shared-Library-Hook-With-GOT.html
Get target process module base address
void* get_module_base (pid_t pid, const char* module_name);
Get the remote module base address
void* get_remote_addr (pid_t target_pid, const char* module_name, void* local_addr);
Lookup process ID based on process name read/proc/%d/cmdline get process name
int find_pid_of (const char *process_name);
Root inject injects remote process flow
Mount to target process first Ptrace_attach (Target_pid)
Read Target process register data Ptrace_getregs (Target_pid, ®s)
Save the original register datamemcpy (&original_regs, ®s, sizeof (regs));
Gets the address of the target process mmap function,Get_remote_addr (Target_pid, Libc_path, (void *) mmap);
The Mmap function is called in the target process to allocate memory space; Ptrace_call_wrapper (Target_pid, "mmap", mmap_addr, parameters, 6, ®s)
Gets the address of the target process Dlopen function get_remote_addr (Target_pid, Linker_path, (void *) dlopen);
Gets the address of the target process Dlsym function get_remote_addr (Target_pid, Linker_path, (void *) dlsym);
Gets the address of the target process Dlclose function get_remote_addr (Target_pid, Linker_path, (void *) dlclose);
Gets the address of the target process Dlerror function get_remote_addr (Target_pid, Linker_path, (void *) dlerror);
Write Library_path data to the target process Ptrace_writedata (Target_pid, Map_base, Library_path, strlen (Library_path) + 1);
Let the target process call the Dlopen function (Ptrace_call_wrapper (target_pid, "Dlopen", dlopen_addr, Parameters, 2, ®s)
Let the target process call the Dlsym function Ptrace_call_wrapper (target_pid, "Dlsym", dlsym_addr, Parameters, 2, ®s)
Let the target process call the Hook_entry function Ptrace_call_wrapper (target_pid, Function_name, hook_entry_addr, parameters, 1, ®s)
Let the target process call the Dlclose function Ptrace_call_wrapper (target_pid, "Dlclose", Dlclose, Parameters, 1, ®s)
Recovery Register
Ptrace_setregs (Target_pid, &original_regs);
Uninstalling from the target process
Ptrace_detach (TARGET_PID);
#include <stdio.h> #include <stdlib.h> #include <asm/user.h> #include <asm/ptrace.h> #include <sys/ptrace.h> #include <sys/wait.h> #include <sys/mman.h> #include <dlfcn.h> #include < dirent.h> #include <unistd.h> #include <string.h> #include <elf.h> #include <android/log.h> #if defined (__i386__) #define PT_REGS user_regs_struct#endif#define enable_debug 1#if enable_debug#define LOG_TAG "Inject" #define LOGD (FMT, args ...) __android_log_print (Android_log_error,log_tag, FMT, # #args) #define Debug_print (Format,args ...) LOGD (format, # #args) #else # define Debug_print (Format,args ...) #endif # define CPSR_T_MASK (1u << 5) const char *libc_path = "/system/lib/libc.so"; const char *linker_path = "/s Ystem/bin/linker ";//Read process data int ptrace_readdata (pid_t pid, uint8_t *src, uint8_t *buf, size_t size) {uint32_t I, J, Rema In uint8_t *laddr; Union u {long val; Char chars[sizeof (long)]; } D; J= SIZE/4; remain = size% 4; LADDR = BUF; for (i = 0; i < J; i + +) {//copy src pointing data D.val = Ptrace (ptrace_peektext, PID, SRC, 0); memcpy (Laddr, D.chars, 4); src + = 4; Laddr + = 4; } if (remain > 0) {d.val = Ptrace (ptrace_peektext, PID, SRC, 0); memcpy (LADDR, D.chars, remain); } return 0;} Write data to process int ptrace_writedata (pid_t pid, uint8_t *dest, uint8_t *data, size_t size) {uint32_t I, j, remain; uint8_t *laddr; Union u {long val; Char chars[sizeof (long)]; } D; j = SIZE/4; remain = size% 4; LADDR = data; for (i = 0; i < J; i + +) {memcpy (D.chars, LADDR, 4); Ptrace (Ptrace_poketext, PID, dest, D.val); Dest + = 4; Laddr + = 4; } if (remain > 0) {d.val = Ptrace (Ptrace_peektext, PID, dest, 0); for (i = 0; i < remain; I + +) {D.chars[i] = *laddr + +; } ptrace (Ptrace_poketext, PID, dest, D.val); }return 0;} #if defined (__arm__) int ptrace_call (pid_t pid, uint32_t addr, long *params, uint32_t num_params, struct pt_regs* regs) { uint32_t i; for (i = 0; i < num_params && I < 4; i + +) {Regs->uregs[i] = params[i]; }////push remained params onto stack//if (I < num_params) {regs->arm_sp-= (num_params-i) * sizeof (long); Ptrace_writedata (PID, (void *) REGS->ARM_SP, (uint8_t *) ¶ms[i], (num_params-i) * sizeof (long)); } regs->arm_pc = addr; if (REGS->ARM_PC & 1) {/* thumb */regs->arm_pc &= (~1U); REGS->ARM_CPSR |= Cpsr_t_mask; } else {/* arm */REGS->ARM_CPSR &= ~cpsr_t_mask; } REGS->ARM_LR = 0; if (Ptrace_setregs (PID, regs) = =-1 | | ptrace_continue (PID) = =-1) {printf ("error\n"); return-1; } int stat = 0; Waitpid (PID, &stat, wuntraced); while (stat! = 0xb7f) {if (Ptrace_contiNue (PID) = =-1) {printf ("error\n"); return-1; } waitpid (PID, &stat, wuntraced); } return 0;} #elif defined (__i386__) long Ptrace_call (pid_t pid, uint32_t addr, long *params, uint32_t num_params, struct USER_REGS_STR UCT * regs) {regs->esp-= (num_params) * sizeof (long); Ptrace_writedata (PID, (void *) REGS->ESP, (uint8_t *) params, (num_params) * sizeof (long)); Long tmp_addr = 0x00; Regs->esp = sizeof (long); Ptrace_writedata (PID, REGS->ESP, (char *) &tmp_addr, sizeof (TMP_ADDR)); Regs->eip = addr; if (Ptrace_setregs (PID, regs) = =-1 | | ptrace_continue (PID) = =-1) {printf ("error\n"); return-1; } int stat = 0; Waitpid (PID, &stat, wuntraced); while (stat! = 0xb7f) {if (ptrace_continue (pid) = =-1) {printf ("error\n"); return-1; } waitpid (PID, &stat, wuntraced); } return 0;} #else #error "not supported" #endif//Read processRegister data int Ptrace_getregs (pid_t pid, struct Pt_regs * regs) {if (Ptrace (Ptrace_getregs, PID, NULL, Regs) < 0) { Perror ("Ptrace_getregs:can not get Register values"); return-1; } return 0;} Set process Register int ptrace_setregs (pid_t pid, struct Pt_regs * regs) {if (Ptrace (Ptrace_setregs, PID, NULL, Regs) < 0) { Perror ("Ptrace_setregs:can not set register values"); return-1; } return 0;} The process continues to point to int ptrace_continue (pid_t pid) {if (Ptrace (Ptrace_cont, PID, NULL, 0) < 0) {perror ("Ptrace_cont"); return-1; } return 0;} Mount to target process int Ptrace_attach (pid_t pid) {if (Ptrace (Ptrace_attach, PID, NULL, 0) < 0) {perror ("Ptrace_attach") ; return-1; } int status = 0; Waitpid (PID, &status, wuntraced); return 0;} unload int Ptrace_detach (pid_t pid) {if (Ptrace (Ptrace_detach, PID, NULL, 0) < 0) {perror ("Ptrace_detach") from the target process ); return-1; } return 0;} Gets the target process module base address void* Get_module_Base (pid_t pid, const char* module_name) {FILE *fp; Long addr = 0; Char *pch; Char filename[32]; Char line[1024]; if (PID < 0) {/* Self process */snprintf (filename, sizeof (filename), "/proc/self/maps", PID); } else {snprintf (filename, sizeof (filename), "/proc/%d/maps", PID); } fp = fopen (filename, "R"); if (fp = NULL) {while (fgets, sizeof (line), FP)) {if (Strstr (line, module_name)) { PCH = Strtok (line, "-"); Addr = Strtoul (PCH, NULL, 16); if (addr = = 0x8000) addr = 0; Break }} fclose (FP); } return (void *) addr;} Get remote module base void* get_remote_addr (pid_t target_pid, const char* module_name, void* local_addr) {void* local_handle, *remo Te_handle; Local_handle = Get_module_base ( -1, module_name); Remote_handle = Get_module_base (Target_pid, module_name); Debug_print ("[+] Get_remote_addr: LOCAL[%X], remote[%x]\n ", Local_handle, Remote_handle); void * Ret_addr = (void *) ((uint32_t) local_addr + (uint32_t) Remote_handle-(uint32_t) local_handle); #if defined (__i386__ if (!strcmp (Module_name, Libc_path)) {ret_addr + = 2; } #endif return ret_addr;} Find process ID based on process name read/proc/%d/cmdline get process name int find_pid_of (const char *process_name) {int id; pid_t pid =-1; dir* dir; FILE *FP; Char filename[32]; Char cmdline[256]; struct Dirent * entry; if (process_name = = NULL) return-1; dir = Opendir ("/proc"); if (dir = = NULL) return-1; while ((Entry = Readdir (dir)) = NULL) {id = atoi (entry->d_name); if (id! = 0) {sprintf (filename, "/proc/%d/cmdline", id); fp = fopen (filename, "R"); if (FP) {fgets (cmdline, sizeof (cmdline), FP); Fclose (FP); if (strcmp (process_name, cmdline) = = 0) {/* process found */ PID = ID; Break }}}} Closedir (dir); return PID;} Long Ptrace_retval (struct Pt_regs * regs) {#if defined (__arm__) return regs->arm_r0; #elif defined (__i386__) return regs->eax; #else #error "not supported" #endif}long ptrace_ip (struct Pt_regs * regs) {#if defined (__arm__) return regs- >ARM_pc; #elif defined (__i386__) return regs->eip; #else #error "not supported" #endif}int Ptrace_call_wrapper (PID _t target_pid, const char * func_name, void * func_addr, long * parameters, int param_num, struct pt_regs * regs) {Debu G_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), p TRACE_IP (regs)); return 0;} Injecting remote process data int Inject_remote_process (pid_t target_pid, const char *library_path, const char *function_name, const char *param, size_t PA ram_size) {int ret =-1; void *mmap_addr, *dlopen_addr, *dlsym_addr, *dlclose_addr, *dlerror_addr; void *local_handle, *remote_handle, *dlhandle; uint8_t *map_base = 0; 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 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]; Debug_print ("[+] injecting process:%d\n", target_pid); First mount to target process if (Ptrace_attach (target_pid) = =-1) goto exit; Read target process register data if (Ptrace_getregs (target_pid, ®s) = =-1) goto exit; /* Save original registers saving the original register data */ memcpy (&original_regs, ®s, sizeof (regs)); Gets the address of the target process mmap function mmap_addr = get_remote_addr (Target_pid, Libc_path, (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//Call the MMAP function in the target process if (Ptrace_call_wrapper (Target_pid, "mmap", mmap_addr, parameters, 6, ®s) = =-1) Goto exit; Map_base = Ptrace_retval (®s); Gets the address of the target process dlopen function dlopen_addr = get_remote_addr (Target_pid, Linker_path, (void *) dlopen); Gets the address of the target process dlsym function dlsym_addr = get_remote_addr (Target_pid, Linker_path, (void *) dlsym); Gets the address of the target process dlclose function dlclose_addr = get_remote_addr (Target_pid, Linker_path, (void *) dlclose); Gets the address of the target process dlerror function dlerror_addr = Get_remoTe_addr (Target_pid, Linker_path, (void *) dlerror); Debug_print ("[+] Get imports:dlopen:%x, Dlsym:%x, Dlclose:%x, Dlerror:%x\n", Dlopen_addr, Dlsym_addr, DLCL OSE_ADDR, DLERROR_ADDR); printf ("Library path =%s\n", Library_path); Write Library_path data to the target process Ptrace_writedata (Target_pid, Map_base, Library_path, strlen (Library_path) + 1); Parameters[0] = map_base; PARAMETERS[1] = rtld_now| Rtld_global; Let the target process call the Dlopen function if (Ptrace_call_wrapper (Target_pid, "Dlopen", dlopen_addr, Parameters, 2, ®s) = =-1) Goto exit; void * Sohandle = Ptrace_retval (®s); #define Function_name_addr_offset 0x100 Ptrace_writedata (Target_pid, M Ap_base + Function_name_addr_offset, function_name, strlen (function_name) + 1); Parameters[0] = Sohandle; PARAMETERS[1] = map_base + function_name_addr_offset; Let the target process call the Dlsym function if (Ptrace_call_wrapper (Target_pid, "Dlsym", dlsym_addr, Parameters, 2, ®s) = =-1) got o exit; void* hook_entry_addr = Ptrace_retval (®s); Debug_print ("hook_entry_addr =%p\n", hook_entry_addr); #define Function_param_addr_offset 0x200 ptrace_writedata (t Arget_pid, Map_base + Function_param_addr_offset, PARAM, strlen (PARAM) + 1); Parameters[0] = map_base + function_param_addr_offset; Let the target process call the Hook_entry function if (Ptrace_call_wrapper (Target_pid, Function_name, hook_entry_addr, parameters, 1, ®s) = =-1) goto exit; printf ("Press ENTER to Dlclose and detach\n"); GetChar (); Parameters[0] = Sohandle; if (Ptrace_call_wrapper (Target_pid, "Dlclose", Dlclose, Parameters, 1, ®s) = =-1)//goto exit; /* Restore Recovery Register */Ptrace_setregs (target_pid, &original_regs); Unload target Process Ptrace_detach (TARGET_PID); ret = 0;exit:return ret;} int main (int argc, char** argv) {pid_t target_pid; Target_pid = find_pid_of ("com.estoty.game2048");//also can pass target PID or target process by param if ( -1 = = target_ PID) { printf ("Can ' t find the process\n"); return-1; }printf ("target_pid=%d argc=%d\n", TARGET_PID,ARGC); char* sopath= "/data/local/tmp/libpackage.so"; if (argc>1) { SOPATH=ARGV[1];} char* main_entry= "Main_entry"; if (argc>2) {main_entry=argv[2];} char* parameter= "parameter"; if (argc>3) {parameter=argv[3];} printf ("Inject_remote_process start\n"); Inject_remote_process (Target_pid, Sopath, main_entry, parameter, strlen (parameter)); return 0;}
Inject the target process, execute the injected code
1.attach on target process
Ptrace_attach (Target_pid)
2. Get the target process register and copy a save to restore the target process after the injection is complete
Ptrace_getregs (Target_pid, ®s)
3. Take the target process mmap function address
Get_remote_func_address (Target_pid, Libc_path, (void *) mmap);
4. Call the target process mmap function to allocate a piece of memory
Ptrace_call_wrapper (Target_pid, "mmap", target_mmap_addr, parameters, 6, ®s)
Get the memory address assigned by MMAP
uint8_t *target_mmap_base = Ptrace_retval (®s);
5. Call the target process Dlopen function load inject so
Take target process Dlopen function address
Get_remote_func_address (Target_pid, Linker_path, (void *) dlopen);
Write injected so address to target process
Ptrace_writedata (Target_pid, Target_mmap_base, Library_path,strlen (Library_path) + 1);
Calling functions via Ptrace
(Ptrace_call_wrapper (Target_pid, "Dlopen", target_dlopen_addr, parameters, 2,®s)
6. Call Dlsym to inject the address of the so library execution function
Address of the target process Dlsym function
Get_remote_func_address (Target_pid, Linker_path, (void *) dlsym);
Write the function name string into the target process
Ptrace_writedata (target_pid, Target_mmap_base + function_name_addr_offset,function_name, strlen (FUNCTION_NAME) + 1);
7. Call the hook function
Parameters required for writing functions
Ptrace_writedata (target_pid, Target_mmap_base + Function_param_addr_offset, Param,strlen (PARAM) + 1);
8. Call Dlclose Unload injection so
Get_remote_func_address (Target_pid, Linker_path, (void *) dlclose);
9. Recovery site
Ptrace_setregs (Target_pid, &original_regs);
10.detach
Ptrace_detach (TARGET_PID);
Android Process Injection Process