本小节将开始介绍本书的主角——在App逆向工作中常用的逆向工具Frida。
官网对Frida的介绍是:Frida是平台原生App的Greasemonkey,说得专业一点,就是一种动态插桩工具,可以插入一些代码到原生App的内存空间去动态地监视和修改其行为,这些原生平台可以是Windows、Mac、Linux、Android或者iOS,同时Frida还是开源的。
Greasemonkey可能看起来比较陌生,其实它是Firefox的一套插件体系,通过利用Greasemonkey插入自定义的JavaScript脚本可以定制网页的显示或行为方式。换言之,可以直接改变Firefox对网页的编排方式,从而实现想要的任何功能。同时,这套插件还是“外挂”的,非常灵活机动。同样,Frida也可以通过将JavaScript脚本插入App的内存中,对程序的逻辑进行跟踪监控,甚至重新修改程序的逻辑,实现逆向人员想要实现的功能,这样的方式也可以称为Hook。
Frida目前非常火爆,该框架从Java层的Hook到Native层的Hook无所不能,虽然持久化还是要依靠Xposed和Hookzz等开发框架,但是Frida的动态和灵活对逆向及自动化逆向帮助非常大。
Frida为什么这么火爆呢?
动静态修改内存实现作弊一直是刚需,比如金山游侠,本质上Frida做的是跟它一样的事情。原则上是可以用Frida把金山游侠,包括CheatEngine等“外挂”做出来的。当然,现在已经不是直接修改内存就可以高枕无忧的年代了。建议读者也不要这样做,要知道做外挂的行为是违法的,学安全先学法。
在逆向的工作上也是一样的道理,使用Frida可以“看到”平时看不到的东西。出于编译型语言的特性,机器码在CPU和内存执行的过程中,其内部数据的交互和跳转对用户来说是看不见的。当然,如果手上有源码,甚至哪怕有带调试符号的可执行文件包,就可以使用GDB、LLDB等调试器连上去调试查看。
那如果没有,是纯黑盒呢?如果仍旧要对App进行逆向和动态调试,甚至自动化分析以及规模化收集信息,此时我们需要的是拥有细粒度的流程控制和代码级的可定制体系以及不断对调试进行动态纠正和可编程调试的框架,Frida做这种工作可以说是游刃有余。
另外,Frida使用的是Python、JavaScript等“胶水语言”,这也是它火爆的一个原因:可以迅速地将逆向过程自动化,并整合到现有的架构和体系中去,为发布“威胁情报”“数据平台”甚至“AI风控”等产品打好基础。
Frida环境的搭建其实非常简单,官网介绍直接使用pip安装frida-tools就会自动安装新版的Frida全系列产品,具体如下:
当然,仅仅在计算机上安装Frida是不够的,还需要在测试机上安装并执行对应版本的Server。例如在Android中,需要从Frida的GitHub主页的Release页面(https://github.com/frida/frida/releases)下载和计算机上版本相同的frida-server。
这里需要注意几点:第一,frida-server的版本一定要和计算机上的版本一致,比如笔者前面安装的Frida版本为14.1.3,那么frida-server的版本也必须是14.1.3,对应的网址是https://github.com/frida/frida/releases/tag/14.1.3,可以根据自己主机的Frida版本修改网址最后的数字;第二,frida-server的架构需要和测试机的系统以及架构保持一致,比如这里使用的Android测试机Nexus 5X是ARM64的架构,就需要下载frida-server相应的ARM64版本。
可以选择进入测试机的Shell执行如下命令查看系统的架构。getprop命令是安卓特有的命令,可用于查看各种系统的属性。
bullhead:/ $ getprop ro.product.cpu.abi arm64-v8a
在下载完frida-server后,需要在解压后将frida-server通过ADB工具推送到Android测试机上。在Android中,使用adb push命令推送文件到data目录一般需要Root权限,但是这里有一个例外,即可以存储到/data/local/tmp目录,所以frida-server一般会被存放在测试机的/data/local/tmp/目录下。在将frida-server存放到测试机目录下后,使用chmod命令赋予frida-server充分的权限,这样frida-server就可以执行了。
当然,由于Frida迭代更新的速度很快,当读者看到本书的时候,Frida版本可能已经不是14系列了。一方面,这说明Frida的活跃度非常高;另一方面,由于Frida迭代更新的速度过快,也会带来一个弊端:Frida的稳定性并不能得到有效的保证。故笔者在这里推荐一款Python版本管理软件pyenv,通过pyenv可以安装和管理不同的Python版本,在不同的Python版本上可以安装不同版本的Frida环境,而每一个pyenv包管理软件安装的Python版本都是相互隔离的。换句话说,无论在这个Python环境中安装了多少依赖包,对于另一个Python版本都是不可见的。
需要注意的是,在安装pyenv之前,建议读者一定要将虚拟机进行一次快照。快照是为了防止安装pyenv的最后一步依赖时,导致整个系统无法进入桌面环境。笔者安装pyenv的具体过程如下:
如果安装后重启能够正常进入桌面环境,那么接下来可以方便地使用pyenv install命令安装不同版本的Python,在安装完毕后,还需要运行pyenv local命令切换到对应版本。例如安装Python 3.8.0命令如下:
在安装一个新的Python环境后,就可以顺利进行下一步Frida的安装了。在众多Frida版本中,笔者推荐相对稳定的12.8.0版本。
在安装自定义版本的Frida时,需要先使用pip安装特定版本的Frida,再安装对应版本的frida-tools。12.8.0版本的Frida和相应的frida-tools版本对应关系如图1-26所示。
图1-26 12.8.0版本的Frida对应的Frida-tools版本
确定frida-tools版本后,即可开始安装特定版本的Frida。
同样,再配置好对应版本的frida-server后,一个全新的Frida就可以投入使用了。
相信读者都知道,在编写代码时,一个好的IDE会使编程工作事半功倍,一个基础的IDE一定要有的功能就是代码的智能提示;同样,在使用Frida编写脚本时,如果有Frida的API智能提示是非常方便的,而Frida的作者也非常体贴地提供了一个使得VSCode、Pycharm这样的IDE支持Frida的API智能提示的方式。具体步骤如下:
安装node和npm 环境,这里不要使用Linux包管理软件APT直接安装,APT安装的版本太低,这里使用Node.js官方的GitHub提供的方法,具体网址为https://github.com/nodesource/distributions,这里根据笔者自己的系统选择Debian版本,并且安装Node.js v12.x。
使用git命令下载frida-agent-example仓库并配置。
使用VSCode等IDE编辑器打开此工程,此时在子目录下编写JavaScript脚本,就会获得Frida API的智能提示,如图1-27所示。当然,这里的VScode等IDE需要读者自己下载安装,这里不再赘述。
图1-27 VSCode智能提示
至此,一个完整的Frida逆向开发环境就基本完成了。从下一章开始,我们将介绍Frida在逆向工作中的使用方法。