APP逆向神器之Frida【Android初级篇】

说到逆向APP,不少人首先想到的都是反编译,可是单看反编译出来的代码很可贵知某个函数在被调用时所传入的参数和它返回的值,极大地增长了逆向时的复杂度,有没有什么办法能够方便地知道被传入的参数和返回值呢?javascript

答案是有的,这个方法就是Hook,Hook的原理简单地说就是用一个新的函数替代掉原来的函数,在这个新的函数中你想作什么均可以,随心所欲。java

本文中的Frida就是一个很经常使用的Hook工具,只须要编写一段Javascript代码就能轻松地对指定的函数进行Hook,并且它基本上能够算是全平台的(主流平台全覆盖),除了Android之外,iOS和PC端的APP也能够用它来进行Hook,很是方便。python


那么怎么使用呢?首先咱们在Frida官方文档中的Installation页能够看到,咱们须要有Python环境,而且用pip安装一个叫frida-tools的库,而后才能够开始使用。git

Python环境相信你们都有了,直接打开命令行,执行一波pip install frida-tools吧。github

安装完毕之后,由于这一页文档的下半部分用于测试刚装好的库是否可用的话过于麻烦,咱们这里就直接使用frida-ps命令来测试吧。shell

看起来是没问题了,而后咱们怎么Hook Android手机上的APP呢?别急,还须要在手机上作一些操做你才能这么作。api


咱们须要有一台已经Root了的Android手机,由于不一样型号的手机Root方法存在差别,本文中就不指导如何对手机进行Root操做了,请自行经过搜索引擎查找方法。实在没有能够Root的Android手机的话能够选择使用模拟器,推荐使用Genymotion之类系统较为原生的模拟器,并将Android版本选择在6.0以上,不然可能会出现一些奇奇怪怪的问题bash

手机准备好了以后,找到Frida文档中Tutorials栏里的Android页,开始进行Frida的手机端准备工做。网络

文档中能看到,Frida官方最近的大部分测试都是在运行着Android 9的Pixel 3上进行的,因此理论上来说若是你在使用中遇到任何奇怪的问题,均可能是你手机的系统致使,因此这里再次建议,使用较为原生和偏高版本的系统(建议至少6.0)进行操做架构

接着往下看,咱们须要在手机上以Root权限运行一个叫frida-server的东西,这个东西须要在Frida官方的GitHub仓库中下载,文档中有连接能够直接跳转

打开GitHub以后你会发现,这里有不少个不一样的版本,应该下载哪个呢?

能够看到这一排的文件中,末尾处都有个系统和CPU架构的标识,咱们直接看Android的。这里标了Android的一共有四个,而后X86的由于不是手机使用的CPU架构,能够直接pass掉,剩下的就是arm和arm64两种了,那么咱们须要怎么判断本身的手机/模拟器属于哪种CPU架构的呢?

查CPU架构的方法不少,这里介绍一个比较方便快捷的——使用一个名叫Device Info HW的APP。

安装后打开它,在芯片栏中咱们能够看到一个叫ABI的东西,右边就是咱们手机的CPU架构了,以下:

因此这里我须要下载的是arm64版本的frida-server,下载后解压出来一个没后缀的文件,而后咱们须要将这个文件放入手机中运行起来。先把这个文件的名字改为frida-server,而后在这个文件所在的目录下打开命令行(Windows下为Shift+鼠标右键,选择“在此处打开CMD/PowerShell”),执行如下命令:

adb root
adb push frida-server /data/local/tmp/ 
adb shell "chmod 755 /data/local/tmp/frida-server"
adb shell "/data/local/tmp/frida-server &"
复制代码

若是你的手机和个人同样,直接这么运行会提示权限不足的话,能够先进入adb shell,在执行su命令获取Root权限后(手机端可能会弹出Root受权提示),再运行/data/local/tmp/frida-server &启动frida-server。

启动后,咱们先照惯例来测试一下是否能正常使用了,和前面同样,使用frida-ps命令,但在后面加一个-U参数,这个参数的意思是让它对USB链接的设备操做,若是不出意外的话,你应该能看到与不加-U参数时大相径庭的显示。

至此,全部准备工做均已完成。

小提示:在手机重启后须要从新运行一次frida-server,但能够不从新执行adb push操做,由于文件已经放进去了。


终于到了喜闻乐见的实战环节了,就拿Frida官方文档中的提到的CTF APP来开刀吧,找到文档中Examples栏里的Android页,通过几回跳转后下载APP安装、打开,会看到这样的一个界面:

这个APP是一个石头剪子布的游戏,点击下面三个按钮分别选择石头、剪子、布,玩起来的时候是这么一个效果(加号后面的是得分值,正常状况下连胜会每次在原来的基础上+1):

咱们先作个比较简单的操做吧,让咱们的每次出招都必胜~先复制一下文档中的代码,建一个.py文件粘贴进去,将this.cnt.value = 999;这一条删除或注释掉,而后运行这个python脚本,在注入完成后,无论你怎么点,你都是一定胜利的,以下图:

注:图中左下方显示的是Hook时产生的日志,其中value是得分值。

可是这样子弄,若是咱们须要让分值达到很高的话,就须要点不少次了,怎么让它一次就加到999呢?很简单,直接把得分值也给改了就行了,咱们把前面去掉的this.cnt.value = 999;再改回来,而后从新运行一遍这个脚本。

正常状况下这个分值会是一个+999,这里显示成这样是由于这个样例APP太老了,不兼容新版本系统,致使出现这种状况,换旧版本系统可解,因此这里不纠结这个问题。


单看这么一通操做是否是以为很懵?复制过来的代码是干啥的都不知道,若是换一个APP咋搞?不慌,我把这个代码的意思一行一行地给你解释一遍,你就知道怎么用了。

首先import不用说了吧,你们都懂,直接看on_message这个函数。这个on_message的用途是接收下面Javascript代码中调用send函数传出的日志,一般咱们能够不用管它,直接复制出来用就好了,或者可使用console.log打日志,效果也是差很少的。

而后是jscode这个变量,这个变量其实建议使用一个单独的.js文件代替,由于这样的话可使用各类编辑器、IDE的JavaScript代码格式化、智能提示等功能,写起来会舒服不少。若是你要替换掉的话,改为读JS代码文件以后read出内容字符串赋值给jscode就好了。

接着是JS代码中的部分。

先看看Java.perform,在Frida官方文档的javascript-api页中能够看到,它的用途是确保当前线程已链接到VM用的,因此咱们直接照着这么用就好了;

而后看看Java.use这个函数,它的用途是获取一个指向某个类的指针,参数中的com.example.seccon2015.rock_paper_scissors.MainActivity就是咱们须要Hook的那个类;

接着就是真正执行Hook的部分了,这个代码中使用了一个MainActivity.onClick.implementation,意思就是Hook前面获取到的类中的onClick方法,后面跟着的赋值函数的部分,函数的参数为对应要Hook方法的参数,内部执行的部分就是在对应方法被调用时所执行的代码,这里它是先打了一个onClick日志,而后调用了原始方法(若是不调用的话原始方法不会被执行),接着它将m、n、cnt(变量具体含义请自行反编译APP后查看代码)的值作了修改,最后,它又打了一个携带着cnt变量值的日志。

最后是一些常规操做,frida.get_usb_device().attach()是获取指定APP(参数为包名)当前运行着的进程,process.create_script(jscode)script.load()是将前面的JS代码注入进去,script.on('message', on_message)是设置消息传出时的回调,最后的sys.stdin.read()是输出日志用的。

总之,除了JS代码部分,其余的其实只是个壳子,核心的Hook操做逻辑全在JS代码中,咱们在使用时通常只改JS代码部分和指定包名的部分就能够了。


看了这一篇文章后你应该会对使用Frida对Android手机上Java层的Hook有所了解了吧,若是以为玩Frida官方文档中的这个石头剪子布APP不够刺激,还能够看看我前面的《当你写爬虫遇到APP的请求有加密参数时该怎么办?【初级篇-秒杀模式】》这篇文章,里面使用的DEMO APP是有SSL Pinning、且对代码进行了混淆的,但愿你可以触类旁通,本身写出一个干掉这个SSL Pinning的脚本。(若是还不会的话能够看更前面的《当你写爬虫抓不到APP请求包的时候该怎么办?【高级篇-混淆致使通用Hook工具失效】》这篇文章)

发送消息“Frida Android初级篇”到个人公众号【小周码字】便可得到代码和APP的下载地址~

这个时代各类东西变化太快,而网络上的垃圾信息又不少,你须要有一个良好的知识获取渠道,不少时候早就是一种优点,还不赶忙关注个人公众号并置顶/星标一波~

相关文章
相关标签/搜索