吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 2780|回复: 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] 纯文本查看 复制代码
 // 解决动态加载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] 纯文本查看 复制代码
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, 2024-12-12 15:35

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

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