开心六月综合激情婷婷|欧美精品成人动漫二区|国产中文字幕综合色|亚洲人在线成视频

    1. 
      
        <b id="zqfy3"><legend id="zqfy3"><fieldset id="zqfy3"></fieldset></legend></b>
          <ul id="zqfy3"></ul>
          <blockquote id="zqfy3"><strong id="zqfy3"><dfn id="zqfy3"></dfn></strong></blockquote>
          <blockquote id="zqfy3"><legend id="zqfy3"></legend></blockquote>
          打開APP
          userphoto
          未登錄

          開通VIP,暢享免費電子書等14項超值服

          開通VIP
          Android中的so注入(inject)和掛鉤(hook)
          分類: Android 2013-08-11 16:27 5529人閱讀 評論(23) 收藏 舉報

          對于Android for arm上的so注入(inject)和掛鉤(hook),網(wǎng)上已有牛人給出了代碼-libinject(http://bbs.pediy.com/showthread.php?t=141355)。由于實現(xiàn)中的ptrace函數(shù)是依賴于平臺的,所以不經(jīng)改動只能用于arm平臺。本文將之擴展了一下,使它能夠通用于Android的x86和arm平臺。Arm平臺部分基本重用了libinject中的代碼,其中因為匯編不好移植且容易出錯,所以把shellcode.s用ptrace_call替換掉了,另外保留了mmap,用來傳字符串參數(shù),當然也可以通過棧來傳,但棧里和其它東西混一起,一弄不好就會隔兒了,所以還是保險點好。最后注意設(shè)備要root。

          首先創(chuàng)建目錄及文件:

          jni
              inject.c
              Android.mk
              Application.mk

          inject.c:

          1. #include <stdio.h>    
          2. #include <stdlib.h>    
          3. #include <asm/user.h>    
          4. #include <asm/ptrace.h>    
          5. #include <sys/ptrace.h>    
          6. #include <sys/wait.h>    
          7. #include <sys/mman.h>    
          8. #include <dlfcn.h>    
          9. #include <dirent.h>    
          10. #include <unistd.h>    
          11. #include <string.h>    
          12. #include <elf.h>    
          13. #include <android/log.h>    
          14.     
          15. #if defined(__i386__)    
          16. #define pt_regs         user_regs_struct    
          17. #endif    
          18.     
          19. #define ENABLE_DEBUG 1    
          20.     
          21. #if ENABLE_DEBUG    
          22. #define  LOG_TAG "INJECT"    
          23. #define  LOGD(fmt, args...)  __android_log_print(ANDROID_LOG_DEBUG,LOG_TAG, fmt, ##args)    
          24. #define DEBUG_PRINT(format,args...) \    
          25.     LOGD(format, ##args)    
          26. #else    
          27. #define DEBUG_PRINT(format,args...)    
          28. #endif    
          29.     
          30. #define CPSR_T_MASK     ( 1u << 5 )    
          31.     
          32. const char *libc_path = "/system/lib/libc.so";    
          33. const char *linker_path = "/system/bin/linker";    
          34.     
          35. int ptrace_readdata(pid_t pid,  uint8_t *src, uint8_t *buf, size_t size)    
          36. {    
          37.     uint32_t i, j, remain;    
          38.     uint8_t *laddr;    
          39.     
          40.     union u {    
          41.         long val;    
          42.         char chars[sizeof(long)];    
          43.     } d;    
          44.     
          45.     j = size / 4;    
          46.     remain = size % 4;    
          47.     
          48.     laddr = buf;    
          49.     
          50.     for (i = 0; i < j; i ++) {    
          51.         d.val = ptrace(PTRACE_PEEKTEXT, pid, src, 0);    
          52.         memcpy(laddr, d.chars, 4);    
          53.         src += 4;    
          54.         laddr += 4;    
          55.     }    
          56.     
          57.     if (remain > 0) {    
          58.         d.val = ptrace(PTRACE_PEEKTEXT, pid, src, 0);    
          59.         memcpy(laddr, d.chars, remain);    
          60.     }    
          61.     
          62.     return 0;    
          63. }    
          64.     
          65. int ptrace_writedata(pid_t pid, uint8_t *dest, uint8_t *data, size_t size)    
          66. {    
          67.     uint32_t i, j, remain;    
          68.     uint8_t *laddr;    
          69.     
          70.     union u {    
          71.         long val;    
          72.         char chars[sizeof(long)];    
          73.     } d;    
          74.     
          75.     j = size / 4;    
          76.     remain = size % 4;    
          77.     
          78.     laddr = data;    
          79.     
          80.     for (i = 0; i < j; i ++) {    
          81.         memcpy(d.chars, laddr, 4);    
          82.         ptrace(PTRACE_POKETEXT, pid, dest, d.val);    
          83.     
          84.         dest  += 4;    
          85.         laddr += 4;    
          86.     }    
          87.     
          88.     if (remain > 0) {    
          89.         d.val = ptrace(PTRACE_PEEKTEXT, pid, dest, 0);    
          90.         for (i = 0; i < remain; i ++) {    
          91.             d.chars[i] = *laddr ++;    
          92.         }    
          93.     
          94.         ptrace(PTRACE_POKETEXT, pid, dest, d.val);    
          95.     }    
          96.     
          97.     return 0;    
          98. }    
          99.     
          100. #if defined(__arm__)    
          101. int ptrace_call(pid_t pid, uint32_t addr, long *params, uint32_t num_params, struct pt_regs* regs)    
          102. {    
          103.     uint32_t i;    
          104.     for (i = 0; i < num_params && i < 4; i ++) {    
          105.         regs->uregs[i] = params[i];    
          106.     }    
          107.     
          108.     //    
          109.     // push remained params onto stack    
          110.     //    
          111.     if (i < num_params) {    
          112.         regs->ARM_sp -= (num_params - i) * sizeof(long) ;    
          113.         ptrace_writedata(pid, (void *)regs->ARM_sp, (uint8_t *)&params[i], (num_params - i) * sizeof(long));    
          114.     }    
          115.     
          116.     regs->ARM_pc = addr;    
          117.     if (regs->ARM_pc & 1) {    
          118.         /* thumb */    
          119.         regs->ARM_pc &= (~1u);    
          120.         regs->ARM_cpsr |= CPSR_T_MASK;    
          121.     } else {    
          122.         /* arm */    
          123.         regs->ARM_cpsr &= ~CPSR_T_MASK;    
          124.     }    
          125.     
          126.     regs->ARM_lr = 0;        
          127.     
          128.     if (ptrace_setregs(pid, regs) == -1     
          129.             || ptrace_continue(pid) == -1) {    
          130.         printf("error\n");    
          131.         return -1;    
          132.     }    
          133.     
          134.     int stat = 0;  
          135.     waitpid(pid, &stat, WUNTRACED);  
          136.     while (stat != 0xb7f) {  
          137.         if (ptrace_continue(pid) == -1) {  
          138.             printf("error\n");  
          139.             return -1;  
          140.         }  
          141.         waitpid(pid, &stat, WUNTRACED);  
          142.     }  
          143.     
          144.     return 0;    
          145. }    
          146.     
          147. #elif defined(__i386__)    
          148. long ptrace_call(pid_t pid, uint32_t addr, long *params, uint32_t num_params, struct user_regs_struct * regs)    
          149. {    
          150.     regs->esp -= (num_params) * sizeof(long) ;    
          151.     ptrace_writedata(pid, (void *)regs->esp, (uint8_t *)params, (num_params) * sizeof(long));    
          152.     
          153.     long tmp_addr = 0x00;    
          154.     regs->esp -= sizeof(long);    
          155.     ptrace_writedata(pid, regs->esp, (char *)&tmp_addr, sizeof(tmp_addr));     
          156.     
          157.     regs->eip = addr;    
          158.     
          159.     if (ptrace_setregs(pid, regs) == -1     
          160.             || ptrace_continue( pid) == -1) {    
          161.         printf("error\n");    
          162.         return -1;    
          163.     }    
          164.     
          165.     int stat = 0;  
          166.     waitpid(pid, &stat, WUNTRACED);  
          167.     while (stat != 0xb7f) {  
          168.         if (ptrace_continue(pid) == -1) {  
          169.             printf("error\n");  
          170.             return -1;  
          171.         }  
          172.         waitpid(pid, &stat, WUNTRACED);  
          173.     }  
          174.     
          175.     return 0;    
          176. }    
          177. #else     
          178. #error "Not supported"    
          179. #endif    
          180.     
          181. int ptrace_getregs(pid_t pid, struct pt_regs * regs)    
          182. {    
          183.     if (ptrace(PTRACE_GETREGS, pid, NULL, regs) < 0) {    
          184.         perror("ptrace_getregs: Can not get register values");    
          185.         return -1;    
          186.     }    
          187.     
          188.     return 0;    
          189. }    
          190.     
          191. int ptrace_setregs(pid_t pid, struct pt_regs * regs)    
          192. {    
          193.     if (ptrace(PTRACE_SETREGS, pid, NULL, regs) < 0) {    
          194.         perror("ptrace_setregs: Can not set register values");    
          195.         return -1;    
          196.     }    
          197.     
          198.     return 0;    
          199. }    
          200.     
          201. int ptrace_continue(pid_t pid)    
          202. {    
          203.     if (ptrace(PTRACE_CONT, pid, NULL, 0) < 0) {    
          204.         perror("ptrace_cont");    
          205.         return -1;    
          206.     }    
          207.     
          208.     return 0;    
          209. }    
          210.     
          211. int ptrace_attach(pid_t pid)    
          212. {    
          213.     if (ptrace(PTRACE_ATTACH, pid, NULL, 0) < 0) {    
          214.         perror("ptrace_attach");    
          215.         return -1;    
          216.     }    
          217.     
          218.     int status = 0;    
          219.     waitpid(pid, &status , WUNTRACED);    
          220.     
          221.     return 0;    
          222. }    
          223.     
          224. int ptrace_detach(pid_t pid)    
          225. {    
          226.     if (ptrace(PTRACE_DETACH, pid, NULL, 0) < 0) {    
          227.         perror("ptrace_detach");    
          228.         return -1;    
          229.     }    
          230.     
          231.     return 0;    
          232. }    
          233.     
          234. void* get_module_base(pid_t pid, const char* module_name)    
          235. {    
          236.     FILE *fp;    
          237.     long addr = 0;    
          238.     char *pch;    
          239.     char filename[32];    
          240.     char line[1024];    
          241.     
          242.     if (pid < 0) {    
          243.         /* self process */    
          244.         snprintf(filename, sizeof(filename), "/proc/self/maps", pid);    
          245.     } else {    
          246.         snprintf(filename, sizeof(filename), "/proc/%d/maps", pid);    
          247.     }    
          248.     
          249.     fp = fopen(filename, "r");    
          250.     
          251.     if (fp != NULL) {    
          252.         while (fgets(line, sizeof(line), fp)) {    
          253.             if (strstr(line, module_name)) {    
          254.                 pch = strtok( line, "-" );    
          255.                 addr = strtoul( pch, NULL, 16 );    
          256.     
          257.                 if (addr == 0x8000)    
          258.                     addr = 0;    
          259.     
          260.                 break;    
          261.             }    
          262.         }    
          263.     
          264.         fclose(fp) ;    
          265.     }    
          266.     
          267.     return (void *)addr;    
          268. }    
          269.     
          270. void* get_remote_addr(pid_t target_pid, const char* module_name, void* local_addr)    
          271. {    
          272.     void* local_handle, *remote_handle;    
          273.     
          274.     local_handle = get_module_base(-1, module_name);    
          275.     remote_handle = get_module_base(target_pid, module_name);    
          276.     
          277.     DEBUG_PRINT("[+] get_remote_addr: local[%x], remote[%x]\n", local_handle, remote_handle);    
          278.     
          279.     void * ret_addr = (void *)((uint32_t)local_addr + (uint32_t)remote_handle - (uint32_t)local_handle);    
          280.     
          281. #if defined(__i386__)    
          282.     if (!strcmp(module_name, libc_path)) {    
          283.         ret_addr += 2;    
          284.     }    
          285. #endif    
          286.     return ret_addr;    
          287. }    
          288.     
          289. int find_pid_of(const char *process_name)    
          290. {    
          291.     int id;    
          292.     pid_t pid = -1;    
          293.     DIR* dir;    
          294.     FILE *fp;    
          295.     char filename[32];    
          296.     char cmdline[256];    
          297.     
          298.     struct dirent * entry;    
          299.     
          300.     if (process_name == NULL)    
          301.         return -1;    
          302.     
          303.     dir = opendir("/proc");    
          304.     if (dir == NULL)    
          305.         return -1;    
          306.     
          307.     while((entry = readdir(dir)) != NULL) {    
          308.         id = atoi(entry->d_name);    
          309.         if (id != 0) {    
          310.             sprintf(filename, "/proc/%d/cmdline", id);    
          311.             fp = fopen(filename, "r");    
          312.             if (fp) {    
          313.                 fgets(cmdline, sizeof(cmdline), fp);    
          314.                 fclose(fp);    
          315.     
          316.                 if (strcmp(process_name, cmdline) == 0) {    
          317.                     /* process found */    
          318.                     pid = id;    
          319.                     break;    
          320.                 }    
          321.             }    
          322.         }    
          323.     }    
          324.     
          325.     closedir(dir);    
          326.     return pid;    
          327. }    
          328.     
          329. long ptrace_retval(struct pt_regs * regs)    
          330. {    
          331. #if defined(__arm__)    
          332.     return regs->ARM_r0;    
          333. #elif defined(__i386__)    
          334.     return regs->eax;    
          335. #else    
          336. #error "Not supported"    
          337. #endif    
          338. }    
          339.     
          340. long ptrace_ip(struct pt_regs * regs)    
          341. {    
          342. #if defined(__arm__)    
          343.     return regs->ARM_pc;    
          344. #elif defined(__i386__)    
          345.     return regs->eip;    
          346. #else    
          347. #error "Not supported"    
          348. #endif    
          349. }    
          350.     
          351. int ptrace_call_wrapper(pid_t target_pid, const char * func_name, void * func_addr, long * parameters, int param_num, struct pt_regs * regs)     
          352. {    
          353.     DEBUG_PRINT("[+] Calling %s in target process.\n", func_name);    
          354.     if (ptrace_call(target_pid, (uint32_t)func_addr, parameters, param_num, regs) == -1)    
          355.         return -1;    
          356.     
          357.     if (ptrace_getregs(target_pid, regs) == -1)    
          358.         return -1;    
          359.     DEBUG_PRINT("[+] Target process returned from %s, return value=%x, pc=%x \n",     
          360.             func_name, ptrace_retval(regs), ptrace_ip(regs));    
          361.     return 0;    
          362. }    
          363.     
          364. int inject_remote_process(pid_t target_pid, const char *library_path, const char *function_name, const char *param, size_t param_size)    
          365. {    
          366.     int ret = -1;    
          367.     void *mmap_addr, *dlopen_addr, *dlsym_addr, *dlclose_addr, *dlerror_addr;    
          368.     void *local_handle, *remote_handle, *dlhandle;    
          369.     uint8_t *map_base = 0;    
          370.     uint8_t *dlopen_param1_ptr, *dlsym_param2_ptr, *saved_r0_pc_ptr, *inject_param_ptr, *remote_code_ptr, *local_code_ptr;    
          371.     
          372.     struct pt_regs regs, original_regs;    
          373.     extern uint32_t _dlopen_addr_s, _dlopen_param1_s, _dlopen_param2_s, _dlsym_addr_s, \    
          374.         _dlsym_param2_s, _dlclose_addr_s, _inject_start_s, _inject_end_s, _inject_function_param_s, \    
          375.         _saved_cpsr_s, _saved_r0_pc_s;    
          376.     
          377.     uint32_t code_length;    
          378.     long parameters[10];    
          379.     
          380.     DEBUG_PRINT("[+] Injecting process: %d\n", target_pid);    
          381.     
          382.     if (ptrace_attach(target_pid) == -1)    
          383.         goto exit;    
          384.     
          385.     if (ptrace_getregs(target_pid, &regs) == -1)    
          386.         goto exit;    
          387.     
          388.     /* save original registers */    
          389.     memcpy(&original_regs, &regs, sizeof(regs));    
          390.     
          391.     mmap_addr = get_remote_addr(target_pid, libc_path, (void *)mmap);    
          392.     DEBUG_PRINT("[+] Remote mmap address: %x\n", mmap_addr);    
          393.     
          394.     /* call mmap */    
          395.     parameters[0] = 0;  // addr    
          396.     parameters[1] = 0x4000; // size    
          397.     parameters[2] = PROT_READ | PROT_WRITE | PROT_EXEC;  // prot    
          398.     parameters[3] =  MAP_ANONYMOUS | MAP_PRIVATE; // flags    
          399.     parameters[4] = 0; //fd    
          400.     parameters[5] = 0; //offset    
          401.     
          402.     if (ptrace_call_wrapper(target_pid, "mmap", mmap_addr, parameters, 6, &regs) == -1)    
          403.         goto exit;    
          404.     
          405.     map_base = ptrace_retval(&regs);    
          406.     
          407.     dlopen_addr = get_remote_addr( target_pid, linker_path, (void *)dlopen );    
          408.     dlsym_addr = get_remote_addr( target_pid, linker_path, (void *)dlsym );    
          409.     dlclose_addr = get_remote_addr( target_pid, linker_path, (void *)dlclose );    
          410.     dlerror_addr = get_remote_addr( target_pid, linker_path, (void *)dlerror );    
          411.     
          412.     DEBUG_PRINT("[+] Get imports: dlopen: %x, dlsym: %x, dlclose: %x, dlerror: %x\n",    
          413.             dlopen_addr, dlsym_addr, dlclose_addr, dlerror_addr);    
          414.     
          415.     printf("library path = %s\n", library_path);    
          416.     ptrace_writedata(target_pid, map_base, library_path, strlen(library_path) + 1);    
          417.     
          418.     parameters[0] = map_base;       
          419.     parameters[1] = RTLD_NOW| RTLD_GLOBAL;     
          420.     
          421.     if (ptrace_call_wrapper(target_pid, "dlopen", dlopen_addr, parameters, 2, &regs) == -1)    
          422.         goto exit;    
          423.     
          424.     void * sohandle = ptrace_retval(&regs);    
          425.     
          426. #define FUNCTION_NAME_ADDR_OFFSET       0x100    
          427.     ptrace_writedata(target_pid, map_base + FUNCTION_NAME_ADDR_OFFSET, function_name, strlen(function_name) + 1);    
          428.     parameters[0] = sohandle;       
          429.     parameters[1] = map_base + FUNCTION_NAME_ADDR_OFFSET;     
          430.     
          431.     if (ptrace_call_wrapper(target_pid, "dlsym", dlsym_addr, parameters, 2, &regs) == -1)    
          432.         goto exit;    
          433.     
          434.     void * hook_entry_addr = ptrace_retval(&regs);    
          435.     DEBUG_PRINT("hook_entry_addr = %p\n", hook_entry_addr);    
          436.     
          437. #define FUNCTION_PARAM_ADDR_OFFSET      0x200    
          438.     ptrace_writedata(target_pid, map_base + FUNCTION_PARAM_ADDR_OFFSET, param, strlen(param) + 1);    
          439.     parameters[0] = map_base + FUNCTION_PARAM_ADDR_OFFSET;      
          440.   
          441.     if (ptrace_call_wrapper(target_pid, "hook_entry", hook_entry_addr, parameters, 1, &regs) == -1)    
          442.         goto exit;        
          443.     
          444.     printf("Press enter to dlclose and detach\n");    
          445.     getchar();    
          446.     parameters[0] = sohandle;       
          447.     
          448.     if (ptrace_call_wrapper(target_pid, "dlclose", dlclose, parameters, 1, &regs) == -1)    
          449.         goto exit;    
          450.     
          451.     /* restore */    
          452.     ptrace_setregs(target_pid, &original_regs);    
          453.     ptrace_detach(target_pid);    
          454.     ret = 0;    
          455.     
          456. exit:    
          457.     return ret;    
          458. }    
          459.     
          460. int main(int argc, char** argv) {    
          461.     pid_t target_pid;    
          462.     target_pid = find_pid_of("/system/bin/surfaceflinger");    
          463.     if (-1 == target_pid) {  
          464.         printf("Can't find the process\n");  
          465.         return -1;  
          466.     }  
          467.     //target_pid = find_pid_of("/data/test");    
          468.     inject_remote_process(target_pid, "/data/libhello.so""hook_entry",  "I'm parameter!", strlen("I'm parameter!"));    
          469.     return 0;  
          470. }    
          注意上面的/system/bin/surfaceflinger進程我隨手寫的,你的設(shè)備上不一定有。沒有的話挑其它的也行,前提是ps命令里能找到。
          Android.mk:
          1. LOCAL_PATH := $(call my-dir)  
          2.   
          3. include $(CLEAR_VARS)  
          4. LOCAL_MODULE := inject   
          5. LOCAL_SRC_FILES := inject.c   
          6.   
          7. #shellcode.s  
          8.   
          9. LOCAL_LDLIBS += -L$(SYSROOT)/usr/lib -llog  
          10.   
          11. #LOCAL_FORCE_STATIC_EXECUTABLE := true  
          12.   
          13. include $(BUILD_EXECUTABLE)  
          Application.mk:
          1. APP_ABI := x86 armeabi-v7a  

          運行nkd-build編譯成生x86和arm平臺下的可執(zhí)行文件:

          1. jzj@jzj-laptop:~/workspace/inject_hook/inject_jni$ ndk-build  
          2. Install        : inject => libs/x86/inject  
          3. Install        : inject => libs/armeabi-v7a/inject  

          再來生成要注入的so,創(chuàng)建目錄及文件:

          jni
              hello.c
              Android.mk
              Application.mk

          hello.c:

          1. #include <unistd.h>  
          2. #include <stdio.h>  
          3. #include <stdlib.h>  
          4. #include <android/log.h>  
          5. #include <elf.h>  
          6. #include <fcntl.h>  
          7.   
          8. #define LOG_TAG "DEBUG"  
          9. #define LOGD(fmt, args...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, fmt, ##args)    
          10.   
          11. int hook_entry(char * a){  
          12.     LOGD("Hook success, pid = %d\n", getpid());  
          13.     LOGD("Hello %s\n", a);  
          14.     return 0;  
          15. }  
          Android.mk:
          1. LOCAL_PATH := $(call my-dir)  
          2.   
          3. include $(CLEAR_VARS)  
          4.   
          5. LOCAL_LDLIBS += -L$(SYSROOT)/usr/lib -llog   
          6. #LOCAL_ARM_MODE := arm  
          7. LOCAL_MODULE    := hello  
          8. LOCAL_SRC_FILES := hello.c  
          9. include $(BUILD_SHARED_LIBRARY)  

          Application.mk:
          1. APP_ABI := x86 armeabi-v7a  
          運行nkd-build編譯成生x86和arm平臺下的so:
          1. jzj@jzj-laptop:~/workspace/inject_hook/hook_so_simple$ ndk-build   
          2. Install        : libhello.so => libs/x86/libhello.so  
          3. Install        : libhello.so => libs/armeabi-v7a/libhello.so  

          然后就可以跑起來試試了,連接root過的Android設(shè)備或者打開模擬器。將inject和libhello.so拷入設(shè)備,設(shè)執(zhí)行權(quán)限,執(zhí)行:


          先看看被注入進程(surfaceflinger)的mmap,可以看到我們的so已經(jīng)被加載了,緊接著的那一塊就是我們mmap出來的:

          從logcat中也可以看到so注入成功,并且以被注入進程的身份執(zhí)行了so中的代碼:


          簡單的注入成功,現(xiàn)在我們再來做一個實驗,就是應(yīng)用這套機制來截獲surfaceflinger中的eglSwapBuffers調(diào)用,然后用我們自己的函數(shù)來替換掉原來的eglSwapBuffers調(diào)用。關(guān)于截系統(tǒng)中的函數(shù)調(diào)用網(wǎng)上有例子http://bbs.pediy.com/showthread.php?t=157419,這里依葫蘆畫瓢。首先將hello.c改下:

          1. #include <unistd.h>  
          2. #include <stdio.h>  
          3. #include <stdlib.h>  
          4. #include <android/log.h>  
          5. #include <EGL/egl.h>  
          6. #include <GLES/gl.h>  
          7. #include <elf.h>  
          8. #include <fcntl.h>  
          9. #include <sys/mman.h>  
          10.   
          11. #define LOG_TAG "DEBUG"  
          12. #define LOGD(fmt, args...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, fmt, ##args)    
          13.   
          14. EGLBoolean (*old_eglSwapBuffers)(EGLDisplay dpy, EGLSurface surf) = -1;  
          15.   
          16. EGLBoolean new_eglSwapBuffers(EGLDisplay dpy, EGLSurface surface)  
          17. {  
          18.     LOGD("New eglSwapBuffers\n");  
          19.     if (old_eglSwapBuffers == -1)  
          20.         LOGD("error\n");  
          21.     return old_eglSwapBuffers(dpy, surface);  
          22. }  
          23.   
          24. void* get_module_base(pid_t pid, const char* module_name)  
          25. {  
          26.     FILE *fp;  
          27.     long addr = 0;  
          28.     char *pch;  
          29.     char filename[32];  
          30.     char line[1024];  
          31.   
          32.     if (pid < 0) {  
          33.         /* self process */  
          34.         snprintf(filename, sizeof(filename), "/proc/self/maps", pid);  
          35.     } else {  
          36.         snprintf(filename, sizeof(filename), "/proc/%d/maps", pid);  
          37.     }  
          38.   
          39.     fp = fopen(filename, "r");  
          40.   
          41.     if (fp != NULL) {  
          42.         while (fgets(line, sizeof(line), fp)) {  
          43.             if (strstr(line, module_name)) {  
          44.                 pch = strtok( line, "-" );  
          45.                 addr = strtoul( pch, NULL, 16 );  
          46.   
          47.                 if (addr == 0x8000)  
          48.                     addr = 0;  
          49.   
          50.                 break;  
          51.             }  
          52.         }  
          53.   
          54.         fclose(fp) ;  
          55.     }  
          56.   
          57.     return (void *)addr;  
          58. }  
          59.   
          60. #define LIBSF_PATH  "/system/lib/libsurfaceflinger.so"    
          61. int hook_eglSwapBuffers()    
          62. {    
          63.     old_eglSwapBuffers = eglSwapBuffers;    
          64.     LOGD("Orig eglSwapBuffers = %p\n", old_eglSwapBuffers);    
          65.     void * base_addr = get_module_base(getpid(), LIBSF_PATH);    
          66.     LOGD("libsurfaceflinger.so address = %p\n", base_addr);    
          67.   
          68.     int fd;    
          69.     fd = open(LIBSF_PATH, O_RDONLY);    
          70.     if (-1 == fd) {    
          71.         LOGD("error\n");    
          72.         return -1;    
          73.     }    
          74.   
          75.     Elf32_Ehdr ehdr;    
          76.     read(fd, &ehdr, sizeof(Elf32_Ehdr));    
          77.   
          78.     unsigned long shdr_addr = ehdr.e_shoff;      
          79.     int shnum = ehdr.e_shnum;      
          80.     int shent_size = ehdr.e_shentsize;      
          81.     unsigned long stridx = ehdr.e_shstrndx;      
          82.   
          83.     Elf32_Shdr shdr;    
          84.     lseek(fd, shdr_addr + stridx * shent_size, SEEK_SET);      
          85.     read(fd, &shdr, shent_size);      
          86.   
          87.     char * string_table = (char *)malloc(shdr.sh_size);      
          88.     lseek(fd, shdr.sh_offset, SEEK_SET);      
          89.     read(fd, string_table, shdr.sh_size);    
          90.     lseek(fd, shdr_addr, SEEK_SET);      
          91.   
          92.     int i;      
          93.     uint32_t out_addr = 0;    
          94.     uint32_t out_size = 0;    
          95.     uint32_t got_item = 0;  
          96.     int32_t got_found = 0;    
          97.   
          98.     for (i = 0; i < shnum; i++) {      
          99.         read(fd, &shdr, shent_size);      
          100.         if (shdr.sh_type == SHT_PROGBITS) {    
          101.             int name_idx = shdr.sh_name;      
          102.             if (strcmp(&(string_table[name_idx]), ".got.plt") == 0   
          103.                     || strcmp(&(string_table[name_idx]), ".got") == 0) {      
          104.                 out_addr = base_addr + shdr.sh_addr;      
          105.                 out_size = shdr.sh_size;      
          106.                 LOGD("out_addr = %lx, out_size = %lx\n", out_addr, out_size);    
          107.   
          108.                 for (i = 0; i < out_size; i += 4) {      
          109.                     got_item = *(uint32_t *)(out_addr + i);    
          110.                     if (got_item  == old_eglSwapBuffers) {      
          111.                         LOGD("Found eglSwapBuffers in got\n");    
          112.                         got_found = 1;  
          113.   
          114.                         uint32_t page_size = getpagesize();  
          115.                         uint32_t entry_page_start = (out_addr + i) & (~(page_size - 1));  
          116.                         mprotect((uint32_t *)entry_page_start, page_size, PROT_READ | PROT_WRITE);  
          117.                         *(uint32_t *)(out_addr + i) = new_eglSwapBuffers;    
          118.   
          119.                         break;      
          120.                     } else if (got_item == new_eglSwapBuffers) {      
          121.                         LOGD("Already hooked\n");    
          122.                         break;      
          123.                     }      
          124.                 }     
          125.                 if (got_found)   
          126.                     break;  
          127.             }     
          128.         }      
          129.     }      
          130.   
          131.     free(string_table);      
          132.     close(fd);    
          133. }    
          134.   
          135. int hook_entry(char * a){  
          136.     LOGD("Hook success\n");  
          137.     LOGD("Start hooking\n");  
          138.     hook_eglSwapBuffers();    
          139.     return 0;  
          140. }  

          其實這種查找方法有點簡單粗暴,要是正式應(yīng)用的話可以在動態(tài)符號表中查找這個符號的got地址。

          接著Android.mk改為:

          1. LOCAL_PATH := $(call my-dir)  
          2.   
          3. include $(CLEAR_VARS)  
          4.   
          5. LOCAL_LDLIBS += -L$(SYSROOT)/usr/lib -llog -lEGL  
          6. #LOCAL_ARM_MODE := arm  
          7. LOCAL_MODULE    := hello  
          8. LOCAL_SRC_FILES := hello.c  
          9. include $(BUILD_SHARED_LIBRARY)  

          Application.mk :

          1. APP_ABI := x86 armeabi-v7a    
          2. APP_PLATFORM := android-14  

          運行ndk-build編譯:

          1. jzj@jzj-laptop:~/workspace/inject_hook/hook_so$ ndk-build   
          2. Install        : libhello.so => libs/x86/libhello.so  
          3. Install        : libhello.so => libs/armeabi-v7a/libhello.so  

          和上面一樣運行,查看logcat,我們可以看到surfaceflinger中調(diào)用eglSwapBuffers的地址已被替換成我們的版本:

          1. D/INJECT  ( 2231): [+] Injecting process: 1728  
          2. D/INJECT  ( 2231): [+] get_remote_addr: local[b7e4f000], remote[b7e73000]  
          3. D/INJECT  ( 2231): [+] Remote mmap address: b7e9fe32  
          4. D/INJECT  ( 2231): [+] Calling mmap in target process.  
          5. D/INJECT  ( 2231): [+] Target process returned from mmap, return value=b4f1c000, pc=0   
          6. D/INJECT  ( 2231): [+] get_remote_addr: local[b7f00000], remote[b7f7e000]  
          7. D/INJECT  ( 2231): [+] get_remote_addr: local[b7f00000], remote[b7f7e000]  
          8. D/INJECT  ( 2231): [+] get_remote_addr: local[b7f00000], remote[b7f7e000]  
          9. D/INJECT  ( 2231): [+] get_remote_addr: local[b7f00000], remote[b7f7e000]  
          10. D/INJECT  ( 2231): [+] Get imports: dlopen: b7f84f50, dlsym: b7f84fd0, dlclose: b7f84de0, dlerror: b7f84dc0  
          11. D/INJECT  ( 2231): [+] Calling dlopen in target process.  
          12. D/INJECT  ( 2231): [+] Target process returned from dlopen, return value=b7f995ec, pc=0   
          13. D/INJECT  ( 2231): [+] Calling dlsym in target process.  
          14. D/INJECT  ( 2231): [+] Target process returned from dlsym, return value=b4f17e10, pc=0   
          15. D/INJECT  ( 2231): hook_entry_addr = 0xb4f17e10  
          16. D/DEBUG   ( 1728): Hook success  
          17. D/DEBUG   ( 1728): Start hooking  
          18. D/DEBUG   ( 1728): Orig eglSwapBuffers = 0xb7d4a9c0  
          19. D/DEBUG   ( 1728): libsurfaceflinger.so address = 0xb7f22000  
          20. D/DEBUG   ( 1728): out_addr = b7f7aff4, out_size = 624  
          21. D/DEBUG   ( 1728): Found eglSwapBuffers in got  
          22. ...  
          23. D/DEBUG   ( 1728): New eglSwapBuffers  
          24. D/DEBUG   ( 1728): New eglSwapBuffers  
          25. D/DEBUG   ( 1728): New eglSwapBuffers  
          26. ...  


          本站僅提供存儲服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊舉報。
          打開APP,閱讀全文并永久保存 查看更多類似文章
          猜你喜歡
          類似文章
          Android注入完全剖析
          linux下實現(xiàn)在程序運行時的函數(shù)替換(熱補丁)
          共享庫注射
          利用 HookZz 實現(xiàn)反調(diào)試與繞過的奇淫技巧
          調(diào)試斷點原理
          Nginx安裝,配置,檢測等相關(guān) | 學(xué)習(xí)筆記
          更多類似文章 >>
          生活服務(wù)
          分享 收藏 導(dǎo)長圖 關(guān)注 下載文章
          綁定賬號成功
          后續(xù)可登錄賬號暢享VIP特權(quán)!
          如果VIP功能使用有故障,
          可點擊這里聯(lián)系客服!

          聯(lián)系客服