吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 3302|回复: 30
上一主题 下一主题
收起左侧

[Android 原创] Android逆向实战-FridaHook破解极简记账VIP

  [复制链接]
跳转到指定楼层
楼主
OrientalGlass 发表于 2024-8-19 21:35 回帖奖励

[toc]

前言

本文中所有内容仅供研究与学习使用,请勿用于任何商业用途和非法用途,否则后果自负!

最近在学习frida,平常用极简记账记录日常流水,正好实战一波VIP破解

样本使用了360加固,但java代码没有混淆,总体难度不大适合新手上路

基本思路:

  1. 通过vip相关组件定位关键代码所在类
  2. frida打印关键代码所在类信息
  3. dump dex文件,分析关键代码
  4. hook vip判断逻辑

一. 相关环境

测试机: 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

使用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<methods.length;i++){
                    var methodParams=methods[i].getParameterTypes()
                    var methodReturnType=methods[i].getReturnType()
                    var methodName=methods[i].getName();
                    console.log(methodReturnType+" "+methodName+"("+methodParams+")");
                }
                console.log("\n==========fields==========");
                for(let i=0;i<fields.length;i++){
                    var fieldName=fields[i].getName();
                    var fieldType=fields[i].getType();
                    var fieldValue=instance[fieldName].value;
                    console.log(fieldType,fieldName,"=",fieldValue);
                }
            },
            onComplete:function(instance){
            }
        })
    })
}
setTimeout(main,500)

发现和支付/vip相关的几个方法

三. DumpDex

使用frida-dexdump 拉取dex文件

将所有dex文件拖进jeb工具分析(jadx无法正确反编译VipActivity相关部分代码)

四. 代码分析

反编译完成后搜索VipActivity,发现alreadyBuy()方法,该方法即为点击"已经购买"后的检测方法

内部主要通过调用isVip()判断是否为vip用户

跟进发现isVip方法是继承自BaseActivity

该方法内部目测是向服务器拉取vip的起始和终止时间判断是否为有效vip,最终返回值为bool类型

VipActivity中还能看到getVipType()不同返回值对应的vip类型

type=0时未解锁,type=1时可续订,type=2时是永久vip

最初hook了VipActivity的isVip()和getVipType()方法,发现ui显示为永久会员但是仍然需要解锁

于是搜索所有isVip()和getVipType()方法实现

五. 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成功,并且是永久会员

vip的导出账本功能正常使用

免费评分

参与人数 10吾爱币 +18 热心值 +9 收起 理由
niedaolong + 2 + 1 我很赞同!
lyrong2008 + 1 用心讨论,共获提升!
林伊轩 + 3 + 1 欢迎分析讨论交流,吾爱破解论坛有你更精彩!
junjia215 + 1 + 1 用心讨论,共获提升!
182615wenke + 1 + 1 我很赞同!
bigzhang + 1 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
正己 + 7 + 1 欢迎分析讨论交流,吾爱破解论坛有你更精彩!
null3213 + 1 我很赞同!
zyh666 + 1 + 1 谢谢@Thanks!
wyz05170517 + 1 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!

查看全部评分

本帖被以下淘专辑推荐:

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

推荐
林伊轩 发表于 2024-9-16 18:38
经过下面这个网站的学习,可算是把frida的js脚本移植到xposed中了.

https://forum.butian.net/share/2248

[Java] 纯文本查看 复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
// 解决动态加载dex文件hook不到问题
        XposedHelpers.findAndHookMethod(ClassLoader.class, "loadClass", String.class, new XC_MethodHook() {
            @Override
            protected void afterHookedMethod(MethodHookParam param) throws Throwable {
//                XposedBridge.log(TAG + " clazz => " + clazz);
                Class<?> clazz = (Class<?>) param.getResult();
                if (clazz != null) {
                    switch (clazz.getName()) {
                        case "com.luyun.simpleaccout.ui.SplashActivity":
                            XposedBridge.hookAllMethods(clazz, "isVip", new XC_MethodHook() {
                                @Override
                                protected void afterHookedMethod(MethodHookParam param) {
                                    XposedBridge.log(TAG + "  Hook SplashActivity isVip()");
                                    Object context = XposedHelpers.callMethod(param.thisObject, "getApplicationContext");
                                    Class<?> sharedPreferencesUtilsClass = XposedHelpers.findClass("com.luyun.simpleaccout.utils.SharedPreferencesUtils", loadPackageParam.classLoader);
                                    Class<?> stubAppClass = XposedHelpers.findClass("com.stub.StubApp", loadPackageParam.classLoader);
                                    Object applicationContext = XposedHelpers.callStaticMethod(stubAppClass, "getOrigApplicationContext", context);
                                    Object paramValue = XposedHelpers.callStaticMethod(sharedPreferencesUtilsClass, "getParam", applicationContext, "is_privacy_show", Boolean.valueOf(false));
                                    boolean bl = (Boolean) XposedHelpers.callMethod(paramValue, "booleanValue");
                                    XposedBridge.log(TAG + " Hook SplashActivity isVip() Succeeded! Origin result=" + param.getResult() + " bl=" + bl);
                                    param.setResult(bl);
                                }
                            });
                            XposedBridge.hookAllMethods(clazz, "popPrivacyDialog", new XC_MethodHook() {
                                @Override
                                protected void afterHookedMethod(MethodHookParam param) throws Throwable {
                                    XposedBridge.log(TAG + " Hook popPrivacyDialog 确认弹窗,执行相关初始化操作并跳转到主界面");
                                    Object context = XposedHelpers.callMethod(param.thisObject, "getApplicationContext");
                                    Class<?> sharedPreferencesUtilsClass = XposedHelpers.findClass("com.luyun.simpleaccout.utils.SharedPreferencesUtils", loadPackageParam.classLoader);
                                    Class<?> stubAppClass = XposedHelpers.findClass("com.stub.StubApp", loadPackageParam.classLoader);
                                    Object origContext = XposedHelpers.callStaticMethod(stubAppClass, "getOrigApplicationContext", context);
                                    XposedHelpers.callStaticMethod(sharedPreferencesUtilsClass, "setParam", origContext, "is_privacy_show", true);
                                    XposedBridge.log(TAG + " SharedPreferencesUtils.setParam() 已执行");
                                    XposedHelpers.callMethod(param.thisObject, "goToMainActivity");
                                    param.setResult(null);
                                }
                            });
                    }
                }
            }
        });
    }
推荐
林伊轩 发表于 2024-9-16 14:41
为什么这个代码转成xp框架代码的时候,报错,提示找不到对应的类,好奇怪

[Java] 纯文本查看 复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
LSPosed-Bridge      E  KWs.VughjCuW.z.gAm.sQH.XposedHelpers$ClassNotFoundError: java.lang.ClassNotFoundException: com.luyun.simpleaccout.ui.SplashActivity
                                                at KWs.VughjCuW.z.gAm.sQH.XposedHelpers.findClass(Unknown Source:12)
                                                at KWs.VughjCuW.z.gAm.sQH.XposedHelpers.findAndHookMethod(SourceFile:6)
                                                at yuu.xposed.jjjz.Hook.handleLoadPackage(Hook.java:20)
                                                at KWs.VughjCuW.z.gAm.sQH.IXposedHookLoadPackage$Wrapper.handleLoadPackage(Unknown Source:2)
                                                at KWs.VughjCuW.z.gAm.sQH.callbacks.XC_LoadPackage.call(Unknown Source:6)
                                                at KWs.VughjCuW.z.gAm.sQH.callbacks.XCallback.callAll(Unknown Source:26)
                                                at h0.a(Unknown Source:320)
                                                at java.lang.reflect.Method.invoke(Native Method)
                                                at J.callback(Unknown Source:253)
                                                at LSPHooker_.createOrUpdateClassLoaderLocked(Unknown Source:11)
                                                at android.app.LoadedApk.getClassLoader(LoadedApk.java:810)
                                                at android.app.LoadedApk.getResources(LoadedApk.java:1032)
                                                at android.app.ContextImpl.createAppContext(ContextImpl.java:2345)
                                                at android.app.ActivityThread.handleBindApplication(ActivityThread.java:5907)
                                                at android.app.ActivityThread.access$1100(ActivityThread.java:207)
                                                at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1663)
                                                at android.os.Handler.dispatchMessage(Handler.java:106)
                                                at android.os.Looper.loop(Looper.java:193)
                                                at android.app.ActivityThread.main(ActivityThread.java:6840)
                                                at java.lang.reflect.Method.invoke(Native Method)
                                                at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
                                                at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:860)
                                               Caused by: java.lang.ClassNotFoundException: com.luyun.simpleaccout.ui.SplashActivity
                                                at java.lang.Class.classForName(Native Method)
                                                at java.lang.Class.forName(Class.java:470)
                                                at q.a(Unknown Source:16)
                                                at KWs.VughjCuW.z.gAm.sQH.XposedHelpers.findClass(Unknown Source:4)
                                                at KWs.VughjCuW.z.gAm.sQH.XposedHelpers.findAndHookMethod(SourceFile:6)&#160;
                                                at yuu.xposed.jjjz.Hook.handleLoadPackage(Hook.java:20)&#160;
                                                at KWs.VughjCuW.z.gAm.sQH.IXposedHookLoadPackage$Wrapper.handleLoadPackage(Unknown Source:2)&#160;
                                                at KWs.VughjCuW.z.gAm.sQH.callbacks.XC_LoadPackage.call(Unknown Source:6)&#160;
                                                at KWs.VughjCuW.z.gAm.sQH.callbacks.XCallback.callAll(Unknown Source:26)&#160;
                                                at h0.a(Unknown Source:320)&#160;
                                                at java.lang.reflect.Method.invoke(Native Method)&#160;
                                                at J.callback(Unknown Source:253)&#160;
                                                at LSPHooker_.createOrUpdateClassLoaderLocked(Unknown Source:11)&#160;
                                                at android.app.LoadedApk.getClassLoader(LoadedApk.java:810)&#160;
                                                at android.app.LoadedApk.getResources(LoadedApk.java:1032)&#160;
                                                at android.app.ContextImpl.createAppContext(ContextImpl.java:2345)&#160;
                                                at android.app.ActivityThread.handleBindApplication(ActivityThread.java:5907)&#160;
                                                at android.app.ActivityThread.access$1100(ActivityThread.java:207)&#160;
                                                at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1663)&#160;
                                                at android.os.Handler.dispatchMessage(Handler.java:106)&#160;
                                                at android.os.Looper.loop(Looper.java:193)&#160;
                                                at android.app.ActivityThread.main(ActivityThread.java:6840)&#160;
                                                at java.lang.reflect.Method.invoke(Native Method)&#160;
                                                at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)&#160;
                                                at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:860)&#160;
                                               Caused by: java.lang.ClassNotFoundException: Didn't find class "com.luyun.simpleaccout.ui.SplashActivity" on path: DexPathList[[zip file "/system/framework/org.apache.http.legacy.boot.jar", zip file "/data/app/com.luyun.simpleaccout-yGgylEBqfcTC9oijJkFuxQ==/base.apk"],nativeLibraryDirectories=[/data/app/com.luyun.simpleaccout-yGgylEBqfcTC9oijJkFuxQ==/lib/arm, /data/app/com.luyun.simpleaccout-yGgylEBqfcTC9oijJkFuxQ==/base.apk!/lib/armeabi-v7a, /system/lib, /system/vendor/lib]]
                                                at dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:134)
                                                at java.lang.ClassLoader.loadClass(ClassLoader.java:379)
                                                at java.lang.ClassLoader.loadClass(ClassLoader.java:312)
                                                at java.lang.Class.classForName(Native Method)&#160;
                                                at java.lang.Class.forName(Class.java:470)&#160;
                                                at q.a(Unknown Source:16)&#160;
                                                at KWs.VughjCuW.z.gAm.sQH.XposedHelpers.findClass(Unknown Source:4)&#160;
                                                at KWs.VughjCuW.z.gAm.sQH.XposedHelpers.findAndHookMethod(SourceFile:6)&#160;
                                                at yuu.xposed.jjjz.Hook.handleLoadPackage(Hook.java:20)&#160;
                                                at KWs.VughjCuW.z.gAm.sQH.IXposedHookLoadPackage$Wrapper.handleLoadPackage(Unknown Source:2)&#160;
                                                at KWs.VughjCuW.z.gAm.sQH.callbacks.XC_LoadPackage.call(Unknown Source:6)&#160;
                                                at KWs.VughjCuW.z.gAm.sQH.callbacks.XCallback.callAll(Unknown Source:26)&#160;
                                                at h0.a(Unknown Source:320)&#160;
                                                at java.lang.reflect.Method.invoke(Native Method)&#160;
                                                at J.callback(Unknown Source:253)&#160;
                                                at LSPHooker_.createOrUpdateClassLoaderLocked(Unknown Source:11)&#160;
                                                at android.app.LoadedApk.getClassLoader(LoadedApk.java:810)&#160;
                                                at android.app.LoadedApk.getResources(LoadedApk.java:1032)&#160;
                                                at android.app.ContextImpl.createAppContext(ContextImpl.java:2345)&#160;
                                                at android.app.ActivityThread.handleBindApplication(ActivityThread.java:5907)&#160;
                                                at android.app.ActivityThread.access$1100(ActivityThread.java:207)&#160;
                                                at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1663)&#160;
                                                at android.os.Handler.dispatchMessage(Handler.java:106)&#160;
                                                at android.os.Looper.loop(Looper.java:193)&#160;
                                                at android.app.ActivityThread.main(ActivityThread.java:6840)&#160;
                                                at java.lang.reflect.Method.invoke(Native Method)&#160;
                                                at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)&#160;
                                                at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:860)&#160;
沙发
cuteapi 发表于 2024-8-20 10:44
3#
332378834 发表于 2024-8-20 12:02
看看好不好,学习一下
4#
xiaobaixuepj 发表于 2024-8-20 13:00
感谢分享,学习
5#
Mathziw1c 发表于 2024-8-20 13:54
最近也遇到类似的apk,这就试验一下
6#
helel223 发表于 2024-8-20 14:27
牛批,刚好在学习frida,我也去试一下
7#
dph5199278 发表于 2024-8-20 14:52
谢谢分享,学习了
8#
MrYuxuan 发表于 2024-8-20 14:57
学习到了,感谢楼主分享
9#
聪本 发表于 2024-8-20 20:42
cuteapi 发表于 2024-8-20 10:44
推荐使用beancount,复式记账,相当好用

这个安卓好像不方便下载把
10#
rEtb1Te 发表于 2024-8-21 08:39
感谢分享。
我有一个问题想问一下:最后给出的hook脚本,需要如何运行?比方说是将该段代码嵌入到原本的代码中,再打包运行?还是有别的运行方式呢?
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2025-4-2 01:13

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表