本文介绍了从脱壳加固的App到使用Frida和Xposed成功破解应用功能的实践过程。
《敕勒歌》
敕勒川,阴山下,
天似穹庐,笼盖四野。
天苍苍,野茫茫,
风吹草低见牛羊。
-北朝民歌
前言
前一段时间使用了某个很好用的App,但使用了几次之后某个功能需要Vip,然后尝试了下破解,反编译之后发现应用被加固了,然后从网上找了一个Frida脱壳脚本,成功获取了被加固的dex,反编译之后,使用Frida编写了js脚本,成功破解了需要vip的功能,使用Frida需要一部root的手机,然后找到了一个免root使用Xposed插件的开源库,接下来使用Xposed编写了一个插件,插件实现了Frida编写的js脚本同样的功能,最终成功破解了某个vip功能。
本文仅用于技术交流,请勿用于非法用途。
Frida简介
Frida 是一款基于 Python + JavaScript 的 Hook 与调试框架,易用的跨平台 Hook 工具,从Java层到 Native 层的 Hook 无所不能,是一种动态的插桩工具,可以插入代码到原生App的内存空间中,动态的去监视和修改行为,原生平台包括 Win、Mac、Linux、Android、iOS 全平台。
大部分 App 对于我们来说都是黑盒,对 App 进行逆向和动态调试、或自动化分析、需要不断的进行动态调试,Frida 通过使用 Python 注入 JavaScript 脚本,都是通过 JS 脚本来操作设备上的 Java代码。如果需要持久化的 Hook 还是需要通过 Xposed 等框架,但是 Frida 的动态和灵活性对逆向和自动化逆向提供了很大帮助。
Frida VS Xposed:
- Xposed的优缺点:
优点:在编写Java层hook插件的时候非常好用,这一点完全优越于Frida和SubstrateCydia,因为他也是Android项目,可以直接编写Java代码调用各类api进行操作,而且可以安装到手机上直接使用。
缺点:配置安装环境繁琐,兼容性差,在Hook底层的时候就很无助了。 - Frida的优缺点:
优点:配置环境很简单,操作也很便捷,对于破解者开发阶段非常好用。选择动态调试函数会遇到各种反调试、崩溃,相比xposed而言,frida优势是其动态执行不需要重启。支持Java层和Native层hook操作,在Native层hook如果是非基本类型的话操作有点麻烦。
缺点:因为他只适用于破解者在开发阶段,也就是他没法像Xposed用于实践生产中,比如编写一个微信插件用Frida写肯定不行的,因为他无法在手机端运行。
脱壳
首先需要一部Root的手机,也可以使用自带Root的模拟器,本篇文章介绍的方法能脱市面上大部分的壳,不保证100%成功。
1.安装Frida:1
2
3
4pip install frida-tools
pip install frida
//查看安装的版本
frida --version //15.1.17
- 查看手机CPU架构:
1
adb shell getprop ro.product.cpu.abi
- 根据架构下载对应的frida-server:
4.将frida-server放到手机的/data/local/tmp下,设置读写权限1
2
3
4
5adb push frida-server-15.1.17-android-arm64 /data/local/tmp
adb shell
cd /data/local/tmp
su //进入到超级用户模式
chmod 777 frida-server-15.1.17-android-arm64
- 启动frida-server:
1
2./frida-server-15.1.17-android-arm64
`
功能启动服务后不会有任何提示。
- 重新开启一个终端窗口,查看是否连接成功:
1
frida-ps -U
连接成功,出现手机进程:
下载基于Frida的脱壳脚本:
1
2//脚本地址:https://github.com/hluwa/FRIDA-DEXDump
pip install frida-dex-dump执行端口转发:
1
2adb forward tcp:27042 tcp:27042
adb forward tcp:27043 tcp:27043手机启动要破解的App。
- 运行脱壳脚本:
1
frida-dexdump -U -f com.xxxx.xxxxx(替换为应用包名)
如果破解成功,可以看到如下图所示,已经将加固的dex输出到应用包名的文件夹中:
编写frida脚本破解vip功能
通过反编译查看代码逻辑,触发vip功能前有一个变量存储了vip的状态,编写frida脚本在点击事件执行前,通过反射修改该变量的值,然后再调用原有方法,即可成功破解vip功能,示例js代码如下:
vip.js1
2
3
4
5
6
7
8
9
10
11
12
13
14if(Java.available) {
Java.perform(function(){
var clazz = Java.use('java.lang.Class');
var Activity = Java.classFactory.use("com.xxxxxx.XXXXActivity"); //这里不能直接使用Java.use,因为java.use会检查在不在perform里面,不在就会失败
Activity.onViewClicked.overload('android.view.View').implementation = function(view){
var activity = view.getContext();
var vip = Java.cast(activity.getClass(),clazz).getDeclaredField('xxx');
vip.setAccessible(true);
vip.setBoolean(activity,true);
var ret = this.onViewClicked(view);
return ret;
}
});
}
执行js脚本1
2
3
4
5frida -R -f com.xxx.xxx -l vip.js
//执行后可以看到如下提示
//Spawned `com.xxx.xxx`. Use %resume to let the main thread start executing!
//然后根据提示输入 %resume继续执行
[Remote::com.xxx.xxx ]-> %resume
tips:可以使用这个项目中的js脚本追踪方法调用,快速定位相关功能逻辑代码。
项目地址:https://github.com/luoyanbei/android_frida_trace_myTrace
使用xposed破解vip功能
使用xposed实现需要注意的一点是,因为应用加固了,需要使用加载加固class的classloader才可以成功的hook到加固的类。示例代码如下:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22if (loadPackageParam.packageName.equals("com.xxx.xxx")) {
XposedHelpers.findAndHookMethod("com.netease.nis.wrapper.MyApplication", loadPackageParam.classLoader,
"attachBaseContext", Context.class, new XC_MethodHook() {
@Override
protected void afterHookedMethod(MethodHookParam param) throws Throwable {
super.afterHookedMethod(param);
//获取到Context对象,通过这个对象来获取classloader
final Context context = (Context) param.args[0];
//获取classloader,之后hook加固后的就使用这个classloader
ClassLoader classLoader = context.getClassLoader();
//下面就是将classloader修改成壳的classloader就可以成功的hook了
final Class clazz = classLoader.loadClass("com.xxxxxx.XXXXActivity");
XposedHelpers.findAndHookMethod(clazz, "onViewClicked", View.class, new XC_MethodHook() {
protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
super.beforeHookedMethod(param);
Toast.makeText(context, "I'm vip!", Toast.LENGTH_SHORT).show();
XposedHelpers.setBooleanField(param.thisObject, "xxx", true);
}
});
}
});
}
免Root使用Xposed
使用Xpatch这个开源库可以免Root加载Xposed插件,Xpatch的原理是对Apk文件进行二次打包,重新签名,并生成一个新的apk文件。 在Apk二次打包过程中,插入加载Xposed插件的逻辑,这样,新的Apk文件就可以加载任意Xposed插件,从而实现免Root Hook任意App的Java代码。一般来说,只要app可以被Xpatch破解,并且运行时没有做签名校验,与其相关的Xposed模块都是可用的。
另外作者还提供了App版本,可以直接安装到手机上,破解手机上安装的应用。
总结
应用脱壳可以使用FRIDA-DEXDump脚本,Frida可以在开发阶段快速完成破解验证,Xposed可以持久化hook相关功能,免root使用Xposed可以使用Xpatch的App版本,以上方法对于一些有针对性处理的App会破解失败。
参考
- https://github.com/hluwa/FRIDA-DEXDump
- https://frida.re/
- https://juejin.cn/post/6847902219757420552
- https://github.com/WindySha/Xpatch