为啥这是一个无效的 smali 寄存器?

Posted

技术标签:

【中文标题】为啥这是一个无效的 smali 寄存器?【英文标题】:Why is this an invalid smali register?为什么这是一个无效的 smali 寄存器? 【发布时间】:2019-04-11 22:22:58 【问题描述】:

我在反编译的应用程序中注入了这段代码invoke-static p0, Lcom/outfit7/talkingtomcandyrun/Toast;->show(Landroid/content/Context;)V

像这样:

.line 70
    move-object/from16 v0, p0

    iget-object v0, v0, Lcom/bee7/gamewall/dialogs/BannerNotificationDialog;->sharedPreferencesNotificationsHelper:Lcom/bee7/sdk/common/util/SharedPreferencesNotificationsHelper;

    move-object/from16 v21, v0

    sget v22, Lcom/bee7/gamewall/BannerNotification;->NUMBER_OF_REWARD_BANNER_NOTIFICATIONS_LAYOUTS:I

    invoke-virtual/range v21 .. v22, Lcom/bee7/sdk/common/util/SharedPreferencesNotificationsHelper;->getNextRewardNotificationLayout(I)I

    .line 76
    sget v21, Lcom/bee7/gamewall/R$layout;->gamewall_banner_notification_reward_0:I

    move-object/from16 v0, p0

    move/from16 v1, v21

    invoke-virtual v0, v1, Lcom/bee7/gamewall/dialogs/BannerNotificationDialog;->setContentView(I)V     
    invoke-static p0, Lcom/outfit7/talkingtomcandyrun/Toast;->show(Landroid/content/Context;)V

    .line 77
    const/16 v21, 0x1

    move/from16 v0, v21

    move-object/from16 v1, p0

    iput v0, v1, Lcom/bee7/gamewall/dialogs/BannerNotificationDialog;->numberOfOffersInBannerNotification:I

但是当我尝试使用 apktool 构建它时,我收到以下消息:

com.outfit7.talkingtomcandyrun\smali\com\bee7\gamewall\dialogs\BannerNotificationDialog.smali[179,106] Invalid register: v25. Must be between v0 and v15, inclusive.

参考这一行:invoke-virtual v0, v1, Lcom/bee7/gamewall/dialogs/BannerNotificationDialog;->setContentView(I)V

为什么会出现这个错误?我什至没有在代码中看到寄存器v25

编辑:

我尝试了其他一些应用程序,发现错误总是将最高寄存器加 1。所以如果方法中的最高寄存器是v17,它会说Invalid register: v18

【问题讨论】:

它在我反编译的其他应用程序中运行良好。 【参考方案1】:

如果您查看invoke-static 操作码的文档,您会发现它使用 4 位来编码每个参数寄存器,这仅允许它引用寄存器 0-15。

p0是参数寄存器,参数寄存器在方法中“分配”的寄存器范围的末尾。

因此,如果该方法有 30 个寄存器 (.registers 30),并且它有 5 个(非长/非双精度)参数,那么该方法的参数将作为 v25-v29 传入。 pNN 寄存器只是最后这个寄存器范围的别名。所以在这种情况下,p0v25 的别名。 p1v26 等的别名。

另外,在计算参数数量时,不要忘记包含非静态方法的隐式 this 参数,它始终是第一个传递的参数。即p0

在这种情况下,最好的办法是改用invoke-static/range,它接受一个连续的寄存器范围,并且可以直接引用这些更高的寄存器。

例如

invoke-static/range p0, Lcom/outfit7/talkingtomcandyrun/Toast;->show(Landroid/content/Context;)V`

另一种选择是使用move-objectp0 中的值暂时与较低的寄存器交换,然后再将其交换回来。当然,您需要找到或创建一个未使用的寄存器才能进行交换。

【讨论】:

在我看来move-object 在这种情况下可能不起作用。至少它不适合我。它应该使用move-object/16 版本 move-object 和 move-object/16 之间的唯一区别是 move-object 仅限于源寄存器的 v0-v255。 move-object/16 可以引用整个 v0-v65535 范围。假设您会根据需要选择正确的移动对象变体。 嗯,这很奇怪,因为在我的例子中 p0 是一个 v18 寄存器,所以当我使用简单的 move-object 时应用程序没有编译。但是从您的回答中,我了解到它应该与非 /16 版本一起正常工作? 这里没有足够的上下文来回答你的问题。我建议根据您的具体情况创建一个实际问题。

以上是关于为啥这是一个无效的 smali 寄存器?的主要内容,如果未能解决你的问题,请参考以下文章

Smali语法

smali语法小结

smali文件语法

深入对android的smali的指令解析

smali 语言语法

Android: samil语法指令集-基于dex文件结构的寄存器虚拟机