Bloga geri dön
Dinamik analiz, bir yazılımın veya uygulamanın çalışma anında (runtime) incelenmesi sürecidir. Bu yöntem, özellikle güvenlik açıklarını tespit etmede kritik bir rol oynar. Dinamik analiz sırasında, uygulamaların gerçek zamanlı davranışları gözlemlenerek, runtime hataları, yanlış yapılandırılmış API’ler ve diğer potansiyel güvenlik açıkları tespit edilebilir. Bu süreç, uygulamanın nasıl çalıştığını anlamak ve güvenlik zafiyetlerini ortaya çıkarmak için oldukça etkilidir.
Android Debug Bridge (ADB), Android uygulamalarını analiz etmek için kullanılan güçlü bir komut satırı aracıdır. ADB, Android cihazlar ile bilgisayar arasında iletişim kurmayı sağlar ve dinamik analiz sürecinde büyük kolaylık sunar. ADB kullanarak Android cihazlara bağlanabilir, uygulamaların çalışma sırasındaki davranışlarını izleyebilir ve çeşitli testler gerçekleştirebilirsiniz.
ADB, temel olarak üç bileşenden oluşur: ADB Sunucusu, ADB Daemon (Hizmeti) ve ADB Binary. Bu bileşenler, cihazlar ve bilgisayar arasında sorunsuz bir iletişim sağlamak için birlikte çalışır.
1. ADB Sunucusu:
ADB sunucusu, bilgisayarınızda çalışan ve cihazlar ile iletişim kurmak için merkezi bir rol üstlenen bir yazılımdır. ADB komutlarını çalıştırdığınızda, ADB sunucusu otomatik olarak başlatılır ve 5037 portu üzerinden ADB istemcileri ile bağlantı kurar. Sunucu, cihazlar arasındaki bağlantıyı yönetir ve istemciden gelen komutları iletmekle sorumludur.
2. ADB Daemon:
ADB daemon, Android cihazında çalışan bir servistir. Bu hizmet, cihaz ile bilgisayar arasındaki bağlantıyı yönetir ve ADB’nin doğru şekilde çalışmasını sağlar. Cihazın ADB üzerinden gelen komutları alması, işlemesi ve sonuçları geri göndermesi için bu daemon sürekli aktif olmalıdır. ADB daemon, cihazla doğrudan iletişim kuran temel bileşendir.
3. ADB Binary:
ADB binary, Android SDK içinde bulunan ikili dosyadır. Bu dosya, ADB komutlarını çalıştıran, komutları sunucuya ileten ve cihazla iletişimi başlatan ana bileşendir. ADB binary, cihazın bağlanması ve komutların iletilmesi işlemlerinin düzgün çalışmasını sağlar. Özellikle adb shell gibi komutlar, bu binary aracılığıyla çalıştırılır.
Bu üç bileşen, ADB’nin etkin bir şekilde çalışmasını sağlayarak, Android cihazlar ile bilgisayar arasında veri aktarımı, hata ayıklama, uygulama yükleme gibi işlemleri mümkün kılar.
Cihazlarla bağlantı kurmanın en basit yolu, cihazı USB ile bilgisayara bağlamak ve ardından adb shell komutunu çalıştırmaktır. Bu komut, cihazla bağlantı kurar ve komut satırı ekranında bir istemci görüntüler. Bu işlem, emülatörler için de geçerlidir.
Birden fazla cihaz bağlandığında, ADB sunucusu hangi cihazla iletişim kuracağını bilemez. Bu durumda, her cihazın benzersiz bir seri numarası vardır ve bu numara kullanılarak doğru cihaz hedeflenebilir. Cihazların seri numaralarını görmek için adb devices komutu kullanılır.
ADB, port yönlendirme işlemleri için de kullanılabilir. Bu özellik, özellikle ağ trafiği analizi sırasında oldukça faydalıdır.
ADB Forward:
adb forward komutu ile, mobil cihazınızdaki bir portu, bilgisayarınızdaki başka bir porta yönlendirebilirsiniz. Örneğin, cihazınızdaki 4444 portunu bilgisayarınızdaki 1337 portuna yönlendirmek için şu komut kullanılır:
adb forward tcp:1337 tcp:4444
ADB Reverse:
adb reverse komutu ise, cihazınızdan bilgisayarınıza bir bağlantı kurmak için kullanılır. Örneğin, bilgisayarınızda çalışan bir web sunucusunun mobil cihazınızdan erişilebilir olmasını sağlamak için şu komut kullanılır:
adb reverse tcp:8080 tcp:80
Bu komut, bilgisayarınızdaki 8080 portunu, mobil cihazınızdaki 80 portu üzerinden erişilebilir hale getirir. Bu ayar, özellikle güvenlik analizi yaparken oldukça kullanışlıdır. Örneğin, Burp Suite gibi bir araç kullanıyorsanız, mobil cihazınızdaki trafiği bilgisayarınıza yönlendirerek, bu trafiği kolayca analiz edebilirsiniz.
adb -s emulator-6555 shell
adb -s emulator-6555 push /path/to/local/file /sdcard/filename
adb -s emulator-6555 pull /sdcard/filename /path/to/local/directory
adb -s emulator-6555 logcat
adb -s emulator-6555 reboot
adb -s emulator-6555 install /path/to/mobilapp.apk
adb -s emulator-6555 uninstall com.example.mobilapp
Burp Suite, uygulamaların ağ trafiğini analiz etmek, veri akışını incelemek ve potansiyel güvenlik açıklarını tespit etmek için yaygın olarak kullanılan bir araçtır. Android cihazlarla Burp Suite’i entegre etmek için Android Debug Bridge (ADB) kullanılır. Burp Suite ve ADB kullanarak Android cihazlardan gelen trafiği izleme ve analiz etme süreçleri için aşağıdaki adımları takip edebilirsiniz.
İlk olarak, Burp Suite uygulaması üzerinde Proxy sekmesine gidin. Burada Proxy Listener ayarlarını yapılandırmanız gerekiyor. Ben genellikle port olarak 8081 kullanıyorum, ancak siz kendi ihtiyaçlarınıza göre farklı bir port numarası da belirleyebilirsiniz.
Android 11.0 ve daha eski sürümlerde, cihazın proxy ayarlarını yapılandırarak Burp Suite üzerinden trafiği inceleyebilirsiniz. Bunun için aşağıdaki ADB komutlarını kullanabilirsiniz:
Bu komutlar, cihazın tüm HTTP/HTTPS trafiğini belirttiğiniz proxy IP ve port üzerinden yönlendirecektir.
Proxy ayarlarını yapılandırdıktan sonra, HTTPS trafiğini yakalayabilmek için Burp Suite’in CA sertifikasını cihaza yüklemeniz gerekiyor. Bu işlem, sistem seviyesinde güvenilen bir sertifika olarak yüklenmesini sağlar.
Sertifikayı PEM Formatına Dönüştürme
Burp Suite’in CA sertifikasını .cer formatında indirdikten sonra, bu sertifikayı PEM formatına dönüştürmeniz gerekiyor:
Sertifikayı PEM Formatına Dönüştürme:
Sertifika Adını Düzenleme:
Daha sonra, sertifikanın subject hash değerini alarak sertifikayı bu değerle yeniden adlandırmanız gerekiyor:
ADB Komutlarıyla Sertifikayı Cihaza Yüklemek:
Cihazı Yeniden Başlatma:
Bu adımları otomatik hale getirmek için aşağıdaki Python scriptini kullanabilirsiniz:
Bu adımları takip ederek, Burp Suite ile Android cihazlardan gelen API trafiğini başarıyla analiz edebilir ve güvenlik açıklarını tespit edebilirsiniz.
Frida, dinamik analiz için kullanılan açık kaynaklı bir araçtır. Özellikle mobil uygulamalarda runtime manipülasyonu yapmak için kullanılır, uygulamanın çalışma zamanındaki davranışlarını değiştirebilmenizi olanak sağlar. Frida, sadece Android ve iOS üzerinde değil, aynı zamanda Linux, Windows ve diğer birçok işletim sisteminde de çalışabilmektedir. Farklı işletim sistemlerinde runtime işlemlerini izleyebilir, bellek üzerinde manipülasyonlar yapabilir ve API’leri test edebilirsiniz.
Frida, iki ana bileşenden oluşur:
Frida, hooking adı verilen bir teknikle çalışır. Hooking, bir uygulamanın belirli fonksiyonlarına veya API çağrılarına müdahale etme işlemidir. Bu sayede, uygulamanın çalışma zamanındaki davranışlarını değiştirebilir veya izleyebilirsiniz.
Frida, mobil uygulamaların çalışma zamanında (runtime) manipülasyon yapmak için hooking adı verilen bir teknik kullanır. Bu teknik, uygulamanın belirli fonksiyonlarına veya API çağrılarına müdahale etme işlemidir. Peki Frida bunu nasıl yapıyor? Gelin, Frida'nın çalışma prensibini daha detaylı inceleyelim.
Android uygulamaları, büyük ölçüde Java veya Kotlin programlama dilleriyle yazılır. Bu uygulamalar, Java Virtual Machine (JVM) üzerinde çalışır. JVM, uygulamanın tüm sınıflarını, metodlarını ve veri yapılarını yönetir. Frida, bu JVM'e hook yaparak, uygulamanın çalışma zamanındaki davranışlarını izler veya değiştirir.
Örneğin, bir uygulamanın şifreleme işlemleri sırasında kullandığı bir metodu izlemek istiyorsanız, Frida ile bu metoda hook yapabilir ve metodun davranışını değiştirebilirsiniz. Bu, güvenlik testlerinde büyük bir avantaj sağlar.
iOS uygulamaları, Objective-C veya Swift dilleriyle yazılır. Frida, iOS cihazlarda da benzer bir şekilde çalışır. iOS'un runtime yapısına müdahale ederek, uygulamanın Objective-C veya Swift kodlarını manipüle edebilir. Özellikle Objective-C Runtime'ın dinamik yapısı, Frida'nın bu platformda da etkili olmasını sağlar.
Hooking, bir uygulamanın belirli fonksiyonlarına veya API çağrılarına müdahale etme işlemidir. Frida, bu işlemi gerçekleştirerek, uygulamanın çalışma zamanındaki davranışlarını değiştirebilir veya izleyebilir. İşte hooking işleminin adımları:
Frida, hooking işlemini genellikle JavaScript veya Python scriptleriyle gerçekleştirir. İşte basit bir örnek:
Örnek: Bir Android Uygulamasının Metodunu Hooklama
Diyelim ki bir Android uygulamasında com.example.MainActivity sınıfının onCreate metodunu hooklamak istiyorsunuz. Bunun için aşağıdaki gibi bir Frida scripti yazabilirsiniz:
Bu script, MainActivity sınıfının onCreate metodunu hooklar ve bu metod çağrıldığında konsola bir mesaj yazdırır. Ayrıca, orijinal metodun davranışını da korur.
Frida’yı kurmaya başlamak için önce Frida’nın istemci kısmını yüklemeliyiz. Eğer Ubuntu gibi bir Linux dağıtımı kullanıyorsanız ve Python 3 yüklüyse, aşağıdaki komutla Frida istemcisini kurabilirsiniz:
Bu komut, Frida'nın istemci araçlarını indirip kurar. Kurulum başarılı olduğunda, terminalde frida komutunu çalıştırarak Frida'nın doğru şekilde kurulduğunu kontrol edebilirsiniz.
Frida Server, analiz edilecek cihazda (örneğin, bir Android cihaz) çalışan bileşendir. Bu sunucu bileşeni, Frida’nın GitHub deposundan indirilebilir.
Frida’yı Android cihazınızda kullanmak için, doğru sunucu versiyonunu indirmeniz gerekir. Frida’nın sunucu bileşeni, cihazınızın mimarisine bağlı olarak farklı versiyonlarda mevcuttur. ARM32, ARM64 veya x86 versiyonlarından birini seçmeniz gerekir. Hangi versiyonu kullanmanız gerektiği, cihazınızın işlemci mimarisine bağlıdır.
Cihazınızın mimarisini öğrenmek için şu komutu kullanabilirsiniz:
Bu komut, cihazınızdaki işlemci mimarisini döndürecektir (örneğin, arm64-v8a, armeabi-v7a, x86 gibi). Bu bilgiye göre, ARM32, ARM64 veya x86 sunucu versiyonlarından uygun olanı seçebilirsiniz.Komutun çıktısındaki mimariye göre uygun Frida Server buradan indirilebilir.
Server ve Client Bağlantısını Aktifleştirme
Frida Server dosyasını cihazınıza aktarmak için aşağıdaki komutu kullanabilirsiniz:
Frida sunucu dosyasını cihazınıza şu komutla gönderin:
Daha sonra, Frida sunucusunun çalışabilmesi için gerekli yetkileri vermeniz gerekir. Bunun için şu komutu kullanabilirsiniz:
Yetkiler verildikten sonra, Frida sunucusunu cihaz üzerinde şu komutla çalıştırabilirsiniz:
Frida sunucusu aktif olduktan sonra, Frida aracını kullanarak Android cihazınızda çalışan işlemleri görüntüleyebilirsiniz. Bu sayede cihazınızdaki süreçleri izlemeye başlayabilirsiniz.
Frida-PS, cihazdaki çalışan işlemleri listelemek için kullanılan bir komut satırı aracıdır. Bu araç, mobil uygulama güvenliği araştırmalarında aktif işlemleri ve uygulamaları görmek için oldukça kullanışlıdır. İşte önemli komutlar:
Örneğin, cihazınızdaki tüm süreçleri listelemek için şu komutu kullanabilirsiniz:
Bu komut, Android cihazınızdaki çalışan tüm süreçleri listeler. Eğer her şey doğru şekilde kurulduysa, Frida-PS komutu ile cihazdaki tüm aktif süreçleri görebilirsiniz.
OWASP UnCrackable Level 1, eğitim amaçlı tasarlanmış bir Android uygulamasıdır. Bu uygulama, root tespiti ve uygulama mantığını tersine mühendislikle çözmek gibi zorluklar içerir. Bu yazıda, Frida kullanarak bu uygulamanın root tespitini nasıl atlatabileceğimizi ve AES şifreleme fonksiyonunu nasıl hooklayabileceğimizi adım adım inceleyeceğiz.
Android uygulamalarını analiz ederken, ilk adım genellikle AndroidManifest.xml dosyasına bakmaktır. Bu dosya, uygulamanın başlangıç noktası ve kritik bileşenlerini tanımlar. Örneğin, aşağıdaki AndroidManifest.xml dosyasından uygulamanın başlatma noktasının sg.vantagepoint.uncrackable1.MainActivity sınıfı olduğunu anlayabiliriz.
Uygulamayı açtığımızda, root tespiti nedeniyle uygulama kapanır. MainActivity sınıfını incelediğimizde, onCreate metodunda root tespiti yapıldığını görürüz. Eğer cihazın rootlu olduğu tespit edilirse, kullanıcıya bir AlertDialog üzerinden uyarı gösterilir ve "OK" düğmesine basıldığında uygulama System.exit(0) ile kapatılır.
onCreate metodu, uygulama açıldığında çalışır ve iki farklı güvenlik kontrolü gerçekleştirir:
Bu yöntemler, uygulamanın hem root edilmiş cihazlarda çalışmasını engellemek hem de debug edilmesini zorlaştırmak için tasarlanmıştır.
MainActivity’deki root tespit mekanizmasını atlatmak için Frida kullanarak bir script geliştirebiliriz. Bu script, uygulama çalışırken System.exit(0) fonksiyonunu geçersiz kılar ve böylece uygulama kapanmaz.
Root tespitini atlatmak için Frida kullanarak bir script yazabiliriz. Bu script, uygulama açıldığında System.exit(0) fonksiyonunu geçersiz kılacaktır.
System.exit.implementation: System.exit(int) metodunu override ederek, kapanma işlemine müdahale ederiz. Uygulama kapanmaz ve bir log mesajı oluştururuz.
-l: Bu parametre, Frida'ya bir JavaScript dosyasının enjekte edilmesini sağlar. Yani, belirtilen JS dosyasını hedef uygulamaya enjekte eder.
-U: Bu parametre, ADB (Android Debug Bridge) üzerinden bağlanmış bir Android cihazını hedef alır. Cihazınız bilgisayarınıza USB kablosu ile bağlanmışsa ve ADB üzerinden erişilebiliyorsa, bu parametre kullanılarak o cihaz seçilir.
-f: Bu parametre, belirtilen Android uygulamasını başlatır. Frida, bu parametre ile verilen uygulamayı çalıştırır ve ardından script enjekte etmeye başlar.
İkinci bir yöntem olarak uygulama, rootlu cihazlarda çalışmayı engellemek için sg.vantagepoint.a.c sınıfındaki a(), b() ve c() metodlarını kullanır. Bu metodlar, cihazın rootlu olup olmadığını kontrol eder. Eğer root tespit edilirse, uygulama kapanır. Bu tespiti atlatmak için Frida kullanarak bu metodları geçersiz kılabiliriz.
Frida Scripti:
1.Java.perform:
Frida'nın Android uygulamaları üzerinde çalışmasını sağlayan temel fonksiyondur. Bu fonksiyon, Java runtime'ına müdahale etmek için kullanılır ve scriptin uygulamanın bellek alanında çalışmasını sağlar.
2.Java.use:
Belirtilen Java sınıfını (sg.vantagepoint.a.c ve sg.vantagepoint.a.b) yükler. Bu, sınıfın metodlarına erişim sağlar ve bu metodları override etmemize olanak tanır. Örneğin, c.a(), c.b(), c.c() ve b.a() metodları bu şekilde yüklenir.
3.implementation (Override Mekanizması):
Bir metodun orijinal davranışını override etmek için kullanılır. Bu script’te, c.a(), c.b(), c.c() ve b.a() metodlarının implementation özelliği değiştirilerek, bu metodlar her çağrıldığında false döndürmesi sağlanır. Bu, root ve debug tespitini etkisiz hale getirir.
sg.vantagepoint.a.c Sınıfı:
Bu sınıf, root tespiti yapan a(), b() ve c() metodlarını içerir. Bu metodlar, cihazın rootlu olup olmadığını kontrol eder. Eğer bu metodlar true dönerse, uygulama root tespit eder ve kapanır.
Override İşlemi:
Script, bu metodların implementation özelliğini override ederek, her zaman false döndürmelerini sağlar. Böylece, root tespiti engellenir ve uygulama rootlu bir cihazda çalışmaya devam eder.
sg.vantagepoint.a.b Sınıfı:
Bu sınıf, debug tespiti yapan a() metodunu içerir. Bu metod, uygulamanın debug modunda olup olmadığını kontrol eder. Eğer true dönerse, uygulama debug modunda olduğunu tespit eder ve kapanır.
Override İşlemi:
Script, bu metodun implementation özelliğini override ederek, her zaman false döndürmesini sağlar. Böylece, debug tespiti engellenir ve uygulama debug modunda çalıştırılabilir.
Uygulama Fonksiyonu Analizi
Uygulama açıldığında, bir metin kutusu ve "VERIFY" butonu görülür. Butona tıklandığında, kullanıcının girdiği değer sg.vantagepoint.a.a.a metodu ile şifrelenmiş bir değerle karşılaştırılır. Eğer değerler eşleşmezse, "That’s not it. Try again." mesajı gösterilir. Doğrulama mantığı şu şekilde kodlanmıştır:
Doğrulama Fonksiyonunun Analizi
Doğrulama fonksiyonu, kullanıcının girdiği değeri sabit bir değere karşı karşılaştırmak için sg.vantagepoint.a.a.a metodunu kullanıyor. Bu metod, AES şifrelemesiyle şifrelenmiş bir veriyi çözüyor.
AES Cipher Fonksiyonunu Hooklamak
Uygulamanın doğrulama mantığını anlamak için AES şifre çözme işlemini hooklayabiliriz. Bu sayede, şifreli veriyi çözerek doğru değeri elde edebiliriz. Aşağıdaki script, AES şifre çözme işleminin çıktısını loglayacaktır:
Frida Scripti
decryptor.a.implementation = function(inputBytes, keyBytes)
satırında, a() metodunu override ederek, bu metod her çağrıldığında kendi yazdığımız fonksiyonun çalışmasını sağlıyoruz. Burada inputBytes ve keyBytes, orijinal a() metoduna verilen byte dizileridir. Bu diziler, şifre çözme işlemi için kullanılır.
1.Input Byte Array:
console.log('Input Byte Array (p0): ' + byteArrayToString(inputBytes));
komutuyla, a() metoduna giren byte dizisini konsola yazdırıyoruz. Bu, şifrelenmiş veriyi görmemizi sağlar.
2.Key Byte Array:
console.log('Key Byte Array (p1): ' + byteArrayToString(keyBytes)); komutuyla, şifre çözme işleminde kullanılan anahtar byte dizisini logluyoruz. Bu, şifre çözme işleminin hangi anahtarla gerçekleştirildiğini izlememizi sağlar.
3.Decrypted Result:
Şifre çözme işlemi tamamlandığında, console.log('Decrypted Result: ' + byteArrayToString(result));
komutuyla çözülmüş veriyi konsola yazdırıyoruz. Bu, orijinal metni veya veriyi görmemizi sağlar.
Bu yardımcı fonksiyon, byte dizisini okunabilir bir string'e dönüştürmek için kullanılır. String.fromCharCode(byteArray[i]) fonksiyonu sayesinde, byte dizisindeki her bir byte'ı karaktere dönüştürüp birleştirerek nihai string'i elde ediyoruz.
Frida kullanarak, uygulamanın root tespiti yapan metodlarını geçersiz kıldık ve AES şifre çözme işlemiyle şifreli veriyi başarıyla çözdük.