Search code examples
androidapkdexsmali

How to debug smali code of an android application?


I have a working android application. of which i dont have a source code. I would like to debug a functionality of this application. I could successfully reverse engineer this application apk file using apktool - https://code.google.com/p/android-apktool/ This tool generates class files in smali format.

My requirement is :

  1. To be able to debug a method by adding debug logs.
  2. To be able to debug method calls by printing a stack trace.

To achieve this I need to inject/insert smali equivalent of a debug log or stack trace. I tried adding some smali instruction at the start of one of the method but it crashed with ClassVerifyError.

Example smali code -

.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

               :
               :

Could someone help me out in adding smali debug logs. Thnx in advance.


Solution

  • 1. Debug log in smali

    Debug log in smali. Say for example inside method test() you want to print "Inside Test()" debug log. At the start of method in smali add following instructions :

    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
    

    Note - You need to be careful while using registers v0,v1 here. In code execution flow, you have to check that you are not using one of the register which is used later in the flow. Or you may get Exception.

    2. StackTrace

    Here is the code of smali to print stacktrace of a method

    Java code

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

    And equivalent smali code is

    .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
    

    Add this method into any smali file. And call as

    (Assuming you added above smali code into com.example.pakagename.ClassName)

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

    Hope this helps .....