Hallo teman-teman, pada tutorial kali ini saya akan menjelaskan sedikit tentang Frida untuk keperluan Mobile App Pentest dan dalam kesempatan ini hanya di devices Android (mungkin selanjutnya kalo ada niatan bisa buat yg iOS hehee)
Sedikit penjelasan soal Frida.
Frida adalah alat instrumentasi biner dinamis (Dynamic Binary Instrumentation). Mungkin sedikit gambaran, pada tahap melakukan penetration testing, kita mengenal 2 tahapan testing yaitu Static Analysis dan Dynamic Analysis. Nah Frida ini biasa digunakan ketika kita melakukan Dynamic Analysis tersebut.
Kenapa Frida bisa digunakan pada tahap tersebut? Karena Frida memungkinkan kita meng-intercept (hooking) sebuah fungsi ketika aplikasi dijalankan. Frida dapat meng-intercept fungsi pada bahasa pemrograman C (disemua sistem operasi), Java (di Android), dan Objective-C (pada MacOS/iOS) dengan menggunakan JavaScript sebagai bahasa untuk mengontrol target [1].
Untuk bentuk intercept yang bisa dilakukan oleh Frida, itulah yang saya akan bahas disini. Namun untuk penjelasan terkait installasi dan-lain-lain nya, teman-teman bisa liat langsung pada dokumentasi dari Frida disini atau pada tulisan medium ini dari teman saya, Danang.
Pada pembahasan kali ini bisa dibilang masih cukup basic tentang penggunaan Frida untuk hooking fungsi di aplikasi Android. Karena yang nantinya saya bahas disini ada 3 point;
1. Simple hook fungsi dan merubah value asli nya
2. Hook 2 fungsi yang sama namanya, namun berbeda signature (method overloading)
3. Menampilkan fungsi secret()
yang tersembunyi
1. Simple Hook
Untuk tutorial yg pertama ini, saya menggunakan contoh APK yang sudah ada dari 11x256, dan temen-temen bisa unduh APK nya disini.
Berikut ini adalah snippet kode nya
Pada contoh aplikasi disitu, terdapat fungsi Fun()
yang didalamnya terdapat proses aritmatika pertambahan biasa antara variable ‘X’ dan ‘Y’. Dan, pada line code 19, kalau teman-teman lihat disitu, fungsi Fun()
sudah di-defined parameter yang nantinya akan dijumlahkan, yaitu 50 dan 30, dimana hasilnya berarti berapa? 80! *seratus point buat regu A*.
Lalu fungsi Fun()
terdapat didalam fungsi onCreate()
yang dipanggil pada awal proses aplikasi dijalankan, dan melakukan pengulangan fungsi Fun()
.
Untuk melihat hasilnya, kita harus lihat pada adb logcat, karena outputnya hanya melalui Log.d()
.
Command untuk melihatnya bisa menggunakan
root@ipin:~⇒ adb logcat
Atau bisa menggunakan pidcat agar terlihat lebih rapih
root@ipin:~⇒ pidcat(spasi)nama.package.aplikasinya
root@ipin:~⇒ pidcat com.example.a11x256.frida_test
Berikut ini adalah hasil outputnya ketika pertama dijalankan.
Nah sebelum memulai hooking dengan Frida, kita harus memastikan hal berikut ini;
1. Pastikan frida-server pada devices Android kita sudah jalan
root@ipin:~⇒ adb shell
android:/$ su
android:/# ./data/local/tmp/frida-server -D
2. Install APK nya pada devices android kita
root@ipin:~⇒ adb install ~/Downloads/app-1.apk
Setelah 2 point itu sudah, barulah kita masuk ke tahap intercept dengan Frida.
Sebagaimana kita sudah tau diawal pembahasan, Frida menggunakan JavaScript untuk menginjeksinya, maka dari itu kita akan menuliskan code injeksi nya dalam JavaScript, lalu menggunakan Python untuk media menjalankannya supaya otomasi. Nanti juga akan dijelaskan yang versi manual.
Berikut ini adalah code JavaScript yang nantinya kita gunakan untuk injeksi ke fungsi Fun()
, dan kemudian merubah value parameter ‘X’ dan ‘Y’ pada penjumlahan tersebut, sehingga hasilnya pun nanti ikut berubah.
Kita bisa jalankan script nya manual dengan menggunakan perintah berikut ini
frida -U -l /path/file-javascript-nya.js -f Nama.package.aplikasinya — no-pause
atau lengkapnya menjadi
root@ipin:~⇒ frida -U -l /frida-script/test-1.js -f com.example.a11x256.frida_test — no-pause
Kemudian untuk script Python bindings Frida nya seperti berikut ini
Lalu langsung jalankan seperti ini
root@ipin:~⇒ python frida-1.py
Dan hasilnya ketika dijalankan
Penjelasannya adalah, pada gambar yang sebelah kiri itu adalah hasil console.log
dari fungsi Fun()
asli yang kita print di dalam JavaScript code nya (lihat file test-1.js line:9).
Sedangkan yang disebelah kanan adalah hasil penjumlahan yang baru setelah kita ubah nilai dari parameter ‘X’ dan ‘Y’ (lihat line:11).
Karena disitu kita ubah menjadi this.fun(1,7)
berarti hasil penjumlahannya sama dengan? *regu B pass, regu C: 8!, seratuss regu C*
Maka dari itu hasil output di adb-logcat
nya menjadi 8, atau hasil baru dari fungsi fun()
yang telah kita injeksi menjadi 8.
2. Method Overloading
Pada penjelasan contoh ke-dua ini, jadi ada 2 fungsi yang namanya sama namun berbeda signature atau tipe dari si parameter fungsi nya. Dalam real-case, ini sering terjadi pada fungsi-fungsi root-checker, dimana banyak fungsi yang namanya sama namun pengecekan di-dalamnya (termasuk tipe / banyaknya parameter) itu berbeda.
Untuk APK yang contoh ke-dua ini bisa di-unduh disini.
Berikut ini adalah potongan kode dari APK-2 nya.
Dari potongan kode tersebut, ada penambahan fungsi baru yaitu;
- Fungsi fun()
dengan return parameter tipe nya String, namun fungsi fun()
yang lama tetap ada.
- Fungsi secret()
yang tidak dipanggil oleh siapa-siapa disitu *kasian bener*
kita akan bahas ini di penjelasan selanjutnya.
Dan pada line:21 kita lihat fungsi fun()
yang String, sudah di-definisikan value nya fun(“LoWeRcAsE Me!!!!!!!!!”)
.
Nah sekarang kalo kita perhatikan, nama fungsi fun()
yang ada disitu masih sama seperti yang di APK pertama. Berarti apakah masih bisa kita gunakan JavaScript code yang sebelumnya? Mari kita coba sajaaa
Diatas adalah hasilnya, terlihat ada error disitu yang menyatakan “[!] Error: fun(): has more than one overload, use .overload(<signature>)”
. Artinya terdapat lebih dari 1 fungsi fun()
, yaitu fungsi fun.overload(‘java.lang.String’)
dan fun.overload(‘int’, ‘int’)
. Maka dari itu, untuk kasus ini kita bisa menggunakan metode Frida overload, dan metode ini juga biasa digunakan pada aplikasi yang code nya di-obfuscated.
Berikut ini contoh penulisan di dalam JavaScript nyahook.fun.overload(“int”,”int”).implementation = function(x){
hook.fun.overload(“java.lang.String”).implementation = function(x){
Kode pada baris yg pertama, untuk fungsi fun()
yang lama, yaitu fungsi yang penjumlahan.
Dan kode pada baris yg kedua, untuk fungsi fun()
yang baru, dengan return parameter tipe nya String.
Berikut ini code JavaScript lengkapnya
Kemudian gunakan script Python sama seperti contoh yang pertama, tapi kita ubah nama JavaScript file nya pada line:16.
Lalu jalankan kembali, dan berikut ini hasilnya.
Yang kita highlight disini hanya pada fungsi fun()
dengan return parameter nya String aja, karena pada fungsi fun()
yang lama masih sama.
Disitu terlihat pada output setelah dijalankan, kita cetak value asli sebelum kita rubah. Dan kita berhasil merubah value yang dikirim oleh fungsi fun()
yang String menjadi my test string###
. Kenapa bisa dibilang berhasil dirubah? Karena kita lihat pada JavaScript code kita (test-2.js) line:21, disitu kita buat String baru dengan value My TeSt String#####
dengan kombinasi huruf besar dan kecil, tapi ketika di-outputkan menjadi huruf kecil semua (lowercase). Itu menandakan berhasil, soalnya pada fungsi fun()
String, kita lihat disitu ada proses return x.toLowerCase();
pada potongan kode Java nya (line:32).
Artinya string baru yang telah kita buat, berhasil merubah string asli nya untuk diproses pada fungsi tersebut.
3. Menampilkan fungsi secret()
yang tersembunyi
Pada pembahasan sebelumnya, kita sudah mentions soal fungsi secret()
yang berada pada potongan kode Java di APK-2. Pada real-case, ini juga terkadang ditemukan, dimana ada sebuah fungsi dari versi aplikasi yang sebelumnya, namun di versi terbaru tidak dipanggil lagi.
Berikut ini kita perkecil lagi code nya, yang hanya berkaitan dengan fungsi secret()
tersebut.
private String total = “@@@###@@@”;
String secret(
){ return total; }
Fungsi secret()
disitu hanya return nilai dari variabel total, dimana variable total bernilai awal sebuah string "@@@###@@@"
.
Karena fungsi secret()
tidak dipanggil oleh fungsi apapun, termasuk fungsi onCreate()
, maka akan sia-sia kalau kita melakukan hook disitu.
Maka dari itu, yang akan kita lakukan disini adalah mencari instance dari fungsi tersebut di memory, lalu memanggilnya kembali dari situ. Dalam hal ini kita bisa menggunakan Frida Java.choose(namaClass, fungsiCallbacknya)
. Argumen pertama adalah namaClass
dari fungsi yang ingin kita cari, sama seperti ketika kita ingin hook sebelumnya dan yang kedua fungsiCallback
maksudnya adalah, kita buat sebuah penanda ketika instance dari secret()
sudah ditemukan dengan menggunakan onMatch
.
Jadi seperti ini kira-kira tambahan untuk menampilkan fungsi secret()
Java.choose(“com.example.a11x256.frida_test.my_activity”, {
onMatch: function (instance) {
console.log(“Instance secret() ditemukan: “ + instance);
console.log(“Print hasil dari fungsi secret(): “ + instance.secret());
},
onComplete: function () { }
Kita tambahkan code tersebut, kedalam code JavaScript yg sebelumnya. Berikut ini final code nya.
Kalau dibuat dalam file baru, sebelum kita running script Python nya, kita ubah terlebih dahulu nama file JavaScript nya. Kalau penambahannya dimasukkan di file yg sama, kita bisa langsung running script Python nya.
Hasilnya adalah berikut ini
Terlihat dari hasilnya, kita berhasil menampilkan hasil dari fungsi secret()
, yaitu string awal dari variable total "@@@###@@@"
, dan instance secret ditemukan pada com.example.a11x256.frida_test.my_activity@62121c3
.
Pasti kalian bertanya-tanya, padahal variable total diproses juga pada fungsi fun()
yang String, tapi kenapa yg ditampilkan nilai awalnya? Jawabannya adalah karena pada proses pemanggilan fungsi secret()
setelah ditemukan akan diproses dengan cepat, secepat kilat! Maka dari itu kita mendapatkan nilai variable total yang belum dimodifikasi.
Penutup
Itulah tadi sedikit tutorial tentang Frida dari saya, tentang bagaimana melakukan hook biasa, hook fungsi yg sama namun berbeda tipe signature, dan terakhir menampilkan fungsi yg tersembunyi.
Dalam penerapan real-case nya, diawal proses memang harusnya melakukan decomplie APK nya terlebih dahulu, dan tak jarang hasil decompile nya tidak semirip code awal dari aplikasi tersebut. Namun untuk memudahkan dalam memahami konsep dasar dari Frida, jadi saya tampilkan seperti itu.
Apabila ada pertanyaan dan saran, monggo :)
Karena belajar adalah tentang berbagi. Keep Learn and Share!
Sekian! Semoga bermanfaat~
-Arfn
Refrensi
[1] https://blog.compactbyte.com/2019/08/11/mengenal-frida-untuk-reverse-engineering/
[2] https://frida.re/docs/android/
[3] https://medium.com/@danangtriatmaja/tutorial-bypass-android-ssl-pinning-frida-script-indonesian-17be2aa0f260
[4] https://11x256.github.io/Frida-hooking-android-part-1/
[5] https://11x256.github.io/Frida-hooking-android-part-2/