Editing Smali

Bagian ini hanya berisi trik dasar dalam unpacking/packing smali, serta beberapa modifikasi dasar yang sering saya lakukan. Sebaiknya Anda membaca resource berikut ini untuk mengenal lebih banyak mengenai bytecode dalvik:

http://stackoverflow.com/questions/5656804/whats-the-best-way-to-learn-smali-and-how-when-to-use-dalvik-vm-opcodes

Pemahaman file smali bisa dibantu dengan decompiler java: bacalah hasil dekompilasi dan bandingkan dengan file smali-nya.

Unpacking dan Packing

Untuk mengedit smali (bytecode dalvik), langkah-langkahnya adalah dengan mengubah APK menjadi banyak file smali:

apktool d appku.apk

Kadang decoding resource gagal, pastikan bahwa aapt/aapt.exe sudah menggunakan versi terbaru dari SDK Android. Jika masih gagal juga, kita bisa mengekstrak file smali tanpa mengekstrak resource:

apktool d -r appku.apk

Setelah selesai, kita akan mendapati banyak file di direktori appku . Setelah kita mengedit file smali, kita perlu mempack ulang apk tersebut, caranya:

cd appku
apktool b

Hasil file APK akan ada di apktool/dist. File tersebut belum ditandatangani secara digital dan hanya bisa diinstall di emulator. Untuk menandatangani agar bisa diinstall di device, kita perlu memiliki keystore. Anda bisa mengikuti langkah di situs Android untuk membuat keystore.

Setelah memiliki keystore, kita bisa menandatangani APK (untuk gampangnya, Anda bisa memakai password yang sama untuk keystore, key password):

 jarsigner -verbose -sigalg SHA1withRSA -digestalg SHA1 -keystore /path/to/my.keystore -storepass mypass -keypass mypass appku.apk mypass

Modifikasi dasar

Modifikasi paling dasar adalah mengubah kondisi dari true menjadi false atau sebaliknya. Ini bisa dilakukan dengan mencari kondisi, seperti ini:

if-ge v0, v2, :cond_0

Lalu mengubahnya menjadi kebalikannya. Dari tabel opcode, kita bisa tahu bahwa kebalikan if-ge adalah if-lt

if-lt v0, v2, :cond_0

Modifikasi lain adalah mengubah sebuah konstanta (misalnya kita ingin mengijinkan teks yang lebih panjang). Contohnya nilai seperti ini:

const/16 v0, 0x10

Bisa diubah menjadi:

const/16 v0, 0x100

Modifikasi yang hampir selalu saya lakukan adalah menambah logging. Jika register v0 tidak dipakai, kita bisa langsung melakukan seperti ini:

const-string v0, "JOEJOEMAP"

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

Jika ada banyak method yang ingin ditambahi lognya, biasanya saya akan menambahkan method baru ke sebuah kelas:

.method private static logShortString(Ljava/lang/String;)V
   .registers 6

   const-string v0, "JOEJOEMAP"

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

   return-void
.end method

Lalu di titik di mana saya ingin mendump variabel, saya tambahkan (ganti p1 dengan register yang ingin didump)

invoke-static {p1}, Lcom/xxx/yyy/zzz;->logShortString(Ljava/lang/String;)V

Menulis kode smali

Membuat kode smali seperti logShortString di atas gampang dilakukan karena sangat singkat. Untuk membuat kode yang lebih panjang, seperti misalnya mendump sebuah Hashtable, saya memilih menggunakan compiler java.

Pertama, tuliskan kode Java apa adanya, contohnya untuk mengubah list menjadi string (supaya bisa diprint dengan logShortString di atas):

import java.util.List;
import java.util.Iterator;

class Hello {
    private static String listToString(List l) {
        if (l==null) {
            return "<Empty List>";
        }
        Iterator iterator = l.iterator();
        StringBuilder sb = new StringBuilder();
        sb.append("List:[");
        while (iterator.hasNext()) {
            Object o = iterator.next();
            sb.append(o.toString());
            sb.append(", ");
        }
        sb.append("]");
        return sb.toString();
    }

}

Compile file tersebut dengant target bahasa Java 1.6:

javac -target 1.6 -source 1.6 Hello.java

Ubah menjadi file JAR (zip filenya):

jar cf hello.jar Hello.class

Lalu konversi menjadi APK:

/path/to/android/sdk/build-tools/android-4.4W/dx --dex --output=hello.apk hello.jar 

Ganti path android-4.4W dengan versi build-tools yang Anda miliki

Unpack lagi APK-nya menjadi file smali:

apktool d -f hello.apk

Sekarang kita memiliki kode smalli yang siap disisipkan ke file lain. Kode ini cukup panjang jika harus ditulis manual:

   .method private static listToString(Ljava/util/List;)Ljava/lang/String;
       .locals 3

       .prologue
       .line 39
       if-nez p0, :cond_0

       .line 40
       const-string v0, "<Empty List>"

       .line 51
       :goto_0
       return-object v0

       .line 42
       :cond_0
       invoke-interface {p0}, Ljava/util/List;->iterator()Ljava/util/Iterator;

       move-result-object v0

       .line 43
       new-instance v1, Ljava/lang/StringBuilder;

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

       .line 44
       const-string v2, "List:["

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

       .line 45
       :goto_1
       invoke-interface {v0}, Ljava/util/Iterator;->hasNext()Z

       move-result v2

       if-eqz v2, :cond_1

       .line 46
       invoke-interface {v0}, Ljava/util/Iterator;->next()Ljava/lang/Object;

       move-result-object v2

       .line 47
       invoke-virtual {v2}, Ljava/lang/Object;->toString()Ljava/lang/String;

       move-result-object v2

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

       .line 48
       const-string v2, ", "

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

       goto :goto_1

       .line 50
       :cond_1
       const-string v0, "]"

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

       .line 51
       invoke-virtual {v1}, Ljava/lang/StringBuilder;->toString()Ljava/lang/String;

       move-result-object v0

       goto :goto_0
   .end method

Copyright © 2009-2010 Yohanes Nugroho