Sizlere daha önceden frida nasıl kurulur, nasıl kullanılır bahsetmiştim. Şimdi ise daha detaylı ve örnek program yaparak pekiştireceğiz.
Programların kaynak kodlarını inceleme
Programların kaynak kodunu incelemeden önce bazı yazılımların nasıl çalıştığından bahsetmeliyim. Android, Java üzerine kurulu olduğundan java nasıl çalışıyorsa uygulamayı hangi platforma kodladığınızdan bağımsız olarak ona göre program derlenir. Javanın temel derlenme mekanizmasının yanında kodlar genelde dex okuyucusunda “MainActivity$1$1$1” gibi işaretlerle görünebilir. Bu, anonymous classlar yüzünden olur ve eğer buraya kod enjeksiyonu yapmak isterseniz “MainActivity$1$1$1” şeklinde yazmalısınız, size önerim bunları kullanmadan doğrudan temel fonksiyonlar ve kütüphanelere erişmeniz olacaktır. Frida genelde çok spesifik durumlar için kullanılmasada ihtiyacınız olan modülü yazmak için çok işe yarayabilir (örneğin emulator kontrolünü android kütüphanesinden yapmak daha kolay olacaktır, servisleri düzenlemek ise daha zahmetli.) öncelikle hack me uygulamamız vardı hatırlıyor musunuz? Tekrar açalım ve kaynak kodu olmadan nasıl erişebiliriz, ne yapabiliriz ona bakalım.
Kaynak kodunu okumak için kullanacağımız programların en başında DEX okuyucusu geliyor. DEX dediğimiz dosya aslında java kodlarının derlenmiş halini içeren bir pakettir.
APK dosyasını ayrıştırma
APK dosyasını ayrıştırmak için yapmanız gereken apktool kullanmak. Bunun için yazılan makaleye göz atabilirsiniz.
Klasör yapısı
Dosyaları tanımlamak gerekirse;
classes[sayı].dex: Bahsettiğim dex dosyaları bunlar. Dosyalar birden fazla olabilir çünkü büyük projelerde dex dosyasının bulunan sınırını aşmaya yarar.
res: Kaynak dosyalarınız. Resimleriniz, tasarımlarınız burada bulunur.
META-INF: İmza bölümü. içeriklere imza yapar
AndroidManifest.xml: programın temel izinler, bilgilerinin bulunduğu klasör
DEX dosyasında gezinti yapma
Öncelikle “AndroidManifest.xml” dosyasından başlangıç aktivitesini bulmamız gerekiyor.
android:name etiketinde “com.andromeda.hackme.MainActivity” yazıldığını görüyoruz. Aslında bakarsanız bu bahsedilen yer classes.dex dosyasının içeriğindeki yer. Gelin oraya göz atalım.
burada derlenmiş java kodunu görüyoruz. isterseniz burada bulunan “0x0” yazan kısmı “0x1” yazarsanızda programımızı hacklemeyi başarabilirsiniz. Fakat.. Şuanda frida anlattığımız için bunu yapamayacak kadar korunaklı bir uygulamanızı test ettiğinizi varsayalım. Buradan göreceğiniz üzere isAdmin() adında bir fonksiyon var. Bu fonksiyon bizim oluşturduğumuz koddaki fonksiyonun ta kendisi! kaynak kodunu github üzerinden inceleme yapmadan kendisini bulabildik. Dilersek burada farklı fonksiyonlarda bulabilirdik.
Frida ile incelenen kodu manipüle etme
Daha önceden nasıl frida kurulur anlattım, dolayısıyla şuanki konumuz aynı örnek üzerinden gittiğimiz için daha spesifik ve uygulamanın kodlarına değişiklik yapacak şekilde örnekler verelim. Önceki makalemde isAdmin() fonksiyonunu güncellemiş ve başarıyla sızmıştım. Şimdi ise uygulamanın ana aktivitesinde açılış ekranında ekrana bir yazı yazdırma gibi işlemler yapacağız.
Çoğu makalede hemen yapılıp geçiliyor fakat asıl olay activity sınıfını kendimiz eklediğimizde. Bu durumda program genelde hata veriyor. Çoğu şey denesemde bir sonuç alamadım. Sonra aklıma daha mantıklı bir çözüm geldi.
Java.perform(function () {
const Activity = Java.use('android.app.Activity');
Activity.onPause.implementation = function () {
if(this.$className.includes("MainActivity")){
console.log("MainActivity kısmındayız :)");
}
this.onPause();
}
});
Bu Javascript kodunda Activity sınıfının kendisini çağırıyoruz. Ardından if yapısı kullanarak class adından nerede olduğumuzu bulduk. Her zaman böyle yapmanızı öneririm. Çünkü doğrudan temel classta herhangi bir kod yazmanız spesifik onu extend eden bir classta kod yazmanızdan çok daha basit ve az uğraştırıcı. Ekrana yeni bir TextView eklemek istersek ne olacağını gelin birlikte görelim.
Java.perform(function () {
const Activity = Java.use('android.app.Activity');
const TextView = Java.use("android.widget.TextView");
TextView.setText.overload("java.lang.CharSequence").implementation = function (x) {
const stringToSend = x.toString();
if(stringToSend === "Beni hackleyemezsin :)"){
return this.setText(Java.use("java.lang.String").$new("Çoktan manipüle ettim bile :)"));
}
return this.setText(x);
}
});
Bu tarz işlemler ile kolayca fonksiyonlar arasında düzenleme yapabilirsiniz. Farkettiyseniz “overload” kullandık. Bu işlevin amacı değer alan fonksiyonlarda parametreyi seçmek. String döndürmek istediğiniz zaman yazdığımız “Java.use(“java.lang.String”).$new” kodunun amacı aslında “new String()” olarak geçer. Bir sonraki yazımızda fridanın python ile birlikte nasıl kullanıldığından bahsedeceğim.