Assalamualaikum warahmatullahi wabarakatuh, pada tulisan kali ini setelah melakukan cheating pada platform Windows Game / Desktop Game kali ini saya akan menuliskan hal yang telah saya pelajari, yaitu cheating dengan menggunakan frida di platform android, ide dari tulisan ini adalah memanfaatkan frida untuk berinteraksi dengan libshared milik aplikasi android dan melakukan patching flow code-nya.
Game yang ditargetkan adalah seperti Screenshot di atas, bisa diunduh di tautan Play Store di atas, berikut ini adalah langkah-langkah yang dapat ditempuh.
Extract Application from Devices
adb shell pm list packages -f | findstr assault
ls :/data/app/~~hacSXCjloDQ9GB_QFwLRHg==/net.cubers.assaultcube-UisYnvIoXF_Xd7EpXZ3UwQ==
adb pull /data/app/~~hacSXCjloDQ9GB_QFwLRHg==/net.cubers.assaultcube-UisYnvIoXF_Xd7EpXZ3UwQ==/base.apk
Reverse the Application
Pada proses ini kita dapat menggunakan JADX untuk mengetahui aplikasi ini berjalan dengan skema kode dan algoritma bagaimana.
Jika dilihat dari AndroidManifest.xml
tidak ada yang menarik dari permission yang ada juga tidak ada yang spesial dari intent
yang didefinisikan, kita dapat mulai melakukan eksplokrasi ke LaunchActivity.
Tidak ada yang menarik dari kode-kode JAVA yang ada, dikarenakan semua algoritma diload pada AssaultCubeLib
dan berikut adalah isinya
Dari kode yang ada, semua algoritma dan skema permainan diload dalam loadLibrary
dengan nama file [libmain.so](http://libmain.so)
kita dapat mengunduhnya di
adb pull /data/app/~~hacSXCjloDQ9GB_QFwLRHg==/net.cubers.assaultcube-UisYnvIoXF_Xd7EpXZ3UwQ==/lib/x86_64/libmain.so
Kita dapat menggunakan beberapa tools public untuk melakukan analisa, ada beberapa tools seperti
Namun sepengalaman saya pada kasus ini, tools paling kacau ada di Ghidra, dan terbaik ada di IDA Pro, namun pada tulisan ini kita dapat menggunakan Radare2 / Binary Ninja. Sebelum melakukan analisa cepat, saya biasanya melakukan analisa symbol-symbol apa saja yang di-load oleh [libmain.so](http://libmain.so)
saya menggunakan frida untuk hal ini, berikut ini code yang saya gunakan
var libAddr = Module.findBaseAddress('libmain.so');
Module.enumerateExports("libmain.so", {
onMatch: function (exp) {
console.log("Exported symbol: " + exp.name + " at address: " + exp.address);
},
onComplete: function () {
console.log("Export enumeration complete");
}
});
Module.enumerateSymbols("libmain.so", {
onMatch: function (symbol) {
console.log("Loaded Symbol: " + symbol.name + " at address: " + symbol.address);
},
onComplete: function () {
console.log("Symbol enumeration complete");
}
});
Script tersebut akan dijalankan dengan loader, loader ini yang akan berfungsi melakukan spawing terhadap aplikasi juga akan melakukan load script ke targeted attach, berikut kode loadernya (pemilik asli)
import time,frida
device = frida.get_usb_device()
print(device)
pid = device.spawn(["net.cubers.assaultcube"])
device.resume(pid)
time.sleep(5)
# print(device.enumerate_processes())
session = device.attach(pid)
with open("debug.js") as f:
script = session.create_script(f.read())
script.load()
input()
Kode kita akan ditulis pada debug.js
dan menjalankan frida via python, jalankan saja loadernya dan kita akan mendapatkan Exported Symbol dan Loaded Symbol yang akan dipanggil dari [libmain.so](http://libmain.so)
saya melakukan analisa manual, dan mendapatkan beberapa fungsi yang menarik dari Symbol yang ada antara lain
Exported symbol: _ZTV6weapon at address:
Exported symbol: _Z12damageeffectiP9playerent at address: 0x73ce1992e300
Exported symbol: hitplayer at address: 0x73ce19b037c8
Exported symbol: __dummy_playerinfo at address: 0x73ce19afcad5
Exported symbol: damageindicatordist at address: 0x73ce19b0a8fc
Exported symbol: _ZN11playerstate8dodamageEii at address: 0x73ce198691a0
Hal-hal paling menarik dan menjadi target kita adalah pada _ZN11playerstate8dodamageEii
kita dapat menggunakan keywords, damage
untuk mencari Symbol tersebut dalam decompiler
Symbol tersebut ternyata juga melakukan reference ke function dodamage
yang berada pada state playerstate
kita dapat memfokuskan pada fungsi dodamage
Dari kode di atas, kita dapat melakukan debbuging, dengan Interceptor untuk mengetahui apakah memang kode di atas terpanggil atau tidak, kita dapat menggunakan frida seperti berikut ini untuk debbuging.
var libAddr = Module.findBaseAddress('libmain.so');
try{
var interceptdamage = Interceptor.attach(libAddr.add(0x9be40), {
onEnter: function(args){
console.log("Im in")
console.log("Arg0: " + args[0].toInt32());
console.log("Arg1: " + args[1].toInt32());
console.log("Arg2: " + args[2].toInt32());
console.log("Arg3: " + args[3].toInt32());
console.log("Arg4: " + args[4].toInt32());
console.log("Arg5: " + args[5].toInt32());
}
});
}catch(e){
console.log(e, "Halo");
}
Interceptor.attach(libAddr.add(0x9be40)
pada line tersebut copykan address yang ada pada BinaryNinja tepat pada fungsi dodamage
Dan akan mendapatkan 0x9be40
saat dijalankan akan mendapatkan hasil seperti berikut ini
Dan benar saja, fungsi dodamage
akan terpanggil dan terlihat pada console terlihat 6 argumen yang sesuai dengan fungsi hasil dekompilasi yang ada, dari sini kita dapat memetahkan beberapa argumen yang ada
Argumen 0 → adalah damage yang masuk ke player
Argumen 1 → address target pemain yang akan diberi damage
Argumen 2 → address pemberi damage
Itulah argumen-argumen yang dapat kita kontrol untuk melakukan cheating, idenya adalah kita dapat merubah damage yang masuk ke address kita untuk menjadikannya 0 dan merubah damage kita menjadi yang paling besar atau menjadikannya 500, langkah pertamanya adalah dengan mencari base address dari player kita sendiri, pada dodamage
sudah terdapat base player address milik kita
Lakukan double click ke variable player 1 dan akan mendapatkan address 0x32df98
dan kita sudah lengkap untuk membuat cheat code frida kita, berikut ini full codenya
var libAddr = Module.findBaseAddress('libmain.so');
console.log("libmain.so address: " + libAddr);
// console.log(libAddr.add(0x7151efd5c1a0));
// Module.enumerateExports("libmain.so", {
// onMatch: function (exp) {
// console.log("Exported symbol: " + exp.name + " at address: " + exp.address);
// },
// onComplete: function () {
// console.log("Export enumeration complete");
// }
// });
try{
var interceptdamage = Interceptor.attach(libAddr.add(0x98c20), { //0019be40
onEnter: function(args){
console.log("Player info")
console.log("Arg0: " + args[0].toInt32());
console.log("Arg1: " + args[1].toInt32());
}
});
}catch(e){
console.log(e, "Halo");
}
try{
var interceptdamage = Interceptor.attach(libAddr.add(0x9be40), { //0019be40
onEnter: function(args){
console.log("Im in")
console.log("Arg0: " + args[0].toInt32());
console.log("Arg1: " + args[1].toInt32());
console.log("Arg2: " + args[2].toInt32()); // target attack 1499958976 0x32df98 0042df98
console.log("Arg3: " + args[3].toInt32());
console.log("Arg4: " + args[4].toInt32());
console.log("Arg5: " + args[5].toInt32());
var playerptr = ptr(0x32df98)
var fixedAddr = libAddr.add(playerptr)
var fixplayeraddr = Memory.readPointer(fixedAddr)
if(fixplayeraddr.toInt32() == args[1].toInt32()){
console.log("Patching damage incoming to 0")
args[0] = ptr(0x0)
}
if(fixplayeraddr.toInt32() == args[2].toInt32()){
console.log("Patching damage outgoing to 0x7fffffff")
args[0] = ptr(0x200)
}
}
});
}catch(e){
console.log(e, "Halo");
}
Terlihat pada gambar di atas, saya menghadapi 2 orang musuh terkena damage dan masih memiliki jumlah HP 100 dikarenakan kita sudah melakukan patching damage masuk ke player kita, dan juga seharusnya saat kita melakukan damage ke musuh kita akan mengirimkan damage paling besar ke musuh.
Terima kasih sudah membaca dokumentasi saya untuk belajar cheating ini, semoga dapat terus berkembang dan dapat bermanfaat bagi kegiatan yang lain.