吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 668|回复: 4
收起左侧

[经验求助] 安卓逆向-method拒绝调用,原因:预期1个参数寄存器,但方法签名有0个。问题怎么解决

[复制链接]
du1263794094 发表于 2024-3-8 15:56
50吾爱币
1.故事前情
https://www.52pojie.cn/thread-1896656-1-1.html 节约时间可以只看提要:前情提要:处理一个APP,通过修改verifyUserLogin方法的判断跳转,成功做到打开软件即登录状态,实现了免登陆。点击部分按钮时,软件需要从服务器获取账号json信息,页面才能正常显示并使用,否则闪退。本以为通过正常登陆获取到账号json,对关键部分进行改编,再强制在返回值处写死就万事大吉了,结果软件一崩再崩,原因是到点击功能按钮这一步骤前,还需要点击获取城市列表按钮,点击选中城市确定按钮,每一步服务器都会返回一段json,每一步软件都会通过alibaba.fastjson处理后刷新给Model.smali,每一步功能按钮点击后软件都会从Model.smali重新获取返回值。因为自己手动写的json是写死了的,而且仅仅是账号信息的内容,没有城市列表、没有所在城市可使用功能等json信息,所以老是on a null object reference。对于一个外行小白来说,json的各种自动转换本身比较复杂,而且这个软件老是刷新不同的json,用写死返回值的方法可能行不通,所以想换个路径继续逆向。

2.问题详情
2.1通过改verifyUserLogin的判断跳转实现启动即登录,点击功能时出现闪退,logcat日志错误信息如下
[Java] 纯文本查看 复制代码
FATAL EXCEPTION: main
                 Process: com.huiyou.xiaoding, PID: 32729
                 java.lang.RuntimeException: Unable to start activity ComponentInfo{com.huiyou.xiaoding/com.huiyou.xiaoding.activity.device.HYChooseDeviceActivity}: java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String com.huiyou.xiaoding.common.model.wallet.HYWallet.getGuid()' on a null object reference
                         at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3307)
                         at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3446)
                         at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:83)
                         at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
                         at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
                         at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2043)
                         at android.os.Handler.dispatchMessage(Handler.java:107)
                         at android.os.Looper.loop(Looper.java:227)
                         at android.app.ActivityThread.main(ActivityThread.java:7533)
                         at java.lang.reflect.Method.invoke(Native Method)
                         at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:539)
                         at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:953)
                 Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String com.huiyou.xiaoding.common.model.wallet.HYWallet.getGuid()' on a null object reference
                         at com.huiyou.xiaoding.activity.device.HYChooseDeviceActivity.loadData(HYChooseDeviceActivity.java:253)
                         at com.huiyou.xiaoding.activity.device.HYChooseDeviceActivity.initUI(HYChooseDeviceActivity.java:130)
                         at com.huiyou.xiaoding.activity.device.HYChooseDeviceActivity.onCreate(HYChooseDeviceActivity.java:121)
                         at android.app.Activity.performCreate(Activity.java:7893)
                         at android.app.Activity.performCreate(Activity.java:7880)
                         at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1307)
                         at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3282)
                         at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3446) 
                         at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:83) 
                         at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135) 
                         at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95) 
                         at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2043) 
                         at android.os.Handler.dispatchMessage(Handler.java:107) 
                         at android.os.Looper.loop(Looper.java:227) 
                         at android.app.ActivityThread.main(ActivityThread.java:7533) 
                         at java.lang.reflect.Method.invoke(Native Method) 
                         at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:539) 
                         at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:953)

问题出在HYWallet,找到HYWallet.smali,查看代码
[Java] 纯文本查看 复制代码
# classes3.dex
.class public Lcom/huiyou/xiaoding/common/model/wallet/HYWallet;
.super Lcom/huiyou/xiaoding/common/model/base/HYModel;
.source "HYWallet.java"


# instance fields
.field private alias:Ljava/lang/String;

.field private avatarUri:Ljava/lang/String;

.field private consumeEnterpriseAlias:Ljava/lang/String;

.field private consumeEnterpriseGuid:Ljava/lang/String;

.field private consumeEnterpriseName:Ljava/lang/String;

.field private countCredit:I

.field private createTime:Ljava/lang/String;

.field private creator:Ljava/lang/String;

.field private dummyMoney:D

.field private fullName:Ljava/lang/String;

.field private guid:Ljava/lang/String;

.field private isSystem:I

.field private modifier:Ljava/lang/String;

.field private modifyTime:Ljava/lang/String;

.field private money:D

.field private oldMoney:D

.field private payStatus:I

.field private phone:Ljava/lang/String;

.field private status:I

.field private studentNumber:Ljava/lang/String;

.field private userGuid:Ljava/lang/String;

.field private version:Ljava/lang/String;

.field private yesEnterprise:I


# direct methods
.method public constructor <init>()V
    .registers 1

    .line 5
    invoke-direct {p0}, Lcom/huiyou/xiaoding/common/model/base/HYModel;-><init>()V

    return-void
.end method


# virtual methods
.method public getAlias()Ljava/lang/String;
    .registers 2

    .line 33
    iget-object v0, p0, Lcom/huiyou/xiaoding/common/model/wallet/HYWallet;->alias:Ljava/lang/String;

    return-object v0
.end method

.method public getAvatarUri()Ljava/lang/String;
    .registers 2

    .line 41
    iget-object v0, p0, Lcom/huiyou/xiaoding/common/model/wallet/HYWallet;->avatarUri:Ljava/lang/String;

    return-object v0
.end method

.method public getConsumeEnterpriseAlias()Ljava/lang/String;
    .registers 2

    .line 201
    iget-object v0, p0, Lcom/huiyou/xiaoding/common/model/wallet/HYWallet;->consumeEnterpriseAlias:Ljava/lang/String;

    return-object v0
.end method

.method public getConsumeEnterpriseGuid()Ljava/lang/String;
    .registers 2

    .line 185
    iget-object v0, p0, Lcom/huiyou/xiaoding/common/model/wallet/HYWallet;->consumeEnterpriseGuid:Ljava/lang/String;

    return-object v0
.end method

.method public getConsumeEnterpriseName()Ljava/lang/String;
    .registers 2

    .line 193
    iget-object v0, p0, Lcom/huiyou/xiaoding/common/model/wallet/HYWallet;->consumeEnterpriseName:Ljava/lang/String;

    return-object v0
.end method

.method public getCountCredit()I
    .registers 2

    .line 49
    iget v0, p0, Lcom/huiyou/xiaoding/common/model/wallet/HYWallet;->countCredit:I

    return v0
.end method

.method public getCreateTime()Ljava/lang/String;
    .registers 2

    .line 57
    iget-object v0, p0, Lcom/huiyou/xiaoding/common/model/wallet/HYWallet;->createTime:Ljava/lang/String;

    return-object v0
.end method

.method public getCreator()Ljava/lang/String;
    .registers 2

    .line 65
    iget-object v0, p0, Lcom/huiyou/xiaoding/common/model/wallet/HYWallet;->creator:Ljava/lang/String;

    return-object v0
.end method

.method public getDummyMoney()D
    .registers 3

    .line 73
    iget-wide v0, p0, Lcom/huiyou/xiaoding/common/model/wallet/HYWallet;->dummyMoney:D

    return-wide v0
.end method

.method public getFullName()Ljava/lang/String;
    .registers 2

    .line 81
    iget-object v0, p0, Lcom/huiyou/xiaoding/common/model/wallet/HYWallet;->fullName:Ljava/lang/String;

    return-object v0
.end method

.method public getGuid()Ljava/lang/String;
    .registers 2

    .line 89
    iget-object v0, p0, Lcom/huiyou/xiaoding/common/model/wallet/HYWallet;->guid:Ljava/lang/String;

    return-object v0
.end method

.method public getIsSystem()I
    .registers 2

    .line 97
    iget v0, p0, Lcom/huiyou/xiaoding/common/model/wallet/HYWallet;->isSystem:I

    return v0
.end method

.method public getModifier()Ljava/lang/String;
    .registers 2

    .line 105
    iget-object v0, p0, Lcom/huiyou/xiaoding/common/model/wallet/HYWallet;->modifier:Ljava/lang/String;

    return-object v0
.end method

.method public getModifyTime()Ljava/lang/String;
    .registers 2

    .line 113
    iget-object v0, p0, Lcom/huiyou/xiaoding/common/model/wallet/HYWallet;->modifyTime:Ljava/lang/String;

    return-object v0
.end method

.method public getMoney()D
    .registers 3

    .line 121
    iget-wide v0, p0, Lcom/huiyou/xiaoding/common/model/wallet/HYWallet;->money:D

    return-wide v0
.end method

.method public ge

将其中getGuid方法改为静态方法,并赋值
[Java] 纯文本查看 复制代码
.method public static getGuid()Ljava/lang/String;
.registers 2

const-string v0, "{\"guid\":\"abcdefghijklmnopqrstuvwxyz\"}"
return-object v0
.end method

保存运行,闪退,错误日志如下
[Java] 纯文本查看 复制代码
FATAL EXCEPTION: main
                 Process: com.huiyou.xiaoding, PID: 3589
                 java.lang.IncompatibleClassChangeError: The method 'java.lang.String com.huiyou.xiaoding.common.model.wallet.HYWallet.getGuid()' was expected to be of type virtual but instead was found to be of type static (declaration of 'com.huiyou.xiaoding.activity.device.HYChooseDeviceActivity' appears in base.apk!classes3.dex)
                 	at com.huiyou.xiaoding.activity.device.HYChooseDeviceActivity.loadData(HYChooseDeviceActivity.java:253)
                 	at com.huiyou.xiaoding.activity.device.HYChooseDeviceActivity.initUI(HYChooseDeviceActivity.java:130)
                 	at com.huiyou.xiaoding.activity.device.HYChooseDeviceActivity.onCreate(HYChooseDeviceActivity.java:121)
                 	at android.app.Activity.performCreate(Activity.java:7893)
                 	at android.app.Activity.performCreate(Activity.java:7880)
                 	at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1307)
                 	at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3282)
                 	at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3446)
                 	at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:83)
                 	at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
                 	at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
                 	at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2043)
                 	at android.os.Handler.dispatchMessage(Handler.java:107)
                 	at android.os.Looper.loop(Looper.java:227)
                 	at android.app.ActivityThread.main(ActivityThread.java:7533)
                 	at java.lang.reflect.Method.invoke(Native Method)
                 	at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:539)
                 	at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:953)

HYChooseDeviceActivity调取getGuid方法时认为应该是virtual非私有的方法,而不是static静态方法,又打开HYChooseDeviceActivity.smali查看代码,调取了getGuid静态方法结果的是下面这个loadData方法
[Java] 纯文本查看 复制代码
.method private loadData()V    .registers 6

    .line 251
    invoke-virtual {p0}, Lcom/huiyou/xiaoding/activity/device/HYChooseDeviceActivity;->HUDLoading()V

    .line 252
    invoke-static {}, Lcom/huiyou/xiaoding/core/HYCore;->sharedCore()Lcom/huiyou/xiaoding/core/HYCore;

    move-result-object v0

    invoke-virtual {v0}, Lcom/huiyou/xiaoding/core/HYCore;->getProject()Lcom/huiyou/xiaoding/common/model/project/HYProject;

    move-result-object v0

    invoke-virtual {v0}, Lcom/huiyou/xiaoding/common/model/project/HYProject;->getEnterpriseGuid()Ljava/lang/String;

    move-result-object v0

    .line 253
    invoke-static {}, Lcom/huiyou/xiaoding/core/HYCore;->sharedCore()Lcom/huiyou/xiaoding/core/HYCore;

    move-result-object v1

    invoke-virtual {v1}, Lcom/huiyou/xiaoding/core/HYCore;->getWallet()Lcom/huiyou/xiaoding/common/model/wallet/HYWallet;

    move-result-object v1

    invoke-virtual {v1}, Lcom/huiyou/xiaoding/common/model/wallet/HYWallet;->getGuid()Ljava/lang/String;

    move-result-object v1

    .line 254
    iget-object v2, p0, Lcom/huiyou/xiaoding/activity/device/HYChooseDeviceActivity;->deviceTypeCode:Ljava/lang/String;

    iget-boolean v3, p0, Lcom/huiyou/xiaoding/activity/device/HYChooseDeviceActivity;->isDrinking:Z

    new-instance v4, Lcom/huiyou/xiaoding/activity/device/HYChooseDeviceActivity$$ExternalSyntheticLambda0;

    invoke-direct {v4, p0}, Lcom/huiyou/xiaoding/activity/device/HYChooseDeviceActivity$$ExternalSyntheticLambda0;-><init>(Lcom/huiyou/xiaoding/activity/device/HYChooseDeviceActivity;)V

    invoke-static {v0, v1, v2, v3, v4}, Lcom/huiyou/xiaoding/http/HYHotWaterAction;->getHouseUse(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;ZLcom/huiyou/xiaoding/common/model/http/HYHttpResponseHandler;)V

    return-void
.end method

那我把invoke-virtual {v1}, Lcom/huiyou/xiaoding/common/model/wallet/HYWallet;->getGuid()Ljava/lang/String;
move-result-object v1之中的调取非私有实例方法invoke-virtual改为调取静态方法invoke-static,保存运行,又闪退崩溃,日志如下
[Java] 纯文本查看 复制代码
FATAL EXCEPTION: main
                 Process: com.huiyou.xiaoding, PID: 8459
                 java.lang.VerifyError: Verifier rejected class com.huiyou.xiaoding.activity.device.HYChooseDeviceActivity: void com.huiyou.xiaoding.activity.device.HYChooseDeviceActivity.loadData() failed to verify: void com.huiyou.xiaoding.activity.device.HYChooseDeviceActivity.loadData(): [0x17] Rejecting invocation, expected 1 argument registers, method signature has 0 (declaration of 'com.huiyou.xiaoding.activity.device.HYChooseDeviceActivity' appears in base.apk!classes3.dex)
                 	at java.lang.Class.classForName(Native Method)
                 	at java.lang.Class.forName(Class.java:454)
                 	at java.lang.Class.forName(Class.java:379)
                 	at com.huiyou.xiaoding.core.HYCommandCore.pushActivity(HYCommandCore.java:372)
                 	at com.huiyou.xiaoding.core.HYCommandCore.startActivity(HYCommandCore.java:321)
                 	at com.huiyou.xiaoding.core.HYCommandCore.run(HYCommandCore.java:84)
                 	at com.huiyou.xiaoding.fragment.home.cell.HYShortcutListCell.zb_didSelectRowAtIndexPath(HYShortcutListCell.java:169)
                 	at com.huiyou.xiaoding.common.view.zbink.listview.ZBRecyclerView$ZBRecyclerViewAdapter$1.onClick(ZBRecyclerView.java:289)
                 	at android.view.View.performClick(View.java:7161)
                 	at android.view.View.performClickInternal(View.java:7138)
                 	at android.view.View.access$3500(View.java:811)
                 	at android.view.View$PerformClick.run(View.java:27419)
                 	at android.os.Handler.handleCallback(Handler.java:883)
                 	at android.os.Handler.dispatchMessage(Handler.java:100)
                 	at android.os.Looper.loop(Looper.java:227)
                 	at android.app.ActivityThread.main(ActivityThread.java:7533)
                 	at java.lang.reflect.Method.invoke(Native Method)
                 	at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:539)
                 	at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:953)

loadData方法拒绝调用,因为预期1个参数寄存器,但是方法签名有0个,这该怎么办呢?.method private loadData()V下不是有一个register 6吗?怎么还是报错?

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

正己 发表于 2024-3-9 22:50
smali分析起来比较麻烦,你有没有试着在改完转为java代码看一下代码有没有问题?
 楼主| du1263794094 发表于 2024-3-10 15:37
正己 发表于 2024-3-9 22:50
smali分析起来比较麻烦,你有没有试着在改完转为java代码看一下代码有没有问题?

因为我对smali语法没有过比较的系统学习,我就看着前面的代码试着改。我是要把getGuid的调取方式由invoke-virtual改为invoke-static,看到loadData这个方法里已经有寄存器用invoke-static调取方式,格式是invoke-static {}, Lcom/……  而我写的是invoke-static {v1}, Lcom/……  我就删去参数v1,保存运行成功了,也算瞎猫碰见死耗子运气比较好吧,虽然还是搞不懂原理……
我还要请教一下大佬,我这个app是后付费制,结束一次使用就会生成订单,只有支付后才能进行第二次使用,我能不能删除生成订单的Activity并在AndroidMainFest删除对应的声明,就实现“结束使用后不会生成订单,可以直接开始第二次使用”?(可能还要修改一下检查未支付订单数量的判断)

点评

理论上会闪退,一般这种都会涉及数据交互,单纯删除会容易崩溃  详情 回复 发表于 2024-3-15 23:09
正己 发表于 2024-3-15 23:09
du1263794094 发表于 2024-3-10 15:37
因为我对smali语法没有过比较的系统学习,我就看着前面的代码试着改。我是要把getGuid的调取方式由invoke ...

理论上会闪退,一般这种都会涉及数据交互,单纯删除会容易崩溃
Henglie 发表于 2024-3-17 12:48
200r搞的GPT4回答:

你的尝试涉及到了Android应用的逆向工程,这是一个复杂且需要深入理解的过程。基于你的描述,问题主要出在对 smali 代码的修改上,尤其是方法调用和方法签名方面。让我们逐一解决你遇到的问题。
关于 java.lang.IncompatibleClassChangeError

这个错误发生的原因是你尝试将一个实例方法 (invoke-virtual) 改为静态方法 (invoke-static),但是你没有相应地修改调用这个方法的地方,使得期望调用的方法签名和实际的不匹配。原本,方法是作为对象的一个实例方法存在的,改为静态方法后,调用方式和期待的参数都发生了变化。
关于 java.lang.VerifyError

这个错误通常发生在应用启动时,JVM/ART(Android运行时)在验证类的过程中发现了某些不一致性。在你的案例中,是因为你尝试更改方法的调用方式,但是没有正确地匹配期望的参数,导致验证失败。
解决方案

    还原 getGuid 方法为非静态。最简单的解决方式是不改变 getGuid 方法的静态或非静态状态。如果你需要改变返回的 guid 值,考虑在该实例被创建的地方插入或修改这个值,而不是改变方法的类型。

    正确修改方法调用。如果你确实需要将某个方法改为静态,并且已经这样做了,你需要确保所有对这个方法的调用都被相应地修改。这意味着使用 invoke-static 替代 invoke-virtual,并且确保方法签名(包括参数数量和类型)与调用匹配。

    理解 registers。在 smali 代码中,.registers 指令定义了方法内部用于参数、局部变量和临时值存储的寄存器总数。对于实例方法,第一个寄存器 (p0) 用于存储 this 引用,静态方法则不需要这个引用。如果你将一个方法从实例方法改为静态方法,你需要重新考虑和调整方法内部寄存器的使用。

    深入理解 Android 应用和 smali 代码结构。逆向工程是一个高级主题,它要求你有深入理解的Android应用内部结构,包括但不限于Activity生命周期、Android组件间的交互、以及如何在不同层次上修改代码而不破坏应用的完整性。
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

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

GMT+8, 2024-12-16 02:54

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

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