您的位置:首页 > 移动开发 > Android开发

android 进程注入动态库 inject

2016-11-16 12:44 351 查看
#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 <malloc.h>

#include <string.h>

#include <stdlib.h>

#include <dlfcn.h>

#include <cutils/compiler.h>

#include <cutils/properties.h>

#include <utils/Log.h>

//#include "AudioResamplerSinc.h"

  

#if defined(__i386__)  

xxxxxxxxxxxxx

#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_DEBUG,LOG_TAG, fmt, ##args)  

#define  LOGD(fmt, args...) printf(ANDROID_LOG_DEBUG,LOG_TAG, fmt, ##args)  

//dddd

#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 = "/system/bin/linker";  

  

int ptrace_readdata(pid_t pid,  uint8_t *src, uint8_t *buf, 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 = buf;  

  

    for (i = 0; i < j; i ++) {  

        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;  

}  

  

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;  

    //printf( "j = %x\n", j);

    //printf( "remain = %x\n", remain );

    //printf( "laddr = %x\n", laddr );

  

    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);

        //printf( "d.val = %x\n", d.val );

        for (i = 0; i < remain; i ++) {  

            d.chars[i] = *laddr ++;  

        }  
  //printf( "d.val = %x\n", d.val );

  

        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_struct * 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  

  

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;  

}  

  

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;  

}  

  

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("ptrace_attach");  

        return -1;  

    }  

  

    int status = 0;  

    waitpid(pid, &status , WUNTRACED);  

  

    return 0;  

}  

  

int ptrace_detach(pid_t pid)  

{  

    if (ptrace(PTRACE_DETACH, pid, NULL, 0) < 0) {  

        perror("ptrace_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");  

    //printf("filename = %s\n", filename);

    if (fp != NULL) {  

        while (fgets(line, sizeof(line), fp)) { 
 

            if (strstr(line, module_name)) {  
 //printf("line = %s\n", line);

                pch = strtok( line, "-" );  

                addr = strtoul( 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);  

  

    //printf("[+] get_remote_addr: local[%x], remote[%x]\n", local_handle, remote_handle);  

    //printf("[+] get_remote_addr: local_addr[%x], local_addr[%x]\n", local_addr, local_addr); 

    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;  

}  

  

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); 
//printf("entry->d_name = %s.\n", entry->d_name);

        //printf("id = %d.\n", id);

        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__)

xxxxxx  

    return regs->eax;  

#else  
vvxxxxxx

#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)   

{  

    printf("[+] 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;  

    printf("[+] Target process returned from %s, return value=%x, pc=%x \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 *param, 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;  

    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];  

  

    printf("[+] Injecting process: %d\n", target_pid);  

  

    if (ptrace_attach(target_pid) == -1){  
  //结婚

        goto exit;  

    }

  

    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, libc_path, (void *)mmap);  

    printf("[+] Remote mmap address: %x\n", mmap_addr);  

    //获取mmap函数的执行虚地址  

    //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, ®s) == -1 ){  

        goto exit;  

    }  

    map_base = ptrace_retval(®s);  

    printf( "map_base: %x\n", map_base );

    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 );  

 

    printf("[+] Get imports: dlopen: %x, dlsym: %x, dlclose: %x, dlerror: %x\n",  

            dlopen_addr, dlsym_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, ®s) == -1 ){ 

        //打开动态链接库

        goto exit;  

    }

    void * sohandle = ptrace_retval(®s);

    //返回动态链接库的控制句柄

  

    #define FUNCTION_NAME_ADDR_OFFSET       0x100  

    ptrace_writedata(target_pid, map_base + FUNCTION_NAME_ADDR_OFFSET, 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, ®s) == -1 ){

        //调用系统函数dlsym,参数为包含钩子函数动态库的首地址,钩子函数的名称

        goto exit;  

    } 

    void * hook_entry_addr = ptrace_retval(®s);

    //其结果就是返回钩子函数的句柄,即函数的执行地址

    printf("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, ®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  

    ptrace_setregs(target_pid, &original_regs);  

    //归还结婚戒指,恢复程序现场

    ptrace_detach(target_pid);  

    //离婚

    ret = 0;  

  

exit:  

    return ret;  

}

//dd

  

int main(int argc, char** argv) {

    pid_t target_pid;
printf("inject.c main.\n");

    target_pid = find_pid_of("/system/bin/htfsk");

    if (-1 == target_pid) {

        printf("Can't find the process\n");

        return -1;

    }
printf("target_pid = %d.\n", target_pid);

    //target_pid = find_pid_of("/data/test");

    //inject_remote_process(target_pid, "/data/libhello.so", "hook_entry", "I'm parameter!", strlen("I'm parameter!"));

//inject_remote_process(target_pid, "/system/lib/libtest_hello.so", "hook_entry", "I'm parameter!", strlen("I'm parameter!"));
inject_remote_process(target_pid, "/system/lib/libtest_hello.so", "hook_entry", "I'm parameter!", strlen("I'm parameter!"));

    return 0;
}

#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 <malloc.h>

#include <string.h>

#include <stdlib.h>

#include <dlfcn.h>

#include <cutils/compiler.h>

#include <cutils/properties.h>

#include <utils/Log.h>

//#include "AudioResamplerSinc.h"

  

#if defined(__i386__)  

xxxxxxxxxxxxx

#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_DEBUG,LOG_TAG, fmt, ##args)  

#define  LOGD(fmt, args...) printf(ANDROID_LOG_DEBUG,LOG_TAG, fmt, ##args)  

//dddd

#define DEBUG_PRINT(format,args...) \  

    LOGD(format, ##args)  

#else  

#define DEBUG_PRINT(format,args...)  

#endif  

  

#define CPSR_T_MASK     ( 1u << 5 )  

  

  

  

#include <unistd.h>

#include <stdio.h>

#include <stdlib.h>

//#include <android/log.h>

#include <elf.h>

#include <fcntl.h>

#include <cutils/klog.h>

#define TAG  "htfsk"

#define LOGE(x...) do { KLOG_ERROR("events", x); } while (0)

#define LOGI(x...) do { KLOG_INFO("events", x); } while (0)

#define LOGV(x...) do { KLOG_DEBUG("events", x); } while (0)

#if 0

int debug_msg(const char *format, ...)

{

    char tmpbuf[4096];

    unsigned int send_len;

    va_list vArgs;

    va_start(vArgs, format);  

    vsnprintf( (char *)&tmpbuf[0], sizeof(tmpbuf), (char const *)format, vArgs );
  

    va_end(vArgs);

    send_len = strlen(&tmpbuf[0]);
__android_log_write( ANDROID_LOG_DEBUG, TAG, tmpbuf );  

    return 0;

}

#endif

   

int hook_entry(char * a){

    //debug_msg("Hook success, pid = %d\n", getpid());

    //debug_msg("Hello %s\n", a);

//__android_log_write( ANDROID_LOG_DEBUG, TAG, "hook_entry 123" ); 

system("echo mabi 123 >/dev/ttyS0");

    return 19;

}

include $(CLEAR_VARS)

LOCAL_SRC_FILES := bionic/inject.c

LOCAL_MODULE := test_dlclose_destruction1

LOCAL_LDFLAGS := -ldl

#LOCAL_SHARED_LIBRARIES := libdlclosetest1 libdlclosetest2

LOCAL_MODULE_TAGS := tests

include $(BUILD_EXECUTABLE)

include $(CLEAR_VARS)

LOCAL_SRC_FILES := bionic/lib_hello.c

LOCAL_MODULE    := libtest_hello

LOCAL_MODULE_TAGS := tests

#LOCAL_SHARED_LIBRARIES := libdlclosetest1 libdlclosetest2 liblog

include $(BUILD_SHARED_LIBRARY)

结果:

shell@astar-dvk3:/proc/self # 

shell@astar-dvk3:/proc/self # 

shell@astar-dvk3:/proc/self # 

shell@astar-dvk3:/proc/self # test_dlclose_destruction1                        

inject.c main.

target_pid = 757.

[+] Injecting process: 757

[+] Remote mmap address: 401bbcf9

[+] Calling mmap in target process.

[+] Target process returned from mmap, return value=417cf000, pc=0 

map_base: 417cf000

[+] Get imports: dlopen: 400c7f4d, dlsym: 400c7e9d, dlclose: 400c7e19, dlerror: 400c7dc9

library path = /system/lib/libtest_hello.so

[+] Calling dlopen in target process.

[+] Target process returned from dlopen, return value=415fbc90, pc=0 

[+] Calling dlsym in target process.

[+] Target process returned from dlsym, return value=417ac359, pc=0 

hook_entry_addr = 0x417ac359

[+] Calling hook_entry in target process.

mabi 123

[+] Target process returned from hook_entry, return value=13, pc=0 

Press enter to dlclose and detach

[+] Calling dlclose in target process.

[+] Target process returned from dlclose, return value=415fbc90, pc=4008be18 

shell@astar-dvk3:/proc/self # 

shell@astar-dvk3:/proc/self # 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: