【问题标题】:How to debug smali code of an android application?如何调试android应用程序的smali代码?
【发布时间】:2014-01-02 09:35:19
【问题描述】:

我有一个工作的 android 应用程序。其中我没有源代码。 我想调试这个应用程序的功能。我可以使用 apktool 成功地对这个应用程序 apk 文件进行逆向工程 - https://code.google.com/p/android-apktool/ 该工具生成 smali 格式的类文件。

我的要求是:

  1. 能够通过添加调试日志来调试方法。
  2. 能够通过打印堆栈跟踪来调试方法调用。

为了实现这一点,我需要注入/插入与调试日志或堆栈跟踪等效的 smali。我尝试在其中一种方法的开头添加一些 smali 指令,但它因 ClassVerifyError 而崩溃。

示例 smali 代码 -

.method public declared-synchronized b()V
    .locals 2

    .prologue

    .line 87
    monitor-enter p0

    :try_start_0
    iget-object v0, p0, Lcom/example/viewerlib/t/d;->a:Ljava/lang/Thread;

    invoke-virtual {v0}, Ljava/lang/Thread;->isAlive()Z

               :
               :

谁能帮我添加 smali 调试日志。提前谢谢。

【问题讨论】:

  • 原来这个应用是用 Smali 写的?
  • 这不是我的应用程序。这是普通的安卓应用程序。我们可以使用apktool反编译apk,它从apk中的classes.dex生成smali代码。
  • 不!它也可以生成Java代码,使用Dex to Jar。完成后使用 JD-GUI。
  • 但如果他将其转换为 Java,他可以在 Eclipse IDE 本身中完成这一切。从好的方面来说,只要付出更多的努力,他也可以获得 XML 文件和资产!
  • @AstralProjection 从 smali 构造 java 代码是可以做到的,但如果方法/类很大,那就更乏味了。相反,正如他指出的那样,为了理解应用程序本身的功能,在运行时打印变量值可能更有用。构建 java 代码仅在一个解耦功能的情况下才有效。对于一个完整的应用程序,他必须在运行时进行调试以检查是否相同。

标签: android apk dex smali


【解决方案1】:

1. smali调试日志

在 smali 中调试日志。例如,在方法 test() 中,您要打印“Inside Test()”调试日志。在 smali 方法的开头添加以下说明:

sget-object v0, Ljava/lang/System;->out:Ljava/io/PrintStream;

const-string v1, "Inside Test()"

invoke-virtual {v0, v1}, Ljava/io/PrintStream;->println(Ljava/lang/String;)V

注意 - 在此处使用寄存器 v0、v1 时需要小心。在代码执行流程中,您必须检查您没有使用稍后在流程中使用的寄存器之一。或者你可能会得到异常。

2。堆栈跟踪

这是 smali 打印方法堆栈跟踪的代码

Java 代码

public static void printStackTraces() {
    StackTraceElement[] stackTraceElements = Thread.currentThread().getStackTrace(); 
    for (StackTraceElement element : stackTraceElements) {
        System.out.println("Class name :: " + element.getClassName() + "  || method name :: " + element.getMethodName());
    }
}

和等效的smali代码是

.method public static printStackTraces()V
    .locals 7

    .prologue
    .line 74
    invoke-static {}, Ljava/lang/Thread;->currentThread()Ljava/lang/Thread;

    move-result-object v2

    invoke-virtual {v2}, Ljava/lang/Thread;->getStackTrace()[Ljava/lang/StackTraceElement;

    move-result-object v1

    .line 75
    .local v1, stackTraceElements:[Ljava/lang/StackTraceElement;
    array-length v3, v1

    const/4 v2, 0x0

    :goto_0
    if-lt v2, v3, :cond_0

    .line 78
    return-void

    .line 75
    :cond_0
    aget-object v0, v1, v2

    .line 76
    .local v0, element:Ljava/lang/StackTraceElement;
    sget-object v4, Ljava/lang/System;->out:Ljava/io/PrintStream;

    new-instance v5, Ljava/lang/StringBuilder;

    const-string v6, "Class name :: " 

    invoke-direct {v5, v6}, Ljava/lang/StringBuilder;-><init>(Ljava/lang/String;)V

    invoke-virtual {v0}, Ljava/lang/StackTraceElement;->getClassName()Ljava/lang/String;

    move-result-object v6

    invoke-virtual {v5, v6}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;

    move-result-object v5

    const-string v6, "  || method name :: " 

    invoke-virtual {v5, v6}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;

    move-result-object v5

    invoke-virtual {v0}, Ljava/lang/StackTraceElement;->getMethodName()Ljava/lang/String;

    move-result-object v6

    invoke-virtual {v5, v6}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;

    move-result-object v5

    invoke-virtual {v5}, Ljava/lang/StringBuilder;->toString()Ljava/lang/String;

    move-result-object v5

    invoke-virtual {v4, v5}, Ljava/io/PrintStream;->println(Ljava/lang/String;)V

    .line 75
    add-int/lit8 v2, v2, 0x1

    goto :goto_0
.end method

将此方法添加到任何 smali 文件中。并调用为

(假设您将上述 smali 代码添加到 com.example.pakagename.ClassName 中)

invoke-static {}, Lcom/example/packagename/ClassName;->printStackTraces()V

希望这会有所帮助.....

【讨论】:

  • 好东西,你的Note 部分说的是程序员在修改smali 代码时最常犯的错误。 +1
  • 谢谢,我试试这个。
  • 我遇到了以下异常:no viable alternative at input 'stackTraceElements'no viable alternative at input 'stackTraceElements' ... 只需将 .local v1, stackTraceElements:[Ljava/lang/StackTraceElement; 更新为 .local v1, "stackTraceElements":[Ljava/lang/StackTraceElement; 并将 .local v0, element:Ljava/lang/StackTraceElement; 更新为 .local v0, "element":Ljava/lang/StackTraceElement; 看起来好像有一个.local 变量的语法更新
【解决方案2】:

如果您喜欢 IntellijIdea,请给smalidea 一个机会!

【讨论】:

    【解决方案3】:

    我建议使用 sony 的 apkanalyzer:

    https://github.com/sonyxperiadev/ApkAnalyser

    它允许您反编译 apk-s 并读取 smali 代码,将打印语句插入到各个位置。有菜单选项:“打印自定义日志”,您还可以打印堆栈跟踪,并做很多其他事情。完成所有更改后,您只需按 Device->Install 并启动 apk。全部来自 GUI。

    【讨论】:

      【解决方案4】:

      嘿,我在想你可能会发现这个工具很有帮助

      它将任何apk文件反编译为java编写的代码类

      检查此链接并尝试一下

      http://forum.xda-developers.com/showthread.php?t=2430413

      【讨论】:

        【解决方案5】:

        很抱歉指出 apkanalyzer 是一个 ststic 分析器 为了理解和编辑 smali 代码,请尝试以下操作

        http://themasterofmagik.wordpress.com/2014/03/08/decompilerecompile-an-apk-basic-editing/

        它解释了各种场景中的编辑。 使用什么工具以及何时使用。

        反编译/重新编译 apk 的不同方法

        a. apk
            1. apktool + Notepad++
            2. Virtuous Ten Studio
            3. AndroChef Java Decompiler
        b. classes.dex
            1. smali/baksmali
            2. dex2jar + JD-GUI
        

        【讨论】:

          【解决方案6】:

          我尝试使用 smalidea 插件,但无法使其正常工作,因此尝试了以下不同的方法。

          Android Studio 3.1.2 中有一个选项,Go to File -> Select Profile or Analyze Apk 选项。然后它将在 classes.dex 文件和包含 smali 文件的 out 文件中反编译 Apk。然后您可以 Rus As-> Debug 选项并将断点放在任何 smali 文件中,它将在指定的断点处停止。这仅在您的应用程序中有单个 dex 文件时才有效。然而,有一个多 dex 应用程序的解决方法,您需要按照以下步骤操作 -

          1) 从here下载Apktool工具

          2) 使用 -> apktool d 反编译 Apk

          3) 将上面生成的smali文件全部复制到多个文件夹smali, smali_classess2, smali_classes3等到Android Studio创建的out文件夹中-> 前面分析Apk方法,这样所有smali文件都在一个文件夹中

          4) 这一步我不确定是否需要,但我已经遵循了这一点,请随时验证这一步。在这里,您再次使用 apktool 使用在步骤 2 中使用 command -> apktool b 创建的文件夹来构建 Apk。这将生成所有 .dex 文件并将所有文件复制到之前使用分析 Apk 方法生成单个 classes.dex 文件的同一位置。

          5) 现在使用使用 Analyze Apk 方法创建的同一个项目,您就可以调试了。

          附: - Android Studio 会抱怨使用 Java 代码进行调试,但这种方法会起作用。此方法仅在您正在编辑任何 smali 文件并要对其进行调试时才有用。

          【讨论】:

            猜你喜欢
            • 2021-09-08
            • 1970-01-01
            • 1970-01-01
            • 2016-07-09
            • 2013-08-18
            • 1970-01-01
            • 2014-11-04
            • 2016-10-11
            • 1970-01-01
            相关资源
            最近更新 更多