学了一段时间的XPosed,发现XPosed真的好强,只要技术强,什么操作都能实现...
这次主要记录一下我对这款应用的逆向思路
apk检查
使用MT管理器检查apk的加壳情况
发现是某数字的免费版本
直接使用frida-dexdump
脱下来后备用
应用分析
进入应用之后会发现里边含有登录
会员
等模块
我们先不管登录的部分,先检查会员
的使用场景,一般在会员
的使用场景或者显示场景中都会有检查是否是VIP
的业务逻辑,根据这个来加载显示不同的资源
会员
分析
通过对应用的检查发现在添加虚拟机设备的时候用到了会员
权限
同时弹出一个对话框,应用也贴心的告诉我们VIP
的使用场景
打开算法助手,算法助手对应用进行了常见功能的Hook,最重要的是支持免费加固的Hook
将这3项勾选
重复1、2步,在日志中检查OnClick和弹窗是否有用的信息
很幸运,在这一步就获取有关的逻辑
且函数名称并没有被混淆,能够从调用堆栈读出以下逻辑:点击下载按钮->检查是否VIP->用户没有登录->显示购买VIP的弹窗
打开jadx将脱壳后的dex文件载入,搜索checkVip
选择第一个函数,发现无有用信息,继续进入checkVip
函数
在此函数中发现getUserConf,即获取用户的配置
通过对此函数的阅读,得出此函数的返回值为UserBean
然后检查
UserBean
很明显,有关VIP的数据都在此,使用XPosed来修改这些成员变量,即可达到对显示UI的修改,即使服务器对这些数据有校验也不影响,至少在UI层面已经成功了
抓包分析
使用抓包工具检查网络请求,当点击底部的导航栏的时候,应用会发送网络请求
通过检查getInfo
,获取一个Post请求的链接
对此链接进行引用查询,发现有关用户的逻辑
阅读此函数,网络请求库可能为Retrofit,当请求成功的时候会将用户的信息保存起来并移除广告?同样也能得到UserBean
,这个关键的信息
编写插件
思路
通过对应用的分析可以得出一个关键的信息getUserConf
getUserConf
函数右键->复制为XPosed片段
1 2 3 4 5 6 7 8 9 10 | XposedHelpers.findAndHookMethod( "com.vmos.pro.account.AccountHelper" , classLoader, "getUserConf" , new XC_MethodHook() {
@Override
protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
super .beforeHookedMethod(param);
}
@Override
protected void afterHookedMethod(MethodHookParam param) throws Throwable {
super .afterHookedMethod(param);
}
});
|
可以看到jadx为我们一键生成了有关的Hook代码,但是这样就行了吗?我可以告诉你,不行。别忘了,这是一个加壳的应用,即使它是一款免费的加壳
加壳应用Hook
通过对网上公开资料的查询,发现即使应用加固也需要在运行时进行还原修复,使用jadx打开加固的apk文件,找到attachBaseContext
1 2 3 4 5 6 7 8 9 | XposedHelpers.findAndHookMethod( "com.stub.StubApp" , param.classLoader, "attachBaseContext" , android.content.Context. class , new XC_MethodHook() {
@Override
protected void afterHookedMethod(MethodHookParam param) throws Throwable {
super .afterHookedMethod(param);
Context context = (Context) param.args[ 0 ]; / / 获取运行时的Context
ClassLoader classLoader = context.getClassLoader() / / 获取真正的ClassLoader
/ / 在此添加Hook VIP等操作,使用classLoader
}
});
|
继续编写
获取到正确的ClassLoader后,对getUserConf
函数的返回值进行遍历
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | XposedHelpers.findAndHookMethod( "com.vmos.pro.account.AccountHelper" , classLoader, "getUserConf" , new XC_MethodHook() {
@Override
protected void afterHookedMethod(MethodHookParam param) throws Throwable {
Object UserBean = param.getResult();
for (Field field : UserBean.getClass().getDeclaredFields()) {
/ / 设置可访问, 极其重要, 不然会崩溃
field.setAccessible(true);
/ / 使用反射来获取运行时的数据
var name = field.getName();
var type = field.getType();
var value = field.get(UserBean);
Log.i( "HookTag" , name + ": " + value);
}
super .afterHookedMethod(param);
}
});
|
Hook完成后,能够发现nickName
是正确的,能够对应上UI的显示
接下来只需要对循环里的数据进行判断赋值,然后返回即可
1 2 3 4 5 6 7 8 9 10 | / / 修改名称,其他自行测试
for (Field field : UserBean.getClass().getDeclaredFields()) {
......
if (name.equals( "nickName" )) {
field. set (UserBean, "测试文字" );
} else if (......) {
......
}
}
param.setResult(UserBean); / / 设置返回值,替换掉param.getResult()获取的
|
UI显示和下载功能
插件下载破解
获取到VIP
后,发现还有一个插件下载的逻辑没有效果
下载逻辑分析
当点击Root或者XPosed的时候,会提示加载失败
但是点击谷歌服务的时候却有效果,猜测是网络请求
打开抓包工具,通过对两者的对比,发现是其中少了一些数据,所以才会加载失败
在jadx中搜索getPluginUrl
,通过阅读此函数发现有2个匿名函数,failure
和success
使用jadx默认给我们的参数Hook不太行,这时候需要使用其他函数来获取vu
1 2 3 4 5 6 7 8 9 10 11 | / / vu<jo4>. class 无法获取
/ / 使用loadClass来获取,在参数中填写vu即可
Class<?> vu = classLoader.loadClass( "vu" );
XposedHelpers.findAndHookMethod( "com.vmos.pro.activities.main.fragments.PluginHelper$getPluginDownloadBean$2$1" , classLoader, "success" , vu, new XC_MethodHook() {
@Override
protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
Log.i( "HookTag" , "success: " + Arrays.toString(param.args));
super .beforeHookedMethod(param);
}
});
/ / 或者使用XposedBridge.hookAllMethods
|
通过对这两者的Hook,当点击Root
插件按钮时会进入success
且参数为:
1 2 | 谷歌服务按钮:success: [CommonResult{code = 0 , msg = 'OK' , data = RespPlugin{systemPluginResult = RespPluginInfo{pluginUrl = 'http://xxx/xxx/plugin/android71gp_plugin-64bit3.zip' , pluginMd5 = '62c38ec6b509e546e9fe9566969f7c49' , version = 0 }}}]
Root按钮:success: [CommonResult{code = 0 , msg = 'OK' , data = RespPlugin{systemPluginResult = null}}]
|
可以明显发现其中确实是少了一些数据,接下来只需要补齐下载链接即可,但是如何获取这个链接呢?
充值VIP获取其中的链接
扫描网站链接?或者找到一个函数获取?
猜测
上面2点显然不是我能够解决的,2333,那就通过对链接的猜测吧,根据能够下载的谷歌服务链接来看,root和xposed可能为:
http://xxx/xxx/plugin/android71root_plugin-64bit.zip'
http://xxx/xxx/plugin/android71xposed_plugin-64bit.zip'
通过一系列猜测,得出来正确的下载链接,MD5的话只需要在终端输入md5 file
即可得到
阅读函数,检查参数发现具体的链接在vu
中的data
,但是返回类型是T,这就比较麻烦了
这里采用一种比较麻烦的方法来修改:
Hookvu
类的m49633
函数获取返回结果
遍历返回结果的Fields
找到含有systemPluginResult
的field
使用field.getType()
获取到Class<?> jo4
使用jo4.newInstance()
创建一个实例ret
再次遍历ret.getDeclaredFields()
根据pluginMd5
和pluginUrl
分别赋值到ret
中
最后使用field.set(data, ret);
赋值即可
具体代码截图,pluginMd5
和pluginUrl
是我获取的正确链接,就不公布了
效果图
文章转自看雪论坛,详细内容请阅读原文
关注公众号追梦前后台回复:送书666,获取送书抽奖码全书共分为13章,内容如下:Web安全快速入门、搭建Web安全测试环境、Web站点入门基础、Web入侵技术常用命令、信息收集与踩点侦察、SQL注入攻击及防范技术、Wi-Fi技术的攻击与防范、跨站脚本攻击漏洞及利用、缓冲区溢出漏洞入侵与提权、网络欺骗攻击与数据捕获、远程控制在Web入侵中的应用、Web入侵及防范技术的应用、Web入侵痕迹的追踪与清理。
文章来源: http://mp.weixin.qq.com/s?__biz=MzI4MDQ5MjY1Mg==&mid=2247511695&idx=1&sn=5095f4b13bec10bc5e76865db56ad926&chksm=ebb5418cdcc2c89a2c67a39ec4a8584dededc1018023186decb3c5d2fa04778aed07d628840e&scene=0&xtrack=1#rd
如有侵权请联系:admin#unsafe.sh