Reverse Engineering APK

Saya sudah menulis beberapa artikel terpisah mengenai reverse engineering APK Android (misalnya di http://yohan.es/security/android/) . Di posting ini saya ingin menggabungkan berbagai tulisan yang pernah saya buat dalam satu posting, supaya lebih gampang dibaca. Topik yang lebih umum mengenai Pengantar Reverse Engineering sudah pernah saya bahas di blog ini (tidak spesifik Android).

 

Tujuan Reversing

Pertama, tentukan tujuannya apa ingin bisa reversing APK. Ini bisa digolongkan jadi dua bagian: apakah ingin mengetahui cara kerjanya? (sekedar membaca kode) atau ingin mengubah aplikasinya? (memodifikasi kode) Yang termasuk dalam kategori pertama: apakah ingin ekstrak API-nya, ingin membaca file yang dibuat oleh aplikasi, ingin tahu protokol aplikasi.

Tujuan yang kedua lebih rumit: intinya ingin memodifikasi aplikasi. Beberapa tujuannya: memperbaiki bug, mengubah sifat aplikasi, menambah fitur, mencurangi game, dsb.

APK itu apa?

Pertama APK itu apa? APK adalah format aplikasi Android, berupa file ZIP yang di dalamnya ada classes.dex yang berisi kode Java, resource dalam bentuk XML (yang diencode khusus), file-file gambar, video, suara, dsb.

Isi APK dilihat dengan 7-ZIP

Selain itu ada juga bagian lain seperti native code (kode dalam bahasa mesin) yang ditulis dalam C/C++/Rust atau bahasa lain. Jika APK dibuat dengan teknologi selain Java, maka kemungkinan ada file-file dalam bahasa lain (misalnya pyc untuk Python, JS untuk JavaScript dsb).

Isi APK dilihat dengan JADX-GUI

Bagaimana APK dibuat?

APK dibuat dari kode program yang umumnya ditulis dalam bahasa Java dan C/C++, tapi tidak selalu harus demikian. APK bisa dibuat dengan kode HTML dan JavaScript, dari kode Python, Ruby, Unity, dsb. Semuanya sangat fleksibel.

Sebenarnya yang didukung langsung oleh Android hanya bisa ada dua jenis kode: Java atau Native. Native artinya kode yang dikompilasi ke bahasa mesin, biasanya ditulis dalam bahasa C/Assembly. Tapi baik kode Java maupun Native bisa meload interpreter bahasa lain, misalnya dari Java kita bisa langsung menggunakan komponen WebView yang mendukung JavaScript. Dari Java kita juga bisa menggunakan library JRuby/JPython untuk menjalankan kode Ruby/Python (dan masih banyak juga library untuk bahasa lain). Dari bahasa C kita juga bisa meload library apapun (termasuk juga interpreter Python, Ruby, Lua, dsb) dan menjalankan kode dalam bahasa itu.

Tapi fakta ini disembunyikan jika kita menggunakan tools tertentu. Misalnya ketika memakai cordova, maka kode Java disembunyikan dari programmer, dan programmer hanya memikirkan kode dalam HTML/JavaScript saja. Demikian juga dengan Unity, programmer tidak akan melihat kode Java dan Native yang disertakan oleh unity untuk menjalankan kode .NET.

Kode Java akan dikompilasi menjadi .class (file Class Java) lalu dikonversi menjadi bytecode dalvik.   Satu aplikasi terdiri dari banyak kelas dan semua ini disimpan dalam file DEX. Bytecode dalvik ini sifatnya biner, agar lebih mudah dibaca, dibuatlah format kode smali yang berupa teks. Dengan format smali, bytecode menjadi lebih mudah diedit.

Supaya lebih terbayang, berikut ini contoh kode dalam bahasa Java

    public int nextInt(int i) {
                return f++;
   }

Versi .class (bytecode Java):

  public int nextInt(int);
    Code:
       0: getstatic     #2                  // Field f:I
       3: dup
       4: iconst_1
       5: iadd
       6: putstatic     #2                  // Field f:I
       9: ireturn

Versi smali

.method public nextInt()I
    .locals 2
    .prologue
    .line 15
    sget v0, LMyRandom;->f:I
    add-int/lit8 v1, v0, 0x1
    sput v1, LMyRandom;->f:I
    return v0
.end method

Ketika sebuah aplikasi dibongkar, maka minimal ada sedikit kode Java. Lebih tepatnya lagi dari DEX kita bisa kembalikan menjadi file-file .class atau .smali, dan dengan decompiler biasanya bisa dikembalikan ke java.

Jika APK tidak dibuat dengan bahasa Java (misalnya dengan JavaScript), maka biasanya logika utama aplikasi berada di file lain (dalam kasus JavaScript ya di kode JavaScript), dan file Java ini hanya me-load file tersebut.

Membaca Source Code

Sebelum membongkar sebuah APK. Coba tanyakan dulu pada diri sendiri: andaikan saya diberikan source code lengkap sebuah aplikasi, apakah saya bisa akan paham? Andaikan diberi source code yang diberi nama jelas, diberi komentar, diberi dokumentasi tetap belum bisa mengerti, maka sebaiknya Anda kembali ke dasar dulu.

Intinya tool-tool untuk membongkar APK maksimum hanya akan bisa mengembalikan menjadi source code. Bahkan terkadang jika ada proteksi tertentu, source codenya bahkan bisa salah, sulit dimengerti, atau bahkan source code tidak bisa dihasilkan sama sekali, dan kita harus melihat ke smali code. Jadi jika memabaca source code saja tidak bisa dimengerti, maka langkah berikutnya akan sulit.

Mendapatkan APK

Sekarang jika sudah siap reverse engineering APK. Pertama adalah mendapatkan APK. Ini bisa didapatkan dari berbagai situs, misalnya APKPure. Perhatikan APK yang didapat mungkin bukan yang terbaru di Play Store.

APK juga bisa diterima dari programmer yang mengirimkan Anda file APK-nya. Pada kegiatan pentest, biasanya metode ini yang dipakai karena aplikasi belum diterbitkan.

Contoh ekstraksi APK

APK juga bisa diekstrak dari aplikasi yang sudah terinstall di  handphone dengan berbagai aplikasi  di handphone (misalnya Apk Extractor, ES File Explorer, dsb). APK juga bisa diambil dari desktop melalui Android Debug Bridge (ADB).

Android Debug Bridge (ADB)

Sebelum Anda mulai lebih jauh, pelajari juga tools dasar Android, terutama ADB. Carilah cara untuk mengaktifkan developer mode pada ponsel Anda, dan ikuti tutorial untuk menjalankan ADB, masuk ke shell adb, mem-push dan pull file ke/dari device, menginstall dan uninstall APK. Untuk device tertentu kadang Anda perlu menginstall device driver khusus untuk bisa melakukan koneksi ke ADB.

Contoh akses shell dengan adb

Hal penting lain adalah mendapatkan log dengan adb logcat dan memfilter isi log. Kemungkinan besar aplikasi akan crash ketika dimodifikasi, jadi mengetahui log akan membantu mencari tahu di mana crash terjadi. Membaca log juga akan membantu untuk memahami aplikasi.

Ekstraksi APK

Sekarang APK bisa diekstrak dengan apktool. Tool ini adalah tool command line yang sangat dasar. Ada beberapa tool lain yang “membungkus” tool ini agar lebih mudah dipakai dengan klik saja. Menurut saya, jika masih pemula, justru bagus untuk bisa mengetahui cara manual ekstraksi file.

Untuk orang yang tujuannya hanya ingin memahami kode Java saja, maka tool jadx akan lebih mudah dipakai. Tool ini juga memiliki GUI yang memudahkan kita membuka file dan melakukan dekompilasi langsung menjadi kode dalam Java. Tool ini memiliki kelemahan: ketika kode dipoteksi maka akan sulit memahami kodenya. Kelemahan lainnya adalah: kita tidak bisa memodifikasi kodenya, ini hanya sekedar untuk melihat saja.

Sebagai catatan: sebagian orang suka menggunakan dua langkah: dex2jar yang akan mengubah APK menjadi file  Jar (yang berisi file .class Java), lalu mendekompilasi file jar-nya dengan decompiler Java (misalnya JD atau CFR).

Perhatikan bahwa jika program tidak ditulis dalam bahasa Java, maka Anda harus memakai tools lain untuk reverse engineering. Beberapa teknologi yang pernah saya temui misalnya:

  • Unity. Ada yang masih memakai kode .NET, dan ada yang dikompilasi menjadi native code dengan il2cpp.
  • HTML/JS (Apache Cordova)
  • Ruby
  • Python
  • Cocos-2DX (native code), kadang dicampur Lua

Teknologi non-Java berada di luar scope posting blog ini. Jika memang tertarik, carilah informasi di internet mengenai masing-masing teknologi untuk tahu cara membongkarnya.

Memahami Program

Jika sudah berhasil diekstrak, maka langkah berikutnya adalah memahami programnya. Bagian ini adalah tersulit. Kembali lagi ke nasihat awal: jika diberikan source code sebuah program apakah Anda bisa mengerti? Jika dihapus semua nama fungsi-nya dan diganti dengan “a”, “b”, “c” apakah kira-kira Anda masih mengerti bahwa sebuah kode melakukan “sorting” atau “searching”?

Selain dengan membaca kode, seorang programmer bisa berusaha memahami program dengan menggunakan “debugger”. Ini juga bisa diaplikasikan ketika melakukan reverse engineering: debugger bisa membantu memahami cara kerja program. Selain itu programmer juga bisa menambahkan logging untuk membantu memahami alur program.

Seorang programmer yang baik akan menggunakan berbagai library yang populer. Pengetahuan mengenai library populer ini akan sangat berguna ketika mereverse engineer sesuatu. Kita bisa mengabaikan banyak kode yang bukan inti dari aplikasi. Misalnya jangan sampai pusing  dan berkutat membaca kode di package android.support.

Modifikasi kode

Sama halnya dengan modifikasi kode: jika ada kode open source di github, apakah Anda bisa menambahkan sendiri fitur yang Anda inginkan? misalnya sekedar mengganti teks, memindahkan tombol, menambah tombol. Jika jawabannya adalah: tidak bisa, maka memodifikasi APK juga akan sulit dilakukan.

Beberapa modifikasi sederhana, seperti bypass root checking, atau SSL Pinning mungkin masih bisa dilakukan dengan sekedar mengubah sebuah kondisi atau if. Tapi modifikasi seperti: mengganti user interface atau menambahkan fitur baru akan sangat sulit dilakukan jika Anda tidak mengerti bagaimana memprogram Android.

Jika ingin mulai dengan benar, belajarlah dulu membuat Aplikasi Android dasar. Materi untuk ini bisa didownload secara gratis. Tutorial dalam bentuk video juga banyak tersedia. Beberapa cara modifikasi APK baik secara permanen maupun temporer pernah saya tuliskan di sini.

Sangat sering saya temui orang yang ingin memodifikasi APK tapi masih bingung dengan konsep app signing. Bertanya: kenapa hasil modifikasi saya nggak  bisa diinstall? (masih lebih bagus jika pertanyaannya eksak seperti ini, ada yang bertanya: kenapa aplikasi saya nggak jalan? lalu setelah muter nanya jauh, ternyata maksudnya tidak bisa diinstall). Tanpa modifikasi apapun, jika aplikasi diunpack dan dipack ulang tapi tidak disign maka tidak bisa diinstall (dengan perkecualian Androidnya sudah dipatch dengan aplikasi tertentu agar mengabaikan code signing, tapi ini berbahaya dari segi security).

Sebelum belajar melakukan modifikasi, minimal belajar dulu packaging ulang aplikasi: ekstrak aplikasi, tidak usah dimodifikasi, lalu package ulang, sign ulang dan install ulang. Pelajari apa itu “signing”, dan bagaimana caranya signing aplikasi. Program tanpa proteksi harusnya akan berjalan normal setelah repackage (tanpa modifikasi).

Jika aplikasi berjalan normal ketika direpackage sebelum dimodifikasi, tapi  kemudian program crash setelah dimodifikasi maka kemungkinan Anda salah memodifikasi. Lihat pesan pada logcat untuk mencari tahu kenapa.

Proteksi

Untuk aplikasi yang diproteksi, maka proses reverse engineerig menjadi lebih sulit. Misalnya proteksi yang paling sederhana sekedar obfuscation. Nama-nama method dan variabel diubah agar sulit dimengerti. Ini bisa sekedar menjadi a,b,c, d tapi juga agar namanya tidak valid untuk OS Windows (misalnya CON atau NUL).

Contoh kode yang gagal didekompilasi

Proteksi tingkat lanjut juga ada, misalnya dengan mengenkrip kode program yang kemudian diload ketika program berjalan. Di tingkat yang lebih lanjut lagi, digunakan native code sehingga harus melihat kode assembly (bahasa mesin) bukan sekedar kode smali.

Ketika proteksi mulai digunakan, maka yang berikutnya dipahami adalah berbagai trik dan pengalaman. Misalnya konstanta MD5/SHA1/AES bisa digunakan untuk mencari tahu algoritma apa yang digunakan. Kadang yang paling mudah adalah dari berbagai string yang muncul dalam sebuah method, misalnya ada pesan tentang error AES, maka kemungkinan kelas itu berhubungan dengan enkripsi AES. Bahkan kemungkinan besar seluruh package tempat kelas tersebut berada berhubungan dengan AES.

Menelusuri Kode

Ketika seseorang bertanya: kok tahu kalau kode enkripsinya ada di kelas yang ini? Jawabannya biasanya adalah: dari pengalaman dan dari penelusuran kode program.

Yang saya maksud dengan menelusuri kode adalah membaca secara manual dan kadang dicampur dengan logging untuk melihat apakah method tertentu dipanggil. Contohnya begini: jika kita tahu di Activity tertentu teks dimasukkan (dalam bentuk plaintext alias belum dienkrip), dan ketika di kirimkan melalui HTTP sudah terenkrip, maka kita bisa menelusuri method yang dipanggil sampai data terkirim untuk mencari di mana method enkripsi.

Secara umum, computational thinking membantu sekali karena ini seperti menyelesaikan sebuah puzzle. Kadang kita harus menelusuri dari belakang, dari depan, atau dari tengah.

Library

Pemakaian library tertentu menunjukkan programmer menggunakan paradigma tertentu dalam memprogram. Contohnya adalah jika library RX Java digunakan maka reactive programming digunakan.

Penggunakan AspjectJ menunjukkan bahwa Aspect Oriented Programming digunakan. Dalam kasus seperti ini, pengetahuan mengenai berbagai paradigma pemrograman akan sangat berguna.

Malware Android

Berbagai malware memiliki proteksi yang di atas rata-rata software biasa. Proteksi malware tertentu sangat kompleks, karena mungkin hanya menargetkan HP jenis tertentu, dan jika crash ya sudah (emangnya ada yang mau kirim bug report?), jadi berbagai proteksi yang sifatnya advanced bisa diterapkan. Kebanyakan malware juga memakai native code yang mempersulit reverse engineering kodenya.

Banyak software banking juga memiliki proteksi tapi biasanya lebih mudah dari malware, karena sebuah aplikasi banking dibatasi oleh beberapa hal: mereka ingin aplikasinya tetap berjalan di berbagai ponsel, mereka tidak ingin terdeteksi sebagai malware, mereka tidak ingin aplikasi menjadi terlalu lambat, mereka tetap ingin bisa mendebug aplikasi jika ada masalah.

Jadi secara umum: membongkar malware levelnya lebih susah. Sebuah malware juga kadang mengandung exploit yang mewajibkan kita mengerti internal Android untuk bisa mengerti eksploitnya.

Security

Jangan kira jika sudah berhasil membongkar sebuah APK kita pasti bisa menemukan masalah security. Sebuah APK biasanya hanyalah salah satu “client” dari sebuah aplikasi server. Artinya segala pemrosesan dilakukan di server, dan jika aplikasinya bagus, maka bagaimanapun kita akali, tetap akan dicek di server.

Contohnya dalam aplikasi banking: jika kita bisa mengubah request kita ke bank, maka seharusnya tidak mungkin kita mengubah jumlah saldo, nilai transaksi, nomor rekening, dsb.

Tapi bukan berarti kita langsung menyerah membongkar APK penting karena dianggap sudah aman. Dalam beberapa kasus saya pernah menemukan bahwa aplikasi yang penting dan sudah dipakai umum masih memiliki bug. Saya pernah menemukan bisa mentransfer dari rekening orang ke diri sendiri. Bug itu tidak ditemukan oleh yang lain karena aplikasinya memakai enkripsi custom dengan socket (bukan HTTP), dan tanpa reverse engineering tidak akan bisa ditamper dengan tool seperti burpsuite. Sebagai catatan: dalam hal ini yang salah bukan sisi app-nya, tapi sisi servernya.

Tools

Bagi saya tools-tools ini sudah cukup untuk membongkar dan menyusun 95% APK yang saya temui:

  • apktool
  • jadx
  • compiler Java dan atau IDE (Intellij/Netbeans/Android Studio)

Tools yang komersial juga ada: JEB tapi harganya relatif mahal.

Beberapa tool lain yang juga saya pakai:

Network

Jika niatnya tidak ingin tahu aplikasi secara dalam, tapi hanya sekedar melihat trafficnya saja, saya memakai tool berikut:

Tools-tools tersebut tidak jalan jika ada certificate pinning. Untuk mengatasinya ada banyak metode yang bisa dipakai, tergantung metode pinning yang dipakai oleh program. Dalam kasus sederhana memakai JustTrustMe (Xposed module) atau Frida sudah cukup, tapi di aplikasi tertentu kita perlu patch kode smali untuk bypass SSL Pinning. Artikel berikut ini membahas metode umum untuk bypass SSL Pinning.

Untuk native code saya menggunakan tools lain: IDA Pro dan  Radare. Saya tidak akan membahas native code reverse engineering di sini.

Memulai

Jadi bagaimana untuk memulai? apa yang perlu dipelajari?. Menurut saya urutan ini cukup baik:

  • Belajar membuat aplikasi Android sederhana (minimal hello world), belajar membuat beberapa user interface sederhana (misalnya halaman login), ini terutama jika ingin mengubah/menambah user interface dari APK yang sudah ada. Sudah ada materi gratis dari Google yang bisa didownload di Internet, berbahasa Indonesia.
  • Ekstrak aplikasi tersebut dengan apktool dan jadx
  • Belajar menggunakan proguard, lalu buat atau download aplikasi dari github, kemudian coba compile, bongkar. Setelah itu coba compile dan obfuscate dengan proguard, lalu bongkar.
  • Download aplikasi dari Google Play yang diinginkan, coba ekstrak aplikasinya. Coba bongkar beberapa aplikasi. Langkah ini bisa diganti dengan mendownload soal CTF Android

Penutup

Berbagai jawaban di atas seharusnya sudah cukup menjawab pertanyaan awal. Banyak pertanyaan lanjutan akan bisa dicari jawabannya di Internet, dan beberapa pertanyaan akan sangat spesifik aplikasi dan bahkan spesifik pada versi aplikasi itu.

Contohnya: banyak aplikasi yang versi awalnya tidak diobfuscate sama sekali (misalnya Gojek, BBM) tapi kemudian diobfuscate. Kebanyakan aplikasi juga akan berubah nama kelasnya, dan bahkan library yang dipakai di versi yang baru bisa berbeda. Di sisi server berbagai hal juga bisa berubah, dari mulai URL, format yang dipakai, metode signature yang dipakai, dsb.

Jadi kalau ada orang yang nanya sesuatu di Gojek terbaru, saya gak akan bisa langsung jawab. Ini seperti nanya isi buku terbaru, saya harus baca dulu apa saja yang berubah dari versi lama, harus tracing lagi nama-nama fungsi, nama library dsb. Dan ini butuh waktu, tidak sebentar apalagi jika pertanyaannya sangat spesifik.

Tergantung kompleksitas aplikasi dan tujuan reversing, mengerjakan satu APK bisa butuh waktu beberapa menit, beberapa jam, dan bahkan berhari-hari. Di kasus ekstrem game Pokemon Go yang proteksinya sangat baik, bahkan dulu dibutuhkan waktu ribuan man-hour (banyak orang bekerja berhari-hari) sebelum mereka berhasil membongkarnya (dan setelah itu sudah diganti lagi algoritmanya, sementara orang-orang sudah menyerah).

Waktu adalah sesuatu yang berharga. Buat apa saya membongkar sebuah APK spesifik secara gratis, sedangkan saya membongkar APK lain (untuk pentest) dibayar? Tapi saya juga tidak pelit, jika memang kebetulan saya pernah atau sedang membongkar APK iseng, saya akan memberikan petunjuk/jawaban (ingat, hanya APK iseng, bukan  APK di mana saya menandatangani NDA untuk pentesting).

Khusus untuk yang masih banyak nanya mengenai APK Gojek: saya tidak lagi tertarik pada Gojek sejak beberapa tahun yang lalu. Saya bahkan belum pernah memakai jasa Gojek (saya tinggal di Thailand). Saya tidak kenal dengan orang-orang di Gojek.

Semoga rangkuman di atas ini cukup buat menjawab berbagai pertanyaan seputar reverse engineering APK.

5 thoughts on “Reverse Engineering APK”

  1. Sangat menginspirasi.
    Kalau bisa minta nomor WA pak atau kontak lain.
    Terima kasih

  2. Makasi pak atas penjelasannya
    Boleh minta kontak wa, saya tertarik mempelajari apk ini pak

  3. Artikelnya luarbiasa, sy sebetulnya programer jg, tapi blm menguasai java/ android. Bisa minta tolong untuk membuang beberapa fungsi aplikasi android ga ? Untuk harga bisa ditawarin aja setelah diskusi. Sy tunggu konfirmasinya ya admin.

Tinggalkan Balasan

Situs ini menggunakan Akismet untuk mengurangi spam. Pelajari bagaimana data komentar Anda diproses.