前言
本文中所有内容仅供研究与学习使用,请勿用于任何商业用途和非法用途,否则后果自负!
最近在学习frida,平常用极简记账记录日常流水,正好实战一波VIP破解
样本使用了360加固,但java代码没有混淆,总体难度不大适合新手上路
基本思路:
[ol]
[/ol]
一. 相关环境
测试机: Pixel 3XL Android12
主机环境: Windows10 frida-16.0.19 python3.10 Java8
相关工具: MT管理器 Jeb4.32
App版本: 2.4.4 (360加固)
二. VIP代码定位
使用MT管理器记录活动,点击已经购买,定位vip检测的相关类
可以发现关键类为com.luyun.simpleaccout.ui.VipActivity
1_ActivityRecord.png (118.42 KB, 下载次数: 0)
下载附件
2024-8-19 21:33 上传
使用frida hook打印VipActivity相关信息
function main(){
Java.perform(function (){
Java.choose("com.luyun.simpleaccout.ui.VipActivity",{
onMatch:function(instance){
console.log("instance:",instance);
var methods=instance.class.getDeclaredMethods(); //方法
var fields=instance.class.getDeclaredFields(); //字段
console.log("\n==========methods==========");
for(let i=0;i
发现和支付/vip相关的几个方法
2_PrintMethods.png (205.53 KB, 下载次数: 0)
下载附件
2024-8-19 21:31 上传
三. DumpDex
使用frida-dexdump 拉取dex文件
3_Frida-dexdump.png (191.03 KB, 下载次数: 0)
下载附件
2024-8-19 21:31 上传
将所有dex文件拖进jeb工具分析(jadx无法正确反编译VipActivity相关部分代码)
四. 代码分析
反编译完成后搜索VipActivity,发现alreadyBuy()方法,该方法即为点击"已经购买"后的检测方法
内部主要通过调用isVip()判断是否为vip用户
4_VipActivity.png (167.52 KB, 下载次数: 0)
下载附件
2024-8-19 21:31 上传
跟进发现isVip方法是继承自BaseActivity
该方法内部目测是向服务器拉取vip的起始和终止时间判断是否为有效vip,最终返回值为bool类型
8_BaseActivity-isVip.png (59.64 KB, 下载次数: 0)
下载附件
2024-8-19 21:31 上传
VipActivity中还能看到getVipType()不同返回值对应的vip类型
type=0时未解锁,type=1时可续订,type=2时是永久vip
5_getVipType.png (61.97 KB, 下载次数: 0)
下载附件
2024-8-19 21:31 上传
最初hook了VipActivity的isVip()和getVipType()方法,发现ui显示为永久会员但是仍然需要解锁
于是搜索所有isVip()和getVipType()方法实现
6_isVip.png (24.36 KB, 下载次数: 0)
下载附件
2024-8-19 21:31 上传
7_getVipType.png (15.69 KB, 下载次数: 0)
下载附件
2024-8-19 21:31 上传
五. Hook脚本
将以上所有类的isVip和getVipType方法实现全部hook
function main(){
Java.perform(function (){
var baseActivity=Java.use("com.luyun.simpleaccout.ui.BaseActivity")
baseActivity.isVip.implementation=function(){
console.log("Hook isVip() method!Origin result=",this.isVip())
return true;
}
baseActivity.getVipType.implementation=function(){
console.log("Hook getVipType() method!Origin result=",this.getVipType())
return 2;
}
var baseFragment=Java.use("com.luyun.simpleaccout.ui.fragment.BaseFragment")
baseFragment.isVip.implementation=function(){
console.log("Hook BaseFragment isVip() Succeeded!Origin result=",this.isVip());
return true;
}
baseFragment.getVipType.implementation=function(){
console.log("Hook BaseFragment getVipType() Succeeded!Origin result=",this.getVipType())
return 2;
}
var splashActivity=Java.use("com.luyun.simpleaccout.ui.SplashActivity");
splashActivity.isVip.implementation=function(){
console.log("Hook SplashActivity isVip() Succeeded!Origin result=",this.isVip());
return true;
}
var accountWidgetProvider=Java.use("com.luyun.simpleaccout.provider.AccountWidgetProvider")
accountWidgetProvider.isVip.implementation=function(){
console.log("Hook AccountWidgetProvider isVip() Succeeded!Origin result=",this.isVip());
return true;
}
})
}
setTimeout(main,500)
六. 效果演示
Hook成功,并且是永久会员
10_getvip1.png (392.02 KB, 下载次数: 0)
下载附件
2024-8-19 21:31 上传
vip的导出账本功能正常使用
12_exportdata.png (51.21 KB, 下载次数: 0)
下载附件
2024-8-19 21:33 上传