Hi I am trying to understand how to properly increase the registers in a smali virtual method. In order to inject code which will use the new register
For reference i have already read the following: https://github.com/JesusFreke/smali/wiki/Registers
This is my java code:
public void toastMsg(String msg) {
Toast toast = Toast.makeText(this, msg, Toast.LENGTH_LONG);
toast.setGravity(Gravity.CENTER, 0, 0);
toast.show();
}
In Smali it looks like this
.method public toastMsg(Ljava/lang/String;)V
.locals 2
const/4 v0, 0x1
.line 26
invoke-static {p0, p1, v0}, Landroid/widget/Toast;->makeText(Landroid/content/Context;Ljava/lang/CharSequence;I)Landroid/widget/Toast;
move-result-object p1
const/4 v0, 0x0
const/16 v1, 0x11
.line 27
invoke-virtual {p1, v1, v0, v0}, Landroid/widget/Toast;->setGravity(III)V
.line 28
invoke-virtual {p1}, Landroid/widget/Toast;->show()V
return-void
.end method
Now as far as I understand it, the above smali snippet for the toastMsg method contains in total 4 registers.
.locals = 2 + 1 for the Object(this) and 1 for the parameter(String msg) to the toastMsg method.
Therefore my registers look like this
v0 - free local register
v1 - free local register
v2 => p0 (this)
v3 => p1 (the string parameter - our msg)
Now lets say I want to inject the following logcat line but I don't have any free local registers.
const-string v3, "MYAWESOMELOG"
invoke-static {v3, p1}, Landroid/util/Log;->d(Ljava/lang/String;Ljava/lang/String;)I
Injecting that logcat code would now of course clobber the v3 register, it will work but the value for p1 would be lost since v3 == p1.
I want to add one extra register to the .locals so that it can hold the string. and not clobber anything. Assuming based on the reference that i can simply bump up the number on the .locals variable it should give me n more local registers to use.
So if .locals 3 the registers in this method should now look like so
v0 - free local register
v1 - free local register
v2 - new free local register ?
v3 => p0 (this)
v4 => p1 (the string parameter - our msg)
Thus local register v2 should now be brand new and free to use if i understand this correctly.
So now the following smali code for logcat i hope can use the new register v2 to store the tag, and still retain the string parameter (p1)
const-string v2, "MYAWESOMELOG"
invoke-static {v2, p1}, Landroid/util/Log;->d(Ljava/lang/String;Ljava/lang/String;)I
Thus the modifed code now looks like this
.method public toastMsg(Ljava/lang/String;)V
.locals 3 <--- increased here by 1
const/4 v0, 0x1
.line 25
invoke-static {p0, p1, v0}, Landroid/widget/Toast;->makeText(Landroid/content/Context;Ljava/lang/CharSequence;I)Landroid/widget/Toast;
move-result-object p1
const/4 v0, 0x0
const/16 v1, 0x11
.line 26
invoke-virtual {p1, v1, v0, v0}, Landroid/widget/Toast;->setGravity(III)V
.line 27
invoke-virtual {p1}, Landroid/widget/Toast;->show()V
# PATCH here useing the new regiser
const-string v2, "MYAWESOMELOG"
invoke-static {v2, p1}, Landroid/util/Log;->d(Ljava/lang/String;Ljava/lang/String;)I
# END PATCH
return-void
.end method
Unfortuantly this doesn't seem to be the case so I assume I have not understood how to modify and use the new registers correctly.
I have rebuilt and installed my example but the application force closes due to a java class verification error.
apktool d example.apk
apktool b example -o example-modified.apk
java.lang.VerifyError: Verifier rejected class
com.example.androidtest.MainActivity: void com.example.androidtest.MainActivity.toastMsg(java.lang.String) failed to
verify: void com.example.androidtest.MainActivity.toastMsg(java.lang.String):
[0x10] register v4 has type Reference: android.widget.Toast but expected Precise Reference: java.lang.String
(declaration of 'com.example.androidtest.MainActivity' appears in
/data/app/com.example.androidtest-m1NPS9_tJaTgZLY7-1Ev6w==/base.apk)
It seems that I have messed up something with the registers but i don't quite understand where the issue is. Increasing the .locals by 1 should give me an extra register and also automatically shift the parameter references down as well therefore v4 should point to p1 and be a string but instead it is pointing to android.widget.Toast.
So am I not able to increase the .locals variable in a method and use the new register? Do i have to declare the new register and initalize it in another way?
The strange thing is that there seems to some questions already that point to the answer that I should infact be able to increase the registers.
I am pretty confident that the file was not dissasembled with the -p/--no-parameter-registers option. I just used the defaults in the apktool d
Smali: Increase number of registers
This answer also states that I should be able to actually do this https://stackoverflow.com/a/12648626/2678928
So the question is why do i not have the new register v2 when I increased the .locals variable or if I do then why are the registers not shifted down? or if all that is correct, then perhapse i have not used the correct register and also not injected the patch in the right place?