如何调试android应用程序的smali代码?

时间:2014-01-02 09:35:19

标签: android apk dex smali

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

我的要求是:

  1. 能够通过添加调试日志来调试方法。
  2. 能够通过打印堆栈跟踪来调试方法调用。
  3. 为了实现这一点,我需要注入/插入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调试日志。 Thnx提前。

7 个答案:

答案 0 :(得分:25)

<强> 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());
    }
}

等效的小代码是

.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

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

答案 1 :(得分:3)

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

答案 2 :(得分:3)

现在,您可以使用适用于Android Studio或Intellij IDEA的精彩插件 - Smalidea。此外,我已在blog post.

中描述了安装过程和调试

答案 3 :(得分:2)

我建议使用sony的apkanalyzer:

https://github.com/sonyxperiadev/ApkAnalyser

它允许您反编译apk-s并读取smali代码,将print语句插入到各个地方。有菜单选项:“打印自定义日志”,您还可以打印堆栈跟踪,并执行许多其他操作。完成所有更改后,只需按设备 - >安装并启动apk即可。全部来自GUI。

答案 4 :(得分:2)

嘿,我以为你可能会觉得这个工具很有帮助

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

检查此链接并尝试一下

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

答案 5 :(得分:1)

很抱歉指出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 :(得分:0)

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

Android Studio 3.1.2中有一个选项,转到文件->选择配置文件或分析Apk选项。然后它将反编译Apk in classes.dex文件和out文件,后者将包含smali文件。然后,您可以在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文件都位于单个文件夹中< / p>

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

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

P.S。 -Android Studio会抱怨使用Java代码进行调试,但是这种方法可以工作。仅当您正在编辑任何smali文件并希望对其进行调试时,此方法才有用。