天天看点

Android注入和HOOK

如何理解HOOK?

大家可以想象一下个人电脑防火墙,特别是Linux下的iptables和netfilter。

譬如说一条命令

可以丢弃所有进入的数据包。

为什么能做到这一点?

数据包从到达网卡一直到传递到上层应用有一条完整的路径,netfilter框架在这条路径上加入了五个钩子函数。这些个钩子函数可以在数据经过自己的时候把它传递给挂在钩子上的处理函数。也即,钩子是系统提供的,如何处理则是由用户来控制的。

古河提供的libinject框架的作用也基本是这样。

1.首先要明白的是,libinject基于ptrace,对给定的进程进行控制。Ptrace本身也类似于钩子,它将一个进程正常的执行流打断,读取这个进程的寄存器和数据,甚至代码,从而实现控制。

2.为什么说libinject是一个框架呢?libinject就类似于netfilter,它实现了一种机制,这种机制使得用户自己提供的.so可以在目标进程中获得执行,也就类似于在iptables中用户准备对数据包进行什么处理,规则是用户自己定义和提供的,而框架负责执行。

3.libinject是如何使得用户的.so可以执行呢?用户的.so要能够得到执行,就必须在进程的地址空间中,这个需要使用mmap函数将用户的.so映射到进程的地址空间;然后调用dlopen函数打开.so动态库,以及使用dlsym函数获得.so库中的具体函数,然后开始执行。

4.因此,简而言之,libinject框架需要完成的工作就是a)停下目标进程正常的执行流,保存现场,然后调用mmap函数将.so映射到目标进程的地址空间;b)调用dlopen函数和dlsym函数获得具体要执行的函数;c)执行该函数——这个函数就是用户希望对被控制进程进行的操作。

5.在具体的实现中,我们知道,进程之所以能够获得执行,是因为CPU忠实地从EIP(PC)寄存器所保存的地址中取出指令,并执行;也即,为了改变程序的执行流,只要改变该进程的EIP寄存器的值就行了。而这个功能正是ptrace所擅长的。

6.接下来的问题是,如何找到mmap可执行文件的地址?mmap本身位于libc.so库中,要先能够找到libc.so库的位置,然后定位出来libc.so库中mmap函数的位置。

(这里,需要对.so库的特点有比较深刻的了解。譬如为什么要有so库?程序是如何调用.so中的函数的?)

libinject的基本思路是利用了在同一个系统中,多个进程公用的同一个.so库,这个库中的某个函数相对于库基址的偏移对于所有的进程都是一样的。所以,只需要在本地进程中计算出mmap函数相对于库基址的偏移,然后通过读取/proc/pid(目标进程)/maps文件得到目标进程中libc.so库的基址,就可以获得目标进程中mmap函数的位置。

7.类似的方法,可以获得linker.so库中dlopen, dlsym以及dlclose等函数的地址,并强制目标进程执行。

8.在通过dlsym找到用户注入的.so库中的函数时,用户的程序便可以获得执行,目标达到。

Android神器Xposed也是如此:

pcedu.pconline.com.cn/484/4841077_all.html

Xposed的强大,只要想一想,基于它,人们已经开发出了众多的广受欢迎的模块,便可见一斑。

有了Xposed,如果想要修改某个apk,只需要在分析该apk的基础上,针对它写一个xposed模块即可。

相比于libinject, xposed的注入对象是Java层的方法,而这个hook是通过修改Android的启动进程zygote而来。

关于zygote,可以参考如下链接

http://www.cnblogs.com/samchen2009/p/3294713.html

xposed安装时修改的正是zygote启动的第一个可执行文件app_process,它增强了app_process的功能(具体如何增强的得细读源码和其他分析文档)。Xposed使用自己的app_process替代了系统中的app_process,基本原理是引入了额外的jar包,使用这个jar包,开发者可以实现对java层方法的hook。

Xposed具有一个方法hookmethodnative,顾名思义,这个方法的作用是改变一个方法的类型为native,并且将这个方法的具体实现转移到xposedbridge中自己实现的native版本。这样的话,每一次这个方法被调用的时候,真正起作用的是xposed中的实现,而并非系统原有的实现。然后,xposed提供一个方法handlehookedmethod,它可以将被hooked的函数的参数传递出去。这样,开发人员便可以改变、使用该参数,调用其他方法、改变结果等等。

因此,xposed框架使用的基本思路便是首先定位到自己想要进行hook的函数,在xposed框架中进行注册,然后获取了该函数的处理权,便可以进行相应的操作。

关于android的hook,更详细资料可以参考:

http://drops.wooyun.org/tips/9300

http://drops.wooyun.org/papers/10156