为什么这是一个无效的 smali 寄存器?
Why is this an invalid smali register?
我在反编译的应用程序中注入了这段代码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
.
如果你查看 invoke-static
操作码的文档,你会发现它使用 4 位来编码每个参数寄存器,这只允许它引用寄存器 0-15。
p0
为参数寄存器,方法中参数寄存器在"allocated"寄存器范围的末尾。
因此,如果该方法有 30 个寄存器 (.registers 30
),并且有 5 个 (non-long/non-double) 个参数,那么方法的参数将作为 v25- v29。 pNN
寄存器只是这个寄存器范围末尾的别名。所以在这种情况下,p0
是 v25
的别名。 p1
是 v26
等的别名
此外,在计算参数数量时,不要忘记包含非静态方法的隐式 this
参数,它始终是第一个传递的参数。即 p0
在这种情况下,最好的办法是改用 invoke-static/range,它接受连续范围的寄存器,并且可以直接引用这些更高的寄存器。
例如
invoke-static/range {p0}, Lcom/outfit7/talkingtomcandyrun/Toast;->show(Landroid/content/Context;)V`
另一种选择是使用move-object
暂时将p0
中的值与较低的寄存器交换,然后再将其交换回来。当然,您需要找到或创建一个未使用的寄存器才能进行交换。
我在反编译的应用程序中注入了这段代码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
.
如果你查看 invoke-static
操作码的文档,你会发现它使用 4 位来编码每个参数寄存器,这只允许它引用寄存器 0-15。
p0
为参数寄存器,方法中参数寄存器在"allocated"寄存器范围的末尾。
因此,如果该方法有 30 个寄存器 (.registers 30
),并且有 5 个 (non-long/non-double) 个参数,那么方法的参数将作为 v25- v29。 pNN
寄存器只是这个寄存器范围末尾的别名。所以在这种情况下,p0
是 v25
的别名。 p1
是 v26
等的别名
此外,在计算参数数量时,不要忘记包含非静态方法的隐式 this
参数,它始终是第一个传递的参数。即 p0
在这种情况下,最好的办法是改用 invoke-static/range,它接受连续范围的寄存器,并且可以直接引用这些更高的寄存器。
例如
invoke-static/range {p0}, Lcom/outfit7/talkingtomcandyrun/Toast;->show(Landroid/content/Context;)V`
另一种选择是使用move-object
暂时将p0
中的值与较低的寄存器交换,然后再将其交换回来。当然,您需要找到或创建一个未使用的寄存器才能进行交换。