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 #
#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 #
相关文章推荐
- Android inject 进程注入
- so注入(inject)和挂钩(hook) 以及同进程动态库so文件的函数hook方法介绍
- android进程inject注入
- Android跨进程事件注入 Injecting to another application requires INJECT_EVENTS permission
- android实现进程注入
- android跨进程事件注入(程序模拟用户输入)
- Android进程注入
- Android下的挂钩(hook)和代码注入(inject)
- android实现进程注入
- Android中的so注入(inject)
- Android中的so注入(inject)和挂钩(hook)
- Android下的挂钩(hook)和代码注入(inject)
- android跨进程事件注入(程序模拟用户输入)
- android跨进程事件注入(程序模拟用户输入)
- Android中的so注入(inject)和挂钩(hook)
- android跨进程事件注入(程序模拟用户输入)
- android平台上实现进程注入
- Android中的so注入(inject)和挂钩(hook) - For both x86 and arm
- android跨进程事件注入(程序模拟用户输入)
- android跨进程事件注入(程序模拟用户输入)