吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 1397|回复: 17
上一主题 下一主题
收起左侧

[Android 原创] 某记账APP的永久VIP功能和签名绕过等

  [复制链接]
跳转到指定楼层
楼主
凶杀的微笑 发表于 2026-10-2 22:28 回帖奖励

直接应用商场下载,MT看了下没加固

打开提示要更新,而且没有关闭键,是强制更新,这不得看看啥逻辑

绕过强制更新

因为弹窗在app启动就检测了,通过了才加载主页,那基本上就是启动开始阶段就去调用了,现在看到的页面已经是检测完的弹窗。那这时候的思路可以是

1、定位当前弹窗,定位弹窗调用的判断逻辑(关键词、算法助手定位堆栈、资源id定位等,当然也有可能关键词是接口返回的)

2、直接搜更新相关的关键词,尝试缕清逻辑

我这里用第二个方法,先尝试找到更新相关的方法

简单搜下更新相关的关键词 (systemUpgrade|forceUpdate|checkVersion)

这里说个思路,大致定位缩小范围再逐步定位

package
├── .bean.*              → 数据模型(Bean类,字段定义)
├── .network.* / .api.*  → 接口定义(Retrofit/OkHttp的Service)
├── .p768ui.
│   ├── .activity.*      → 页面入口(功能触发点)
│   ├── .fragment.*      → 页面片段(功能触发点)
│   ├── .model.*         → Model层(接口封装+回调转发)
│   ├── .adapter.*       → 列表适配器(UI渲染,非核心逻辑)
│   ├── .receiver.*      → ContentProvider/BroadcastReceiver(跨进程/广播)
│   └── .view.*          → 自定义View(UI控件,非核心逻辑)
├── .base.*              → 基类(缓存/公共逻辑)
├── .databinding.*       → ViewBinding生成类(布局绑定,含控件ID映射)
└── .R                   → 资源ID定义(只用来反查,不是逻辑)

anp.kad.sdk
├── C[数字][字母]        → 混淆回调类(Lambda/Function1编译产物)
├── AbstractC09xxBg     → 工具类(Toast/比较/类型转换/日志)
├── AbstractC0xxx       → 抽象基类(公共逻辑)
└── C2972xC             → Unit占位类(Kotlin Unit的Java包装)

第三方SDK(直接跳过)
├── com.bytedance.*      → 字节广告SDK
├── com.baidu.mobads.*   → 百度广告SDK
├── com.kwad.*           → 快手广告SDK
├── com.huawei.hms.*     → 华为推送/更新SDK
├── com.alibaba.*        → 阿里推送SDK
├── com.alipay.sdk.*     → 支付宝SDK
├── com.tencent.mmkv.*   → MMKV存储库
├── androidx.*           → AndroidX系统库
├── android.*            → Android系统类
└── cn.hutool.*          → Hutool工具库

所以基于这个思路,基本上,第三方SDK,bean,model等优先级先调低,先看自身包名调用的,那能不能找到蛛丝马迹。

最终定位到 forceUpdate 方法,这里实在不行用update去搜,再用上面的方法去缩小范围定位也是可以的

forceUpdate获取布尔值后用做判断,zisShowing的值为false并且forceUpdate的值为true时,走else逻辑,实例化Alert弹窗,猜测这就是提示更新的逻辑,直接hook getforceUpdate返回false

Java.perform(function(){
    var AppInfos = Java.use("com.xxx.bean.AppInfos");
    AppInfos["getForceUpdate"].implementation = function () {
        console.log(`AppInfos.getForceUpdate is called`);
        let result = false;
        console.log(`AppInfos.getForceUpdate result=${result}`);
        return result;
    };
})

没有符合的就大范围地搜,根据文件路径自行过滤 (Upgrade|Update),然后大略看一下, 比如看到forceUpdate这样就可以重点关注

绕过VIP

登录后大致有这些功能,各个地方都在提示开通VIP,就按这些功能来吧,看哪些功能触发的时候提示要开通VIP。

聊天记账

先点击聊天记账,看到有每日试用次数,并提示开通会员

直接搜 今日试用 关键词,几个都一样点进去看

这里讲一下,整体的逻辑先不看,先关注重点参数,不然一股脑地就分析各个调用逻辑容易被绕进去。这里着重关注还剩多少次这个多少,就 f32935i0 参数,往上追这个参数是 aiVipCount.getReceiveTrialTimes() - aiVipCount.getUsedTrialTimes(),这两个都是get方法,那思路就有了。

hook getReceiveTrialTimes和getUsedTrialTimes,一个直接为超大数字,一个为0。

Java.perform(function(){
    var AiVipCount = Java.use("com.jxm.bill.anxin.bean.AiVipCount");
    AiVipCount.getReceiveTrialTimes.implementation = function() {
        // 返回一个很大的试用次数,永远 > usedTrialTimes
        return Java.use("java.lang.Integer").valueOf(999999);
    };
    AiVipCount.getUsedTrialTimes.implementation = function() {
        return Java.use("java.lang.Integer").valueOf(0);
    };
})

这里有个小坑,一开始为直接返回 9999 不行,因为这两个参数定义为 Integer (包装类型/对象) ,不是 int (基本类型)。Frida 在桥接 JavaScript → Java 时,需要保证返回值 类型兼容 。方法声明的返回类型是 java.lang.Integer (对象),而 JavaScript 的 9999 是一个 JS 原始 number。Frida 的 Java 桥接层 不会自动把 JS number 装箱为 Java Integer 对象。

小计:

Java返回类型是 int/boolean/long  → 直接 return JS 值
Java返回类型是 Integer/Boolean/Long → 必须用 Java.use().valueOf() 或 .$new()
Java返回类型是 String           → 直接 return JS 字符串(String本就是对象)

然后就可以了

自动记账

自动记账默认是关的,点击开启会直接弹出开通VIP的按钮。

这是算法助手抓 onclick 的,但实际看不到细节的方法调用

androidx.constraintlayout.widget.ConstraintLayout
控件Id:7f0905b3
控件标题:自动记账

回调类:anp.kad.sdk.n2

返回结果类型:void
返回结果值:void

调用堆栈:
        at D.ADLdiqn.iTQ.djJXV.gw.XposedBridge$LegacyApiSupport.handleAfter(Unknown Source:33)
        at J.callback(Unknown Source:292)
        at LSPHooker_.performClick(Unknown Source:8)
        at android.view.View.performClickInternal(View.java:6576)
        at android.view.View.access$3100(View.java:780)
        at android.view.View$PerformClick.run(View.java:25899)
        at android.os.Handler.handleCallback(Handler.java:873)
        at android.os.Handler.dispatchMessage(Handler.java:99)
        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

从这里可能看到回调类 = anp.kad.sdk.n2。搜索 7f0905b3 得到控件名 layout_switch 。触发的功能是"自动记账",最可能是 ActivityAutomateBinding。看一下谁在使用这个Binding

这个 this.f31135l = constraintLayout10; 这里默认点ctrl+鼠标左键 / 选中按x,都查不到,要有有意识地去查找这个值

然后就得找实际触发的方法了。

理论上通过封装好的什么方法都是用 setOnClickListener ,可以直接全局搜 f311351.setOnClickListener / setOnClickListener 再一个个去定位

这里找到对应的方法,但实际触发的是case 1检查悬浮窗,这很明显不是我们要找的。之前绑定事件是嵌套式的子父结构,算法助手hook的是默认父节点,constraintLayout10 继续往下是 constraintLayout11,对应的 f31136m,就是上面截图中 i2 = 1上面那个,对应的ViewOnClickListenerC2532n2方法,第一个参数是 8,看下case 8分支。

这里就开始判断分支了 m80f 方法进去判断等于,其实就是判断用户类型是否为 3,猜测就是判断用户是否为 VIP,第一个分支是不等于,第二个分支有 automateActivity 去调用方法,猜测第二个分支是判断用户为 VIP的情况。实在不行直接hook 返回true/false判断即可

Java.perform(function(){
    console.log("
  • 自动记账 VIP 绕过(仅 case 8)启动...");         try {             var BaseActivity = Java.use("com.jxm.bill.anxin.base.BaseActivity");             // 这里直接用jadx的frida会报错cannot set property 'implementation' of undefined             // 应该混淆后运行时真实方法名是 N,不是 JADX 显示的 m34835N,jadx里有             BaseActivity.N.implementation = function() {                 return "3";             };             console.log("[+] BaseActivity.N → 返回 '3'(VIP)");         } catch (e) {             console.log("[!] Hook 失败:" + e);         }         console.log("
  • 脚本加载完成");         console.log("[!] 请在系统设置中手动开启:无障碍服务 + 悬浮窗权限"); }
  • 修改smali代码

    现在是hook可以,也知道要修改哪几个值,那就来修改静态 smali 代码,打包apk

    这一块MT管理器确实不错,但这次我用电脑操作,反编译和打包 apk 用 apktool,签名用 apksigner。

    反编译、打包、签名

    # 1. 反编译
    java -jar apktool.jar d -f xxx.apk -o xxx_decompiled
    
    # 2. 打包
    java -jar apktool.jar b xxx_decompiled -o xxx_unsigned.apk
    
    # 3. 签名
    java -jar apksigner.jar --apks xxx_unsigned.apk

    修改 1:AppInfos.getForceUpdate() → 返回 false

    文件路径: smali/com/jxm/bill/anxin/bean/AppInfos.smali

    搜索 getForceUpdate ,找到:

    .method public final getForceUpdate()Ljava/lang/Boolean;
        .locals 1
    
        iget-object v0, p0, Lcom/jxm/bill/anxin/bean/AppInfos;->forceUpdate:Ljava/lang/Boolean;
        return-object v0
    .end method

    替换为:

    .method public final getForceUpdate()Ljava/lang/Boolean;
        .locals 1
    
        sget-object v0, Ljava/lang/Boolean;->FALSE:Ljava/lang/Boolean;
        return-object v0
    .end method

    修改 2:AiVipCount.getReceiveTrialTimes() → 返回 999999

    文件路径: smali/com/jxm/bill/anxin/bean/AiVipCount.smali

    搜索 getReceiveTrialTimes ,找到:

    .method public final getReceiveTrialTimes()Ljava/lang/Integer;
        .locals 1
    
        iget-object v0, p0, Lcom/jxm/bill/anxin/bean/AiVipCount;->receiveTrialTimes:Ljava/lang/Integer;
        return-object v0
    .end method

    替换为:

    .method public final getReceiveTrialTimes()Ljava/lang/Integer;
        .locals 1
    
        const v0, 0xf423f
        invoke-static {v0}, Ljava/lang/Integer;->valueOf(I)Ljava/lang/Integer;
        move-result-object v0
        return-object v0
    .end method

    修改 3:AiVipCount.getUsedTrialTimes() → 返回 0

    搜索 getUsedTrialTimes ,找到:

    .method public final getUsedTrialTimes()Ljava/lang/Integer;
        .locals 1
    
        iget-object v0, p0, Lcom/jxm/bill/anxin/bean/AiVipCount;->usedTrialTimes:Ljava/lang/Integer;
        return-object v0
    .end method

    替换为:

    .method public final getUsedTrialTimes()Ljava/lang/Integer;
        .locals 1
    
        const/4 v0, 0x0
        invoke-static {v0}, Ljava/lang/Integer;->valueOf(I)Ljava/lang/Integer;
        move-result-object v0
        return-object v0
    .end method

    修改 4:BaseActivity.N() → 返回 "3"

    文件路径: smali/com/jxm/bill/anxin/base/BaseActivity.smali

    注意 :smali 里方法名是 N ,不是 m34835N 。

    搜索 .method public final N()Ljava/lang/String; ,找到类似:

    .method public final N()Ljava/lang/String;
        .locals 2
    
        iget-object v0, p0, Lcom/jxm/bill/anxin/base/BaseActivity;->G:Ljava/lang/String;
        if-eqz v0, :cond_0
        return-object v0
    
        :cond_0
        const-string v0, "userType"
        invoke-static {v0}, Lanp/kad/sdk/AbstractC0942Bg;->N0(Ljava/lang/String;)V
        const/4 v0, 0x0
        throw v0
    .end method

    替换为:

    .method public final N()Ljava/lang/String;
        .locals 1
    
        const-string v0, "3"
        return-object v0
    .end method

    过签名校验

    这里忘记截图了,签名打包后,直接安装启动提示 "非法请求"。基本上就是 APK 有做签名校验了,毕竟hook没问题重新打包就出问题了,代码中也搜不到提示的关键词,猜测是服务器端的签名校验,这里可以用MT的去签名校验试试,但默认只能过客户端校验的,思路也是修改 smali 代码绕过校验。

    但如果是服务器端校验,就要找校验逻辑,看看哪里取的证书。

    混淆只能改类名方法名, 改不了 Android 系统 API 的名字 。系统 API 调用是代码的"指纹"。

    // 旧版 API(API < 28)
    PackageManager.getPackageInfo(pkg, PackageManager.GET_SIGNATURES)
    //                                  flag = 0x40 = 64
    packageInfo.signatures                  // Signature[]
    
    // 新版 API(API 28+)
    PackageManager.getPackageInfo(pkg, PackageManager.GET_SIGNING_CERTIFICATES)
    //                                  flag = 0x2000000 = 134217728
    packageInfo.signingInfo
    SigningInfo.getApkContentsSigners()     // Signature[]
    SigningInfo.hasPastSigningCertificates()
    
    // 指纹计算
    MessageDigest.getInstance("SHA-256" / "SHA-1" / "MD5")
    Signature.toByteArray() / toCharsString()

    所以这里直接搜 getPackageInfo

    这里有个小技巧

    ✓ 要重点看的:
      C[数字][字母]          → 混淆回调/工具类,可能含核心逻辑
      AbstractC0[数字]       → 混淆抽象工具类
      [A-Z]开头无意义短名     → 混淆业务类
    
    ✗ 可以跳过的:
      XxxActivity / XxxFragment  → 页面入口(除非要找触发点)
      XxxAdapter                 → 列表适配器(UI,非核心)
      XxxBinding                 → ViewBinding(无业务逻辑)
      XxxProvider / XxxReceiver  → 跨进程/广播(特定场景才看)
      *Helper / *Util / *Manager → 工具类(可能有用但优先级低)

    定位到了 anp.kad.sdk 的 AbstractC1830zg 方法

    ProGuard/R8 有一条规则叫 -repackageclasses (或-flattenpackagehierarchy ),作用是把所有类的包名统一改成一个短包名。anp.kad.sdk 这种就是 ProGuard 混淆的产物,而混淆的往往是业务代码。

    这个方法里有 getPackageInfo、SigningInfo.getApkContentsSigners() 、MessageDigest.getInstance,基本上确定是取签名指纹的方法

    后续就开始找这个方法的实际调用,静态分析的话直接在 jadx 按 x,这里我使用 hook,因为这是大概是在 app 发起请求时触发的,不一定是通过常规的方法调用。静态方法不能直接查到反射调用、接口多态、动态代理的调用。

    Java.perform(function(){
        var AbstractC3068zg = Java.use("anp.kad.sdk.zg");
        // 1. 加上 overload(防御多重载)
        AbstractC3068zg.s.overload('android.content.ContextWrapper').implementation = function(contextWrapper) {
            console.log("s is called");
            // 2. 用 .call(this, ...) 调原方法,避免递归
            let result = this.s.overload('android.content.ContextWrapper').call(this, contextWrapper);
            // 3. Java 对象转字符串再打印
            var set = Java.cast(result, Java.use("java.util.Set"));
            console.log("s result: " + set.toString());
            // 4. 打调用栈(自己抛异常取栈)
            console.log(Java.use("android.util.Log").getStackTraceString(
                Java.use("java.lang.Exception").$new()
            ));
            return result;
        };
    }

    返回的值是这样的

    java.lang.Exception
            at anp.kad.sdk.zg.s(Native Method)
            at com.xxx.xxx.xxx.App.onCreate(SourceFile:24)
            ...

    看下 onCreate 方法,调用方法获取签名方法后,签名值放进本地 SharedPreferences 文件中,这个直接在手机 apk 路径就可以找到。对应的 key 为 app_sign,看下哪里代码里哪里获取了这个 key,最终在 HeaderInterceptor 找到了获取 app_sign,基本就可以推断是拦截器在每个请求之前加了 app_sign。

    这里思路很多,直接去 hook 这个生成签名的 s 方法,读取本地的 SharedPreferences 文件,用 apktool 查看证书,甚至是抓个包看看。

    这里我选择直接读取本地的 SharedPreferences 文件

    adb shell su -c "cat /data/data/com.xxx.xxxx.xxxxx/shared_prefs/phone_info.xml" | findstr app_sign

    keytool -printcert -jarfile xxxv2.1.16.apk

    可以看到格式有差异但内容相同,以 phone_info.xml 文件里格式为准,毕竟这是代码实际去读取的。

    修改思路是,修改 smali 代码,让获取签名的方法固定返回这个签名值,打包后安装,再去读取这个文件看是不是跟原apk一模一样,内容格式都要完全一样,过程中就遇到不少坑,两边多了[]或是中间多了:之类的。实际去读取就知道了。

    开始修改 smali 代码获取签名的方法,就是上面那个我们通过 getPackageInfo定位到的 s 方法,jadx切换smali可以看实际方法名,通过文件路径在反编译的源码中定位方法进行修改

    把整个方法体替换成:

    .method public static final s(Landroid/content/ContextWrapper;)Ljava/util/Set;
        .locals 3
    
        new-instance v0, Ljava/util/HashSet;
    
        invoke-direct {v0}, Ljava/util/HashSet;-><init>()V
    
        # 换成原始签名指纹(保留冒号,注意 smali 字符串里冒号无需转义)
        const-string v1, "25A26462F42FB0C1CF98A95828038D1CCD88C918B43098EC940280019CF25A3B"
    
        invoke-interface {v0, v1}, Ljava/util/Set;->add(Ljava/lang/Object;)Z
    
        return-object v0
    .end method

    再去执行反编译、打包、签名即可。

    LSPosed 脚本

    这里再补充下 LSPosed 脚本吧

    private static final String TARGET_PKG = "com.xxx.xxx.xxx";
    
        @Override
        public void handleLoadPackage(XC_LoadPackage.LoadPackageParam lpparam) throws Throwable {
            if (!TARGET_PKG.equals(lpparam.packageName)) {
                return;
            }
    
            ClassLoader cl = lpparam.classLoader;
            XposedBridge.log("
  • 安心记账 Hook 模块加载...");         // ============================================================         // ② 强制更新:AppInfos.getForceUpdate() 返回 false         // Frida: AppInfos["getForceUpdate"].implementation = () => false         // 无参方法 → findAndHookMethod 里不写任何参数类型         // ============================================================         XposedHelpers.findAndHookMethod(                 "com.jxm.bill.anxin.bean.AppInfos", cl,                 "getForceUpdate",                 new XC_MethodHook() {                     @Override                     protected void beforeHookedMethod(MethodHookParam param) {                         XposedBridge.log("AppInfos.getForceUpdate is called → false");                         // setResult 会直接替换返回值,原方法体不再执行                         // 返回类型是 Boolean,传 false 会自动装箱成 Boolean.FALSE                         param.setResult(false);                     }                 });         // ============================================================         // ③ 聊天记账:AiVipCount 试用次数         // Frida: getReceiveTrialTimes → 999999; getUsedTrialTimes → 0         // ============================================================         XposedHelpers.findAndHookMethod(                 "com.jxm.bill.anxin.bean.AiVipCount", cl,                 "getReceiveTrialTimes",                 new XC_MethodHook() {                     @Override                     protected void beforeHookedMethod(MethodHookParam param) {                         param.setResult(999999);   // int 自动装箱为 Integer                     }                 });         XposedHelpers.findAndHookMethod(                 "com.jxm.bill.anxin.bean.AiVipCount", cl,                 "getUsedTrialTimes",                 new XC_MethodHook() {                     @Override                     protected void beforeHookedMethod(MethodHookParam param) {                         param.setResult(0);                     }                 });         // ============================================================         // ④ 自动记账:BaseActivity.N() 返回 "3"(运行时真名,不是 m34835N)         // ============================================================         XposedHelpers.findAndHookMethod(                 "com.jxm.bill.anxin.base.BaseActivity", cl,                 "N",                 new XC_MethodHook() {                     @Override                     protected void beforeHookedMethod(MethodHookParam param) {                         XposedBridge.log("[+] BaseActivity.N → '3'");                         param.setResult("3");                     }                 });         // ============================================================         // ⑤ 签名 zg.s(ContextWrapper) —— 你的 Frida 只打印日志         // 有参方法:在回调前写上参数类型 ContextWrapper.class         // beforeHookedMethod 不 setResult → 只观察,不改变行为         // ============================================================         XposedHelpers.findAndHookMethod(                 "anp.kad.sdk.zg", cl,                 "s",                 ContextWrapper.class,                 // ← 参数类型,用来匹配重载                 new XC_MethodHook() {                     @Override                     protected void beforeHookedMethod(MethodHookParam param) {                         // param.args[0] 取第1个参数                         XposedBridge.log("zg.s called, ctx=" + param.args[0]);                     }                     @Override                     protected void afterHookedMethod(MethodHookParam param) {                         // after 里 param.getResult() 是原方法返回值                         XposedBridge.log("zg.s result=" + String.valueOf(param.getResult()));                     }                 });         XposedBridge.log("
  • 全部 Hook 安装完成");     }
  • 补充

    事件绑定

    科普下ID 事件绑定方式

    常规绑定:

      Activity.java
      ├─ View btn = findViewById(R.id.layout_switch);  ← 直接在Activity里找控件
      └─ btn.setOnClickListener(new OnClickListener() {...});

    ViewBinding方式:

      编译器生成 → ActivityAutomateBinding.java(只有控件引用,无逻辑)
      Activity.java
      ├─ binding.f31129f  ← 通过Binding字段间接拿控件
      └─ binding.f31129f.setOnClickListener(...)
    
      搜索 layout_switch → 先搜到Binding类(只是控件声明)
      → 需要再搜Binding类名引用 → 才找到使用它的Activity
      → 多了一层间接

    这里就搜索 ActivityAutomateBinding 的引用,返回了11个类: 其中有一个anp.kad.sdk.ViewOnClickListenerC2532n2,注意这个名字: ViewOnClickListenerC2532 + n2 = 这就是算法助手报告的回调类 anp.kad.sdk.n2。jadx对部分类方法会加字符,路径也会,比如算法助手里看到的是com.xxx.xxx.xxx.ui.方法,jadx里看的可能是com.xxx.xxx.xxx.p768ui.方法

    总结,

    任何按钮点击定位(通用流程):
    
    第1步:算法助手/布局工具 → 获取控件ID(十六进制如0x7F0905B3)
    
    第2步:R类中搜十六进制值 → 找到资源名(如 layout_switch)
    
    第3步:搜索资源名 → 得到N个结果,分两种情况:
    
      情况A:结果中直接有Activity/Fragment(传统findViewById方式)
      └─ 直接打开Activity → 搜索资源名 → 找到findViewById → 往下看setOnClickListener
    
      情况B:结果中只有Binding类(ViewBinding方式,这个app用的)← 多一步
      ├─ 按类名/控件名判断选哪个Binding
      ├─ 搜索该Binding类名的引用 → 找到使用它的Activity/Fragment + 回调类
      └─ 打开Activity → 搜索字段名(如f31129f)→ 找到setOnClickListener
    
    第4步:setOnClickListener的第二个参数 = 点击回调类
    
    第5步:打开回调类 → 看onClick → 找到业务逻辑

    其实这就类似于某种框架的事件绑定使用方法,换做以前就得各种去翻文档,找到某个用法或特性,现在AI的知识广度可以弥补很好地弥补这一点。

    系统 API

    混淆只能改类名方法名, 改不了 Android 系统 API 的名字 。系统 API 调用是代码的"指纹"。

    功能 API 指纹
    取签名 getPackageInfo + GET_SIGNING_CERTIFICATES / 0x40 / 0x2000000 + MessageDigest
    版本更新 getPackageInfo + versionName / versionCode + PackageManager
    网络请求 OkHttpClient/HttpURLConnection/Retrofit/Request$Builder
    加解密 Cipher.getInstance/MessageDigest/Mac.getInstance/SecretKeySpec
    存储 SharedPreferences / MMKV / SQLiteDatabase / FileOutputStream
    反射 Class.forName / Method.invoke / getDeclaredMethod
    动态加载 DexClassLoader/PathClassLoader/loadClass
    权限 checkSelfPermission / requestPermissions / PackageManager

    001.png (191.78 KB, 下载次数: 0)

    1

    1

    002.png (372.85 KB, 下载次数: 0)

    2

    2

    003.png (289.76 KB, 下载次数: 0)

    3

    3

    004.png (90.85 KB, 下载次数: 0)

    4

    4

    005.png (171.27 KB, 下载次数: 0)

    5

    5

    006.png (250.49 KB, 下载次数: 0)

    6

    6

    007.png (57.28 KB, 下载次数: 0)

    7

    7

    008.png (75.89 KB, 下载次数: 0)

    8

    8

    009.png (247.96 KB, 下载次数: 0)

    9

    9

    010.png (90.26 KB, 下载次数: 0)

    10

    10

    011.png (140.06 KB, 下载次数: 0)

    11

    11

    012.png (47.4 KB, 下载次数: 0)

    12

    12

    013.png (74.37 KB, 下载次数: 0)

    13

    13

    014.png (102.17 KB, 下载次数: 0)

    14

    14

    015.png (139.92 KB, 下载次数: 0)

    15

    15

    016.png (329.94 KB, 下载次数: 0)

    16

    16

    017.png (68.4 KB, 下载次数: 0)

    17

    17

    019.png (16.77 KB, 下载次数: 0)

    18

    18

    019.png (16.77 KB, 下载次数: 0)

    19

    19

    020.png (33.35 KB, 下载次数: 0)

    20

    20

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

    推荐
    wyxnyj 发表于 2026-10-4 12:29
    厉害&#128077;,楼主厉害。敢问楼主,是不是随便一个手机版app,都可以破解。我有一个主要功能记录联系人的,按照单位分类,科室标签。里面还有设置了一些小工具,比如记事本,生成证件照,识别车辆等。这样的可以破解吗
    推荐
    Tomatoman 发表于 2026-10-3 19:26
    一步一步地看完了,感觉这个写软件的人技术还是蛮强的,不容易让人一下子破解,学习了编写的思路。也感谢分析逆向过程,很详细,清晰明了。
    沙发
    如风哥哥 发表于 2026-10-3 15:42
    用的一木,记的太多了还是不换了。感谢分享经验
    3#
    bluesky137 发表于 2026-10-3 16:23
    分析过程非常详细,很适合学习,感谢分享!
    5#
    yzx159357123 发表于 2026-10-3 21:35
    学习了,感谢分享,不过现在记账主要靠手机自带的功能了
    6#
    xxoosplay 发表于 2026-10-3 23:01
    小米再带的钱包够用了。
    7#
    Sexy98 发表于 2026-10-4 04:17
    感谢分享!!
    8#
    sdmxs 发表于 2026-10-4 10:12
    来瞧瞧看啥好东西
    9#
    dork 发表于 2026-10-4 10:26
    虽然排版有点乱,还是看完了,重点其实在最后
    10#
    seller0212 发表于 2026-10-4 10:49
    分析过程非常详细,很适合学习,感谢分享
    您需要登录后才可以回帖 登录 | 注册[Register]

    本版积分规则

    返回列表

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

    GMT+8, 2026-10-5 15:01

    Powered by Discuz!

    Copyright © 2001-2020, Tencent Cloud.

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