android adbi,Android Hook框架adbi源码浅析(二)

二、libbase

其实上面加载完SO库后,hook的功能我们完全可以自己在动态库中实现。而adbi作者为了方便我们使用,编写了一个通用的hook框架工具即libbase库。

libbase依然在解决两个问题:1.获取要hook的目标函数地址;2.给函数打二进制补丁即inline hook。

关于获取hook函数地址的方法这里不再赘述。直接看inline hook部分,这部分功能在base\hook.c的hook()函数中实现,先看hook_t结构体:

struct hook_t {

unsigned int jump[3]; //跳转指令(ARM)

unsigned int store[3]; //原指令(ARM)

unsigned char jumpt[20]; //跳转指令(Thumb)

unsigned char storet[20]; //原指令(Thumb)

unsigned int orig; //被hook函数地址

unsigned int patch; //补丁地址

unsigned char thumb; //补丁代码指令集,1为Thumb,2为ARM

unsigned char name[128]; //被hook函数名

void *data;

};

hook_t是一个标准inline hook结构体,保存了跳转指令/跳转地址/指令集/hook函数名等信息。因为ARM使用了ARM和Thumb两种指令集,所以代码中需进行区分:

if (addr % 4 == 0) {

/* ARM指令集 */

} else {

/* Thumb指令集 */

}

这样进行判断的依据,是编译器在使用Thumb指令集编译一个函数时,会自动将真正映射地址的最后一位置’1’赋给符号地址,这样可以实现无缝的Thumb指令集函数与Arm指令集代码混编。

接下来看一下ARM指令集分支的处理流程,这是该问题解决的核心部分:

if (addr % 4 == 0) {

log("ARM using 0x%lx\n", (unsigned long)hook_arm)

h->thumb = 0;

h->patch = (unsigned int)hook_arm;

h->orig = addr;

h->jump[0] = 0xe59ff000; // LDR pc, [pc, #0]

h->jump[1] = h->patch;

h->jump[2] = h->patch;

for (i = 0; i 

h->store[i] = ((int*)h->orig)[i];

for (i = 0; i 

((int*)h->orig)[i] = h->jump[i];

}

首先填充hook_t结构体,第一个for循环保存原地址处3条指令共12字节。第二个for循环用新的跳转指令进行覆写,关键的三条指令分别保存在jump[0]-[2]中:

jump[0]赋值0xe59ff000,翻译成ARM汇编为ldr pc,[pc,#0],由于pc寄存器读出的值是当前指令地址加8,因此这条指令实际是将jump[2]的值加载到pc寄存器。

jump[2]保存的是hook函数地址。jump[1]仅用来4字节占位。Thumb分支原理与ARM分支一致,不再分析。

接下来我们注意到,函数最后调用了一处hook_cacheflush()函数:

hook_cacheflush((unsigned int)h->orig, (unsigned int)h->orig+sizeof(h->jumpt));

我们知道,现代处理器都有指令缓存,用来提高执行效率。前面我们修改的是内存中的指令,为防止缓存的存在,使我们修改的指令执行不到,需进行缓存的刷新:

void inline hook_cacheflush(unsigned int begin, unsigned int end)

{

const int syscall = 0xf0002;

__asm __volatile (

"mov     r0, %0\n"

"mov     r1, %1\n"

"mov     r7, %2\n"

"mov     r2, #0x0\n"

"svc     0x00000000\n"

:

:   "r" (begin), "r" (end), "r" (syscall)

:   "r0", "r1", "r7"

);

}

参考资料

[1].adbi源码 https://github.com/crmulliner/adbi

[2].minghuasweblog,ARM Cache Flush on mmap’d Buffers with __clear_cache(),March 29, 2013

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值