对于Android for arm上的so注入(inject)和挂钩(hook),网上已有牛人给出了代码-libinject(http://bbs.pediy.com/showthread.php?t=141355)。由于实现中的ptrace函数是依赖于平台的,所以不经改动只能用于arm平台。本文将之扩展了一下,使它能够通用于Android的x86和arm平台。Arm平台部分基本重用了libinject中的代码,其中因为汇编不好移植且容易出错,所以把shellcode.s用ptrace_call替换掉了,另外保留了mmap,用来传字符串参数,当然也可以通过栈来传,但栈里和其它东西混一起,一弄不好就会隔儿了,所以还是保险点好。最后注意设备要root。
首先创建目录及文件:
jni
inject.c
Android.mk
Application.mk
inject.c:
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#if defined(__i386__)
#define pt_regs user_regs_struct
#endif
#define ENABLE_DEBUG 1
#if ENABLE_DEBUG
#define LOG_TAG "INJECT"
#define LOGD(fmt, args...) __android_log_print(ANDROID_LOG_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 <
constchar*libc_path ="/system/lib/libc.so";
constchar*linker_path ="/system/bin/linker";
intptrace_readdata(pid_t pid, uint8_t *src, uint8_t *buf,size_tsize)
{
uint32_t i, j, remain;
uint8_t *laddr;
unionu {
longval;
charchars[sizeof(long)];
} d;
j = size / 4;
remain = size % 4;
laddr = buf;
for(i = 0; 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);
}
return0;
}
intptrace_writedata(pid_t pid, uint8_t *dest, uint8_t *data,size_tsize)
{
uint32_t i, j, remain;
uint8_t *laddr;
unionu {
longval;
charchars[sizeof(long)];
} d;
j = size / 4;
remain = size % 4;
laddr = data;
for(i = 0; i
memcpy(d.chars, laddr, 4);
ptrace(PTRACE_POKETEXT, pid, dest, d.val);
dest += 4;
laddr += 4;
}
if(remain > 0) {
d.val = ptrace(PTRACE_PEEKTEXT, pid, dest, 0);
for(i = 0; i
d.chars[i] = *laddr ++;
}
ptrace(PTRACE_POKETEXT, pid, dest, d.val);
}
return0;
}
#if defined(__arm__)
intptrace_call(pid_t pid, uint32_t addr,long*params, uint32_t num_params,structpt_regs* regs)
{
uint32_t i;
for(i = 0; i
regs->uregs[i] = params[i];
}
//
// push remained params onto stack
//
if(i
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;
}
intstat = 0;
waitpid(pid, &stat, WUNTRACED);
while(stat != 0xb7f) {
if(ptrace_continue(pid) == -1) {
printf("error\n");
return-1;
}
waitpid(pid, &stat, WUNTRACED);
}
return0;
}
#elif defined(__i386__)
longptrace_call(pid_t pid, uint32_t addr,long*params, uint32_t num_params,structuser_regs_struct * regs)
{
regs->esp -= (num_params) * sizeof(long) ;
ptrace_writedata(pid, (void*)regs->esp, (uint8_t *)params, (num_params) *sizeof(long));
longtmp_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;</