Увеличьте местные регистры в Смали и используйте новый регистр - PullRequest
2 голосов
/ 10 мая 2019

Привет. Я пытаюсь понять, как правильно увеличить регистры в 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();

    }

В Smali это выглядит так:

.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

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

.locals = 2 + 1 для объекта (this) и 1 для параметра (String 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, или, если я это сделаю, почему регистры не сдвинуты вниз?или если все правильно, то, возможно, я не использовал правильный регистр и тоже не вставил патч в нужное место?

Ответы [ 2 ]

1 голос
/ 10 мая 2019

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

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

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

0 голосов
/ 11 мая 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 в начале функции.

...