Увеличьте местные регистры в Smali и используйте новый регистр

Привет, я пытаюсь понять, как правильно увеличить регистры в виртуальном методе smali. Чтобы внедрить код, который будет использовать новый регистр

Для справки я уже прочитал следующее: https://github.com/JesusFreke/smali/wiki/Registers

Это мой код Java:

    public void toastMsg(String msg) {

        Toast toast = Toast.makeText(this, msg, Toast.LENGTH_LONG);
        toast.setGravity(Gravity.CENTER, 0, 0);
        toast.show();

    }

На смали это выглядит так

.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

Теперь, насколько я понимаю, приведенный выше небольшой фрагмент для метода toastMsg содержит всего 4 регистра.

.locals = 2 + 1 для объекта (этот) и 1 для параметра (строка msg) метода toastMsg.

Поэтому мои регистры выглядят так

v0 - free local register
v1 - free local register
v2 => p0 (this)
v3 => p1 (the string parameter - our msg)

Теперь предположим, что я хочу ввести следующую строку logcat, но у меня нет свободных локальных регистров.

const-string v3, "MYAWESOMELOG"
invoke-static {v3, p1}, Landroid/util/Log;->d(Ljava/lang/String;Ljava/lang/String;)I

Внедрение этого кода logcat теперь, конечно, уничтожит регистр v3, он будет работать, но значение для p1 будет потеряно, поскольку v3 == p1.

Я хочу добавить один дополнительный регистр в .locals, чтобы он мог хранить строку. и ничего не заморачиваться. Предполагая, основываясь на ссылке, что я могу просто увеличить число в переменной .locals, это должно дать мне больше локальных регистров для использования.

Итак, если .locals 3, регистры в этом методе теперь должны выглядеть так

v0 - free local register
v1 - free local register
v2 - new free local register ?
v3 => p0 (this)
v4 => p1 (the string parameter - our msg)

Таким образом, локальный регистр v2 теперь должен быть совершенно новым и бесплатным, если я правильно понимаю.

Итак, теперь следующий код smali для logcat, я надеюсь, может использовать новый регистр v2 для хранения тега и по-прежнему сохранять строковый параметр (p1)

 const-string v2, "MYAWESOMELOG"
    invoke-static {v2, p1}, Landroid/util/Log;->d(Ljava/lang/String;Ljava/lang/String;)I

Таким образом, измененный код теперь выглядит так

.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

К сожалению, похоже, это не так, поэтому я предполагаю, что не понял, как правильно изменять и использовать новые регистры.

Я перестроил и установил свой пример, но приложение закрывается из-за ошибки проверки класса Java.

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)

Кажется, я что-то напутал с регистрами, но я не совсем понимаю, в чем проблема. Увеличение .locals на 1 должно дать мне дополнительный регистр, а также автоматически сместить ссылки на параметры вниз, поэтому v4 должен указывать на p1 и быть строкой, но вместо этого он указывает на android.widget.Toast.

Итак, я не могу увеличить переменную .locals в методе и использовать новый регистр? Должен ли я объявлять новый регистр и инициализировать его другим способом?

Странно то, что, кажется, некоторые вопросы уже указывают на ответ, что я действительно должен иметь возможность увеличивать регистры.

Я почти уверен, что файл не был дизассемблирован с опцией -p/--no-parameter-registers. Я просто использовал значения по умолчанию в apktool d

Smali: увеличить количество регистров

В этом ответе также говорится, что я должен быть в состоянии сделать это https://stackoverflow.com/a/12648626/2678928

Итак, вопрос в том, почему у меня нет нового регистра v2, когда я увеличил переменную .locals, или если есть, то почему регистры не сдвинуты вниз? или если все верно, то может я не тот регистр использовал и патч не туда вставил?


person Sevren    schedule 10.05.2019    source источник
comment
Хороший вопрос :)   -  person JesusFreke    schedule 10.05.2019


Ответы (2)


Проблема с этой инструкцией

invoke-static {v2, p1}, Landroid/util/Log;->d(Ljava/lang/String;Ljava/lang/String;)I

Вы передаете p1 в качестве второго аргумента, но p1 по-прежнему содержит объект всплывающего уведомления. Метод ожидает строковый объект для второго аргумента, а не всплывающий объект.

person JesusFreke    schedule 10.05.2019

Проблема была именно в том, что описал JesusFreke, но я также исправил код не в том месте. Я пытался вызвать метод Log и не понял, что к концу функции тип p1 изменился со String на android/widget/Toast.

Следующие работы с использованием нового регистра v2

.method public toastMsg(Ljava/lang/String;)V
    .locals 3

    const/4 v0, 0x1

    .line 26

    # PATCH HERE
    const-string v2, "MYAWESOMELOG"
    invoke-static {v2, p1}, Landroid/util/Log;->d(Ljava/lang/String;Ljava/lang/String;)I
    # END PATH

    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

Вот более подробное объяснение:

Увеличение .locals работает как обычно и выглядит так в начале вызова метода toastMsg

v0 - free local register
v1 - free local register
v2 - free local register
v3 => p0 (this)
v4 => p1 (the string parameter - our msg)

Однако следующие строки теперь изменяют значения в регистре, обратите внимание, что v4 == p1 Перед выполнением этих строк v4(p1) указывает на строковый объект (наш параметр msg)

invoke-static {p0, p1, v0}, Landroid/widget/Toast;->makeText(Landroid/content/Context;Ljava/lang/CharSequence;I)Landroid/widget/Toast;

move-result-object p1

После move-result-object p1 во фрагменте кода выше значение в регистрах теперь выглядит так

v0 - 0x1
v1 - free local register
v2 - "MYAWESOMELOG"
v3 => p0 (this)
v4 => p1 (android/widget/Toast)

У нас больше нет исходного строкового значения, которое было передано в метод toastMsg.

Если бы я хотел использовать исходное значение p1, мне пришлось бы использовать его ДО строки move-result-object p1. В качестве альтернативы я мог бы снова увеличить локальные значения и скопировать/сохранить результат p1 в начале функции.

person Sevren    schedule 11.05.2019