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 < 3; i++)
                h->store[i] = ((int*)h->orig)[i];
    for (i = 0; i < 3; 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

时间: 2024-10-24 21:38:47

Android Hook框架adbi源码浅析(二)的相关文章

Android Hook框架adbi源码浅析(一)

adbi(The Android Dynamic Binary Instrumentation Toolkit)是一个Android平台通用hook框架,基于动态库注入与inline hook技术实现.该框架由两个主要模块构成,1.hijack负责将动态库注入到目标进程:2.libbase提供动态库本身,它实现了通用的hook功能. 而example则是一个使用adbi进行epoll_wait hook的demo. [email protected]PC:~/Android/adbi-maste

android hook 框架 ADBI 如何实现dalvik函数挂钩

前面几篇分析已经能做到注入一个so到目标进程并用so里的函数挂钩目标进程的函数,如果对这个实现不了解,请返回去阅读  android hook 框架 ADBI 简介.编译.运行  . android hook 框架 ADBI 如何实现so注入 .android hook 框架 ADBI 如何实现so函数挂钩, so函数的挂钩只能影响native世界,没有影响到java虚拟机内部,而android绝大部分逻辑都是跑在虚拟机内部的.所以这篇接着分析 adbi 剩下的部分代码,看它如何实现挂钩dalv

Android 网络框架 volley源码剖析

转载请注明出处:  http://blog.csdn.net/guolin_blog/article/details/17656437 经过前三篇文章的学习,Volley的用法我们已经掌握的差不多了,但是对于Volley的工作原理,恐怕有很多朋友还不是很清楚.因此,本篇文章中我们就来一起阅读一下Volley的源码,将它的工作流程整体地梳理一遍.同时,这也是Volley系列的最后一篇文章了. 其实,Volley的官方文档中本身就附有了一张Volley的工作流程图,如下图所示. 多数朋友突然看到一张

Android应用Loaders全面详解及源码浅析

1 背景 在Android中任何耗时的操作都不能放在UI主线程中,所以耗时的操作都需要使用异步实现.同样的,在ContentProvider中也可能存在耗时操作,这时也该使用异步操作,而3.0之后最推荐的异步操作就是Loader.它可以方便我们在Activity和Fragment中异步加载数据,而不是用线程或AsyncTask,他的优点如下: 提供异步加载数据机制: 对数据源变化进行监听,实时更新数据: 在Activity配置发生变化(如横竖屏切换)时不用重复加载数据: 适用于任何Activit

android hook 框架 libinject2 如何实现so注入

上一篇 android hook 框架 libinject 简介.编译.运行 实际运行了so的注入并调用了注入so里的一个函数,这篇开始分析其实现. 与之前分析的 abdi 项目一样,libinject2 也是依赖于linux系统的 ptrace 系统调用. android hook 框架 ADBI 简介.编译.运行 android hook 框架 ADBI 如何实现so注入 android hook 框架 ADBI 如何实现函数挂钩 这个库首先对ptrace的调用封装了几个helper函数 i

【Android 系统开发】 编译 Android 系统 u-boot 内核 源码 并烧写到 OK-6410A 开发板上

博客地址 : http://blog.csdn.net/shulianghan/article/details/40299813  本篇文章中用到的工具源码下载 : -- ok-6410A 附带的 Android 光盘 下载地址 : http://pan.baidu.com/share/link?shareid=3662728609&uk=2754759285 ; -- 光盘所含内容 : Android 引导 u-boot 源码, Android 内核 源码, Android 系统源码, 交叉编

Android网络通信Volley框架源码浅析(三)

尊重原创 http://write.blog.csdn.net/postedit/26002961 通过前面浅析(一)和浅析(二)的分析,相信大家对于Volley有了初步的认识,但是如果想更深入的理解,还需要靠大家多多看源码. 这篇文章中我们主要来研究一下使用Volley框架请求大量图片的原理,在Android的应用中,通过http请求获取的数据主要有三类: 1.json 2.xml 3.Image 其中json和xml的获取其实原理很简单,使用Volley获取感觉有点大财小用了,了解Volle

Volley框架源码浅析(二)

尊重原创 http://write.blog.csdn.net/postedit/25921795 在前面的一片文章Volley框架浅析(一)中我们知道在RequestQueue这个类中,有两个队列:本地队列和网络队列 /** The cache triage queue. */ private final PriorityBlockingQueue<Request<?>> mCacheQueue = new PriorityBlockingQueue<Request<

Android源码浅析(二)——Ubuntu Root,Git,VMware Tools,安装输入法,主题美化,Dock,安装JDK和配置环境

Android源码浅析(二)--Ubuntu Root,Git,VMware Tools,安装输入法,主题美化,Dock,安装JDK和配置环境 接着上篇,上片主要是介绍了一些安装工具的小知识点Android源码浅析(一)--VMware Workstation Pro和Ubuntu Kylin 16.04 LTS安装配置,其实Ubuntu Kylin 16.04 LTS也只是为了体验,我们为了追求稳定,还是使用了Ubuntu14.04 这里提供一个国内镜像的下载链接,可以用迅雷,下载下来之后后缀