So injection (inject) in Android arm64 (AARCH64)-compatible with x86 and arm

Source: Internet
Author: User

Implements so injection (inject) in Android arm64 (AARCH64) and is compatible with x86 and arm. If not mistaken, this is the first public at home and abroad arm64 injection of Targeted complete information ~ ~

The code is based on Ariesjzj 's "soinject in Android (inject) and hooks"-for both x86 and arm , which adds support for arm64. (There are currently 64 Android phones already started)

Similarly, the code is composed of the following three files in Jni.

Inject.c
Android.mk
Application.mk

Among them android.mk, the APPLICATION.MK

App_abi: = arm64-v8a
Inject.c as follows:

#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> #include <sys/uio.h> #if defined (__i386__) #define PT_REGS user_regs_struct  #elif defined (__aarch64__) #define PT_REGS user_pt_regs #define Uregsregs#define arm_pcpc#define arm_spsp#define Arm_cpsrpstate#define arm_lrregs[30] #define ARM_R0REGS[0] #define PTRACE_GETREGS ptrace_getregset#define PTRACE_ Setregs ptrace_setregset#endif #define ENABLE_DEBUG 1 #if enable_debug #define LOG_TAG "INJECT" #defi  Ne logd (fmt, args ...) __android_log_print (Android_log_debug,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) #if defined (__aarch64__) const char *libc_path = "/syste    M/lib64/libc.so ";    const char *linker_path = "/system/bin/linker64";    #elseconst char *libc_path = "/system/lib/libc.so";    const char *linker_path = "/system/bin/linker";        #endif int Ptrace_readdata (pid_t pid, uint8_t *src, uint8_t *buf, size_t size) {Long I, j, remain;           uint8_t *laddr;    size_t bytes_width = sizeof (long);            Union u {long val;        Char Chars[bytes_width];            } D;        j = size/bytes_width;            remain = size% Bytes_width;            LADDR = BUF;            for (i = 0; i < J; i + +) {D.val = Ptrace (ptrace_peektext, PID, SRC, 0);            memcpy (Laddr, D.chars, bytes_width);            src + = bytes_width;        Laddr + = Bytes_width; } if (remain > 0) {d.val = Ptrace (Ptrace_peektEXT, PID, SRC, 0);        memcpy (LADDR, D.chars, remain);    } return 0;        } int Ptrace_writedata (pid_t pid, uint8_t *dest, uint8_t *data, size_t size) {Long I, j, remain;        uint8_t *laddr;    size_t bytes_width = sizeof (long);            Union u {long val;        Char Chars[bytes_width];            } D;        j = size/bytes_width;            remain = size% Bytes_width;            LADDR = data;            for (i = 0; i < J; i + +) {memcpy (D.chars, laddr, bytes_width);                Ptrace (Ptrace_poketext, PID, dest, D.val);            Dest + = Bytes_width;        Laddr + = Bytes_width;            } 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__) | | Defined (__AARCh64__) int Ptrace_call (pid_t pid, uintptr_t addr, long *params, int num_params, struct pt_regs* regs) {int i;    #if defined (__arm__) int num_param_registers = 4; #elif defined (__aarch64__) int num_param_registers = 8; #endif        for (i = 0; i < num_params && i < num_param_registers; i + +) {Regs->uregs[i] = params[i]; }////push remained params onto stack//if (I < num_params) {regs-            &GT;ARM_SP-= (num_params-i) * sizeof (long);        Ptrace_writedata (PID, (void *) REGS-&GT;ARM_SP, (uint8_t *) ¶ms[i], (num_params-i) * sizeof (long));        } regs->arm_pc = addr;            if (REGS-&GT;ARM_PC & 1) {/* thumb */regs->arm_pc &= (~1U);        REGS-&GT;ARM_CPSR |= Cpsr_t_mask;        } else {/* arm */REGS-&GT;ARM_CPSR &= ~cpsr_t_mask;                } REGS-&GT;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, uintptr_t addr, long *params, int num_params, struct user_regs        _struct * regs) {regs->esp-= (num_params) * sizeof (long);            Ptrace_writedata (PID, (void *) REGS-&GT;ESP, (uint8_t *) params, (num_params) * sizeof (long));        Long tmp_addr = 0x00;        Regs->esp = sizeof (long);             Ptrace_writedata (PID, REGS-&GT;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 int ptrace_getregs (pid_t pid, struct Pt_regs * regs) {#if de    Fined (__aarch64__) int regset = nt_prstatus;struct Iovec iovec;iovec.iov_base = Regs;iovec.iov_len = sizeof (*REGS); if (Ptrace (Ptrace_getregset, PID, (void*) Regset, &iovec) < 0) {perror ("Ptrace_getregs:can not get Regi           Ster values ");         printf ("Io%llx,%d", Iovec.iov_base, Iovec.iov_len);        return-1;   } return 0; #else if (Ptrace (Ptrace_getregs, PID, NULL, Regs) < 0) {perror ("Ptrace_getregs:can not get register Val            UEs ");        return-1; } return 0;  #endif} int Ptrace_setregs (pid_t pid, struct Pt_regs * regs) {#if defined (__aarch64__) int regset =    Nt_prstatus;struct Iovec iovec;iovec.iov_base = Regs;iovec.iov_len = sizeof (*REGS); if (Ptrace (Ptrace_setregset, PID, (void*) Regset, &iovec) < 0) {perror ("Ptrace_setregs:can not get Regi            Ster values ");        return-1;   } return 0; #else if (Ptrace (Ptrace_setregs, PID, NULL, Regs) < 0) {perror ("Ptrace_setregs:can not set register Val            UEs ");        return-1;   } return 0;            #endif} int ptrace_continue (pid_t pid) {if (Ptrace (Ptrace_cont, PID, NULL, 0) < 0) {            Perror ("Ptrace_cont");        return-1;    } return 0; } int Ptrace_attach (pid_t pid) {if (Ptrace (Ptrace_attach, PID, NULL, 0) < 0) {perror ("ptr            Ace_attach ");        return-1;        } int status = 0; Waitpid (PID, &amP;status, wuntraced);    return 0; } int Ptrace_detach (pid_t pid) {if (Ptrace (Ptrace_detach, PID, NULL, 0) < 0) {perror ("ptr            Ace_detach ");        return-1;    } return 0;        } 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 = Strtoull (PCH, NULL, 16);                if (addr = = 0x8000) addr = 0;        Break        }} fclose (FP);    } return (void *) addr; } void* get_remote_addr (pid_t target_pid, const char* module_name, void* local_addr) {void* Local_handle            , *remote_handle;        Local_handle = Get_module_base ( -1, module_name);            Remote_handle = Get_module_base (Target_pid, module_name);            Debug_print ("[+] get_remote_addr:local[%llx], remote[%llx]\n", Local_handle, Remote_handle);        void * Ret_addr = (void *) ((uintptr_t) local_addr + (uintptr_t) Remote_handle-(uintptr_t) local_handle);        #if defined (__i386__) if (!strcmp (Module_name, Libc_path)) {ret_addr + = 2;    } #endif return ret_addr;        } 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; } uint64_t ptrace_retval (struct Pt_regs * regs) {#if defined (__arm__) | | defined (__AARCH64__) return regs    ->arm_r0;    #elif defined (__i386__) return regs->eax; #else #error "not supported" #endif} uint64_t ptrace_ip (struct pt_regs * regs)   {#if defined (__arm__) | | defined (__AARCH64__) 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, VO ID * func_addr, long * parameters, int param_num, struct pt_regs * regs) {debug_print ("[+] calling%s in Targe        T process.\n ", func_name);            if (Ptrace_call (Target_pid, (uintptr_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=%llx, PC=%LLX \ n", Func_name, Ptrace_retval        (regs), Ptrace_ip (regs));    return 0; } int inject_remote_process (pid_t target_pid, const char *library_path, const char *function_name, const char *para        M, size_t param_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;            Long parameters[10];            Debug_print ("[+] injecting process:%d\n", target_pid);            if (Ptrace_attach (target_pid) = =-1) goto exit;            if (Ptrace_getregs (target_pid, &regs) = =-1) goto exit;            /* Save Original Registers */memcpy (&original_regs, &regs, sizeof (regs));        MMAP_ADDR = Get_remote_addr (Target_pid, Libc_path, (void *) mmap);            Debug_print ("[+] Remote mmap address:%llx\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 if (Ptrace_call_wrapper (Target_pid, "mmap", mmap_addr, parameters, 6, &regs) = =-1) got            o exit;          Map_base = Ptrace_retval (&regs);        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);            DLERROR_ADDR = Get_remote_addr (Target_pid, Linker_path, (void *) dlerror); Debug_print ("[+] Get imports:dlopen:%llx, Dlsym:%llx, Dlclose:%llx, Dlerror:%llx\n", Dlopen_addr, Dlsy            M_addr, DLCLOSE_ADDR, dlerror_addr);        printf ("Library path =%s\n", Library_path);              Ptrace_writedata (Target_pid, Map_base, Library_path, strlen (Library_path) + 1);           Parameters[0] = map_base; PARAMETERS[1] = rtld_now|             Rtld_global; if (PTRACE_CALL_WRApper (Target_pid, "Dlopen", dlopen_addr, Parameters, 2, &regs) = =-1) goto exit;        void * Sohandle = Ptrace_retval (&regs); if (!sohandle) {if (Ptrace_call_wrapper (Target_pid, "Dlerror", dlerror_addr, 0, 0, &regs) = =-1) Goto EX                It      uint8_t *errret = Ptrace_retval (&regs);    uint8_t errbuf[100];  Ptrace_readdata (Target_pid, Errret, ERRBUF, 100); } #define Function_name_addr_offset 0x100 ptrace_writedata (target_pid, Map_base + function_name_addr_o        Ffset, Function_name, strlen (function_name) + 1);           Parameters[0] = Sohandle;             PARAMETERS[1] = map_base + function_name_addr_offset;            if (Ptrace_call_wrapper (Target_pid, "Dlsym", dlsym_addr, Parameters, 2, &regs) = =-1) goto exit;        void * Hook_entry_addr = Ptrace_retval (&regs);        Debug_print ("hook_entry_addr =%p\n", hook_entry_addr);       #define Function_param_addr_offset 0x200 Ptrace_writedata (target_pid, Map_base + Function_param_addr_offset, PARAM, strlen (PARAM) + 1);            Parameters[0] = map_base + function_param_addr_offset;                if (Ptrace_call_wrapper (Target_pid, "Hook_entry", hook_entry_addr, Parameters, 1, &regs) = =-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, &regs) = =-1) goto exit;        /* Restore */Ptrace_setregs (target_pid, &original_regs);        Ptrace_detach (TARGET_PID);        ret = 0;    Exit:return ret;        } int main (int argc, char** argv) {pid_t target_pid;    Target_pid = find_pid_of ("System_server");          if ( -1 = = target_pid) {printf ("Can ' t find the process\n");      return-1;        }//target_pid = find_pid_of ("/data/test"); Inject_remote_process (Target_pid, "/data/libhello.so "," Hook_entry "," I ' M parameter! ", strlen (" I ' M parameter! "));  return 0;     }

In addition, it is used toLibhello. So, the code is basically the same, except that the build arm64 is also specified in Application.mk.
App_abi: = arm64-v8a

Finally, it should be noted that the current arm64 mobile phones should be Android 5.0+, may be due to SELinux authority control caused by injection failure, such as the system_server in the example will fail, but inject calendar no problem.

You can temporarily turn off SELinux (execute Setenforce 0), and you need to configure SELinux for resolution.

So injection (inject) in Android arm64 (AARCH64)-compatible with x86 and arm

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.