【APP逆向100例】Frida初体验,root检测及加密字符串定位数据接口已经脱敏,严禁用于商业和非法用途,否则由此产生的一切后果与本站无关作者!本文未经许可禁止转载,修改后禁止二次传播。对于因未经授权使用本文所解释的技术而导致的任何事故,作者概不负责。如有侵权,请第一时间联系作者公众号【K爬虫哥】删除!反向目标设备:谷歌Pixel4,Android10,root过的APP:UnCrackable-Level1.apk(在公众号回复APP获取)APP检测root,如果手机root了会强制退出APP,检测到root后,会返回Astringneedsinputforverification.安装ADBadb(AndroidDebugBridge),也就是Android调试桥。安装后即可在电脑上与手机进行交互。AndroidStudio和其他工具将随adb一起提供。有时候我们不想下载这么大的工具,所以这里介绍一下AndroidSDKPlatform-Tools,它是AndroidSDK的一个组件,它包含了与Android平台交互的工具,主要有adb和fastboot,官方下载地址:https://developer.android.com...,下载完成后,将目录添加到环境变量中,用USB连接手机,允许手机USB调试,使用命令adbversion查看版本信息,adbdevices查看当前连接的设备,如下图:安装FridaFrida是一个基于Python+JavaScript的Hook调试框架,首先在电脑上使用命令pipinstallfrida-tools安装frida模块(该命令会默认安装最新版本的frida和frida-tools等),然后下载frida-server,下载地址:https://github.com/frida/frid...frida-server要根据你电脑安装的frida版本和手机的CPU架构来选择。使用命令frida--version查看frida版本,使用命令adbshell进入手机,输入getpropro.product.cpu.abi查看CPU架构,如下图,我的frida版本是15.2.2,手机CPU是arm64,所以下载了frida-server-15.2.2-android-arm64.xz。某些较低的Android版本在使用较高版本的frida时可能会出现问题。如果遇到问题,可以尝试降低frida版本来解决。使用adbpush命令将下载好的frida-server传输到手机/data/local/tmp/目录下,并赋予777读写执行权限,然后直接运行frida-server。通常,不会有输出。当然你也可以使用&等让它在后台运行。然后再打开一个cmd,使用命令frida-ps-U查看手机的进程,如果有输出则正常。逆向分析使用adbinstall命令安装UnCrackable-Level1.apk,打开APP,会检测到root,检测到一个Root!会出现提示,如下图:使用JEB、JADX、GDA等工具反编译apk,直接搜索关键字Rootdetected!可以定位检测到的地方:可以看到图中有c.a()、c.b()、c.c()三种检测方法,其中一种返回true,检测到Root!会弹出,然后在它前面有个onClick方法,如果点击确定按钮,System.exit(0);被触发,即退出APP,首先点击三种检测方式查看:a()方法判断Android系统环境变量root中是否有su文件;b()方法通过检查Build.TAGS中是否包含stringtest-keys来判断是否root;c()方法通过检查指定路径下是否包含指定文件来判断是否root。所以我们这里有多种检测方法:方法一:Hook三种检测方法,让它们都返回false,并且不执行后面的方法a,就不会退出APP:java.perform(function(){console.log("[*]Hookbegin")varvantagePoint=Java.use("sg.vantagepoint.a.c")vantagePoint.a.implementation=function(){console.log("[*]Hookvantagepoint.a.c.a")this.a();returnfalse;}vantagePoint.b.implementation=function(){console.log("[*]Hookvantagepoint.a.c.b")this.b();returnfalse;}vantagePoint.c.实现=function(){console.log("[*]Hookvantagepoint.a.c.c")this.c();returnfalse;}})方法二:Hooka()方法,为空,什么都不做,不弹出对话框在不退出APP的情况下启动:Java.perform(function(){console.log("[*]Hookbegin")varmainActivity=Java.use("sg.vantagepoint.uncrackable1.MainActivity");mainActivity.a.implementation=function(){console.log("[*]HookmainActivity.a")}})方法三:HookonClick()方法,点击确定防止其退出APP,注意这里是Hook写法内部类的方法:Java.perform(function(){console.log("[*]Hookbegin")varmainActivity$1=Java.use("sg.vantagepoint.uncrackable1.MainActivity$1");mainActivity$1.onClick.implementation=function(){console.log("[*]HookmainActivity$1.onClick")}})方法四:HookSystem.exit()方法,点击确定后,不让它退出APP:Java.perform(function(){console.log("[*]Hookbegin")varjavaSystem=Java.use("java.lang.System");javaSystem.exit.implementation=function(){console.log("[*]Hooksystem.exit")}})root检测通过后,APP需要输入一个字符串。如果输入错误,会提示That'snotit。再试一次,如下图:分析Java代码,有if-else判断,obj为输入字符串,a.a(obj)判断为true,说明输入正确按照a.a()方法,您可以看到bArr是一个内置字符串。使用equals()方法比较输入的str是否等于bArr:bArr的值主要是通过sg.vantagepoint.a.a.a()方法处理后得到的。继续跟进,会发现是AES加密算法:这里可以直接Hooksg.vantagepoint.a.a.a(),直接得到加密后的值,就是我们想要的正确字符串。由于这里返回的是ASCII码,所以我们还需要在JavaScript代码中使用String.fromCharCode()将其转换为普通字符。Hook代码如下:Java.perform(function(){varcryptoAES=Java.use("sg.vantagepoint.a.a");cryptoAES.a.implementation=function(bArr,bArr2){console.log("[*]挂钩cryptoAES")varsecret="";vardecryptValue=this.a(bArr,bArr2);console.log("[*]DecryptValue:",decryptValue)for(vari=0;i
