Android – UnCrackable-Level3 Solution

Merhabalar,

bu yazıda OWASP Uncrackable-Level3 android uygulamasının çözümünü inceleyeceğiz.

İlk olarak uygulama “.apk” dosyasının içeriği herhangi bir arşiv açma aracı kullanarak dışarı çıkartılır ve uygulamaya ait “.dex” dosyası elde edilir. Uygulama kodlarını JD-GUI decompiler aracı ile inceleyebilmek için “.dex” dosyalarını “.jar” formatına dönüştürmemiz gerekmektedir. Dönüşüm işlemi “d2j-dex2jar” aracı yardımı ile gerçekleştirilmektedir.

JD-GUI decompiler aracı ile elde edilmiş olan “classes-dex2jar.jar” dosyası açılır ve uygulama kodları incelenmeye başlanır. “MainActivity” sınıfına ait “onCreate” metodunun, uygulamanın çalışmaya başlaması ile tetiklendiği ve içerisindeki işlemleri gerçekleştirdiği görülmektedir.

“onCreate” metodu içerisinde;

  • Root kontrolü
  • Native kütüphanesi bütünlük kontrolü
  • Debuggable özelliğinin kontrolü

Sistem üzerinde root, bütünlük veya debuggable ihlallerinden birisinin tespiti sonucunda ise uygulamanın “showDialog” metodu kullanılarak kapatıldığı görülmektedir. Genel yapısı itibari ile UnCrackable-Level2 uygulamasına benzediği görülmektedir.

Uncrackable-Level2 uygulamasından farklı olarak Uncrackable-Level3 içerisinde bütünlük kontrolü yöntemi ile binary patching işlemine karşı önlem alındığı görülmektedir. Bu kontrolün atlatılması, “.smali” kodlarının değiştirilmesi ile gerçekleştirilebilmektedir. Peki smali nedir?

Smali/Backsmali, assembler/dissassembler araçlarıdır. Yani? Android uygulamaları içerisinde bulunan “.dex” dosyaları insan gözü ile okunarak anlaşılamayacak kadar karmaşıktır. Backsmali aracı “.dex” dosyaları insanlar tarafından anlaşılabilir bir formatta dönüştürülebilmesini sağlanmaktadır. Bir diğer önemli konu ise, backsmali aracı ile elde edilen anlaşılır kodların değiştirilebilmesi ve smali aracı kullanılarak tekrar “.dex” formatına dönüştürülebilmesidir. Bu işlemin ismi smali injection olarak bilinmektedir.

Smali injection işlemi için bizler “apktool” aracını kullanacağız. Apktool smali dönüşümüne ek olarak, “.apk” içerisinde bulunan “AndroidManifest.xml” vb. dosyaların da okunabilir formata dönüştürülmesini sağlamaktadır.

Not: “.apk” dosya içeriğinin herhangi bir arşiv aracı kullanarak dışarı çıkartılması ile “AndroidManifest.xml” dosyası elde edilebilir. Elde edilen bu dosya herhangi bir text-editör yardımı ile açıldığında içeriği aşağıdaki şekilde görünmektedir.

“apktool d UnCrackable-Level3.apk” komutu ile uygulama kodlarının decode/disassemble edilmesi gerçekleştirilmektedir (“d” parametresi decode/disassemble işlemi için kullanılmaktadır)

İşleminin tamamlanmasının ardından, oluşan klasör içerisinde bulunan “smali/sg/vantagepoint/uncrackable3/MainActivity.smali” dosyası herhangi bir text-editör yardımı ile açılmaktadır.

JD-GUI üzerinde tespit edilen kontrollerin “MainActivity.smali” dosyası üzerinden silinebilmesi için ilk olarak “onCreate” metodunun yeri tespit edilmelidir.

Smali kodları içerisinde  bu kontrolleri gerçekleştirildiği bölüm aşağıdaki şekildedir.

Görüldüğü üzere “if-nez” şartlanma komutu ile “checkRoot1()Z”, “checkRoot2()Z” ve diğer metotların kontrol edildiği, tespit edilen bir durum sonucunda ise “cond_0” tag değerine sıçrama gerçekleştirilmektedir. Tespit edilen tüm kontrollere ait smali kodlarının silinmesi sonrasında elde edilen görüntü aşağıdaki şekildedir.

Elde edilen yeni smali kodları, “apktool b UnCrackable-Level3” komutu kullanılarak “.apk” dosyasına dönüştürülür (İlgili “.apk” dosyası “UnCrackable-Level3/dist” dizini altında bulunmaktadır)

Oluşturulan “.apk” dosyası imzalanarak sistem üzerine yüklenmelidir. Aksi taktirde mobil cihaz içerisinde çalıştırılmayacaktır. İmzalama işlemi iki adımda gerçekleştirilmektedir.

  1. İmzalama işleminde kullanılacak olan “keystore” dosyasının oluşturulması.
  2. “Jarsign” aracı kullanılarak, oluşturulmuş olan “keystore” ile “.apk” dosyasının imzalanması.

“keytool -genkey -v -keystore newStoreName.keystore -alias aliasName -keyalg RSA -keysize 2048 -validity 10000” komutu kullanılarak “keystore” oluşturma işlemi gerçekleştirilmektedir.

Daha sonra “jarsigner -verbose -sigalg SHA1withRSA -digestalg SHA1 -keystore keyStoreName.keystore apkName.apk aliasName” komutu ile “.apk” dosyası imzalanmaktadır.

Elde edilen “.apk” dosyası emulatör içerisine yüklenir ve uygulama çalıştırılarak güvenlik kontrollerinin kaldırıldığı görülür.

Bir sonraki aşamada cihaz üzerinde çalışan uygulamaların listesi görüntülenmektedir.

“owasp.mstg.uncrackable3” paketine ait iki farklı PID değeri bulunduğu görülmektedir. Uygulama içerisinde anti-debugging araçlarına karışı bu önlemin alındığı görülmektedir (UnCrackable-Level2 uygulama çözümünde anti-debugging yöntemi ve bypass edilmesine ilişkin detaylar bulunmaktadır)

Anti-Debugging kontrolünün gerçekleştirilmiş olduğu alanın tespit edilmesi için radare2 aracı ile “libfoo.so” kütüphanesi içerisinde bulunan ve JNI çağrısı ile dışarıdan çağırılan metotlar incelenir.

“init” metodunun incelenmesi esnasında “fcn.00003250” fonksiyonunun çağırıldığı görülmektedir.

“fcn.00003250” metodunun içeriği görüntülendiğinde ise “ptrace” sistem çağırısı kullanıldığı görülmektedir. “ptrace” kullanımı ile uygulamanın kendisine attach olduğu ve bu nedenle aynı paket adına ait iki farklı PID değeri ile karşılaştığımız anlaşılmaktadır.

Tespit edilen kontrollerin, “0x0000325c” adresinde bulunan “call” metodu ile başladığı görülmektedir. Bu metot “call 0x3304” olacak şekilde güncellenir ve uygulamanın “ptrace” sistem çağrılarına uğramadan sonlanması sağlanılır.

Daha sonra, güncellenen “libfoo.so” kütüphanesi emulatör içerisinde bulunan “/data/app/owasp.mstg.uncrackable3-1/lib/x86” dizini altı taşınır ve ardından uygulama çalıştırılır. Çalışan uygulamaların listesi görüntülendiğinde “owasp.mstg.uncrackable3” paketine ait tek PID değeri bulunduğu görülmektedir.

Çözüme giden son adımda uygulama içerisinde bulunan gizli ifadenin tespiti gerçekleştirilecektir. İşe uygulama kaynak kodları incelenerek başlanır ve gizli ifade doğrulama işleminin “MainActivity” sınıfı içerisinde bulunan “verify” metodu ile gerçekleştirildiği tespit edilir.

Metot içerisinde “CodeCheck” sınıfına ait “check_code” kontrolünün çağırıldığı görülmektedir. “CodeCheck” sınıfı incelendiğinde ise “check_code” metodunun içerisinde “bar” isimli bir metot çağırıldığı ve bu metodun native kütüphane içerisinde tanımlandığı anlaşılmaktadır.

Bu bilginin ardından radare2 aracı ile native kütüphane – “libfoo.so” dosyası açılır ve içerisinde bulunan metotlar listelenir.

“Java_sg_vantagepoint_uncrackable3_CodeCheck_bar” metoduna ait adres bilgisi bu şekilde elde edilir.

“s 0x000033b0” komutu ile imleç konumu “bar” metot adresine taşınır ve “VV” komutu ile metot içeriği görselleştirilir.

Kullanıcıdan alınan girdi ile uygulama içerisinde bulunan statik bir ifadenin karşılaştırılması gerektiği bilinmektedir. Bu nedenle karşılaştırma operatörleri dikkatli bir şekilde incelenir.

İlk olarak “0x00003432” adresinde bulunan kontrol incelenir.

0x18 hexadecimal değeri ile “eax” kaydedicisi içerisinde bulunan değer karşılaştırılmaktadır. “eax” içerisinde bulunan değeri öğrenebilmek için GDB yardımı ile uygulama debug edilir.

Öncelikle “gdb” içerisinde “info sharedlib” komutu çalıştırarak, native kütüphanenin yerleşmiş olduğu bellek adres bilgisi elde edilir.

“0xaecb59e0” adresi, uygulamaya ait offset adres değerini de içermektedir. Offset değeri uygulamanın çalışmaya başlayacağı (entry point) değeri belirtmektedir. Radare2 aracı ile “ie” komutu kullanılarak uygulamanın entry point adresi elde edilebilir.

Offset değeri”0x9e0″ olarak elde edilir. “0xaecb59e0” adres değerinden offset değerinin çıkartılması sonucunda uygulama için ayrılmış olan bellek alanının başlangıç değeri elde edilmektedir – “0xaecb5000”. Disassembler içerisinde tanımlanmış olan adres değerlerinin ofset değerini içermemesi nedeni ile adres dönüşüm işlemi gerçekleştirilmelidir.

Bu bilgilerin ardından “0x00003432” adresine break point yerleştirerek “eax” değerinin içeriğini elde edilir. Uygulama base adres değeri “0xaecb5000” olarak belirlenmişti, bu nedenle break point adresi “0xaecb8432” şeklinde dönüştürülür.

Ara yüz üzerinde “1111” gibi rastgele bir ifade girerek uygulamanın break point noktasına yönlendirilmesi sağlanır.

Amacımız “eax” kaydedicisinin içeriğini görüntülemek, bu nedenle “info registers” komutu ile kaydedicilere ait bilgilerin ekranda gösterilmesi sağlanılır.

“eax” kaydedicisi içerisinde “4” decimal değerinin bulunduğu görülmektedir. Elde edilen değer, girmiş olduğumuz ifade uzunluğunu temsil etmektedir. Bu şekilde gizli ifadenin 0x18 hexadecimal (0x18 = 24 decimal) büyüklüğünde olması gerektiğini tespit ediyoruz.

Karakter boyutunun 24 olduğu durum sonrasında, uygulama “0x00003440” adresine yönlendirilmekte olup, “0x00003446” adresinde başka bir karşılaştırma metodu kullanıldığı görülmektedir. Karşılaştırma esnasında kullanılan kaydedici değerlerinin görüntülenebilmesi için GDB ile “0xaecb8440” adresine break point yerleştirilmektedir (Adres değerleri base adres üzerine eklenerek hesaplanmıştır)

Daha sonra uygulama ara yüzü üzerinden 24 karakterden oluşan rastgele bir ifade girilir. Ardından, “0xaecb8440” adresinde bulunan break point noktasına erişim sağlanır ve “info register” komutu ile kaydedicilerin mevcut durumu görüntülenir.

Radare2 üzerinden de görüleceği üzere “edx” kaydedicisine, “ecx” kaydedicisi içerisinde bulunan adres değerinin barındırdığı ifade aktarılmaktadır. Ardından “dl” kaydedicisi içerisinde bulunan ifade ile “esp + eax” kaydedicileri içerisindeki adres değerlerinin toplamı ile oluşan yeni adres değerinin içerdiği ifade “xor” işlemine tabi tutulur ve sonuç “dl” kaydedicisi içerisine aktarılır (“dl” kaydedicisi “edx” kaydedicisinin düşük değerli 8 bitlik bölümünü içermektedir)

Son olarak da “dl” kaydedicisinin içerdiği değer ile, “esi + eax” kaydedicileri içerisinde adres değerlerinin toplanması ile oluşturulan adres değerinde bulunan ifadenin karşılaştırılması gerçekleştirilmektedir.

“eax” kaydedicisinin içeriğinin boş olduğu “info registers” komutu sonucunda görülmektedir. Bu nedenle karşılaştırma işlemi “esp” ve “esi” kaydedicileri içerisinde bulunan adreslerin içerdiği değerler üzerinden gerçekleştirilmektedir.

“x/s 0xaecbb01c” komutu ile “ecx” kaydedicisi içerisinde bulunan adres değerinin içerdiği ifade ekranda gösterilmektedir.

“x/s 0xbfb04450” komutu ile “esp” kaydedicisi içerisinde bulunan adres değerinin içerdiği ifade ekranda gösterilmektedir.

Fakat elde edilen ifade çok anlamlı görünmemektedir. Bu nedenle “x/24x 0xbfb04450” komutu ile belirtilen adres üzerindeki ilk 24 değerin hexadecimal olarak ekranda görüntülenmesi sağlanmaktadır.

Daha sonra “x/s 0xa380c08” komutu ile “esi” kaydedicisi içerisinde bulunan adres değerinin içerdiği ifade ekranda gösterilir ve kullanıcıdan alınan ifadeyi içerdiği tespit edilir.

Uygulama tarafından gizli ifade doğrulamak için kullanılan tüm bileşenler bu şekilde elde edilmektedir. Geriye “esp” ile “dl” kaydedicileri içerisinden elde edilen değerlerin “xor” işleminde kullanılması ile sonucun elde edilmesi kalmıştır. Bu işlemin gerçekleştirilmesi için aşağıdaki python kodu geliştirilmiştir.

Script çalıştırıldığında gizli ifadenin elde edildiği görülmektedir.

Son olarak elde edilen değerin emulatör üzerinden doğruluğu test edilir.

Yazar: Ahmet Akan

2016 Karabük Üniversitesi Bilgisayar Mühendisliği Mezunu. Kariyerine Uygulama Güvenliği Analisti olarak başladı ve bu alanda görev almaya devam etmekte.

6 thoughts on “Android – UnCrackable-Level3 Solution

    neil

    (Ekim 24, 2019 - 8:31 am)

    https://github.com/OWASP/owasp-mstg/blob/master/Crackmes/Android/Level_03/UnCrackable-Level3.apk
    libfoo.so There are two questions
    1、ida Tips
    (1)Bad file structure or read error (line 1134). Continue?
    (2)File contains meaningless/illegal section declarations, using program sections
    2、gdb info sharedlibary unable to get memory address
    How did you solve it?

      Ahmet Akan

      (Ekim 25, 2019 - 8:40 pm)

      Hi, can you give more detail about your test platform? Did you use emulator or real device etc. I didn’t use IDA but I will try it.

    neil

    (Ekim 28, 2019 - 2:11 am)

    Hi, the download address is https://github.com/OWASP/owasp-mstg/blob/master/Crackmes/Android/Level_03/UnCrackable-Level3.apk
    I use emulator x86 libfoo.so
    I refer to your blog to try to use GDB, but the prompt is that ELF file without memory address is malformed.

    neil

    (Ekim 28, 2019 - 7:36 am)

    Section Headers:
    [Nr] Name Type Addr Off Size ES Flg Lk Inf Al
    [ 0] NULL 00000000 000000 000000 00 0 0 0
    [ 1] .note.android.ide NOTE 00000134 000134 000098 00 A 0 0 2
    [ 2] .note.gnu.build-i NOTE 000001cc 0001cc 000024 00 A 0 0 4
    [ 3] .dynsym DYNSYM 000001f0 0001f0 000230 10 A 4 1 4
    [ 4] .dynstr STRTAB 00000420 000420 00021d 00 A 0 0 1
    [ 5] .hash HASH 00000640 000640 0000d8 04 A 3 0 4
    [ 6] .gnu.version VERSYM 00000718 000718 000046 02 A 3 0 2
    [ 7] .gnu.version_d VERDEF 00000760 000760 00001c 00 A 4 1 4
    [ 8] .gnu.version_r VERNEED 0000077c 00077c 000020 00 A 4 1 4
    [ 9] .rel.dyn REL 0000079c 00079c 000048 08 A 3 0 4
    [10] .rel.plt REL 000007e4 0007e4 0000a0 08 AI 3 20 4
    [11] .plt PROGBITS 00000890 000890 000150 04 AX 0 0 16
    [12] .text PROGBITS 000009e0 0009e0 002a94 00 AX 0 0 16
    [13] .rodata PROGBITS 00003480 003480 00008d 00 AMS 0 0 16
    [14] .eh_frame PROGBITS 00003510 003510 000eec 00 A 0 0 4
    [15] .eh_frame_hdr PROGBITS 000043fc 0043fc 00043c 00 A 0 0 4
    [16] .fini_array FINI_ARRAY 00005e6c 004e6c 000008 04 WA 0 0 4
    [17] .init_array INIT_ARRAY 00005e74 004e74 000004 04 WA 0 0 4
    [18] .dynamic DYNAMIC 00005e78 004e78 000118 08 WA 4 0 4
    [19] .got PROGBITS 00005f90 004f90 000014 00 WA 0 0 4
    [20] .got.plt PROGBITS 00005fa4 004fa4 00005c 00 WA 0 0 4
    [21] .data PROGBITS 00006000 005000 000008 00 WA 0 0 4
    [22] .bss NOBITS 00006008 005008 000034 00 WA 0 0 4
    [23] .comment PROGBITS 00000000 005008 000108 01 MS 0 0 1
    [24] .note.gnu.gold-ve NOTE 00000000 005110 00001c 00 0 0 4
    [25] .shstrtab STRTAB 00000000 00512c 000105 00 4249878528 65107 1
    readelf: Warning: section 25: sh_link value of 4249878528 is larger than the number of sections

      Ahmet Akan

      (Ekim 28, 2019 - 1:15 pm)

      Can you send a screenshot of the steps you have taken to akn.ahmet@msn.com? Because I didn’t take any error.

    neil

    (Ekim 31, 2019 - 3:06 am)

    dear Ahmet Akan I’ve emailed you and I’m looking forward to your reply

Bir cevap yazın

E-posta hesabınız yayımlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir