CTFZone 2018 android_ololo_country_checker

Points : 314 , 8 takım çözdü

Sorunun açıklaması :

1
It's a foreign android application. Let's try to guess the country!

Ve bir apk verildi. ololo.apk

Apkdaki dosyalarımız :
apk

APKyı jadx ile açtığımda, jadx’in classları düzgün decompile edemediğini gördüm. Hazır açmışken native kütüphane var mı diye baktım ve lib/armeabi-v7a altında libnative-lib.so dosyasını gördüm. Şimdii normalde android emulatoru olarak genymotion kullanmaktaydım. Ancak bu native so dosyasını apk’nın çalıştırabilmesi için arm tabanlı bir imaj kullanmam gerek, genymotionda arm sistem ayağa kaldırmak malesef mümkün değil. O yüzden paşa paşa android studioyu kurup armeabi-v7a lı bir imaj kurmamız gerekiyor. Ve apkmızın MainActivity’sindeki

1
2
if (System.getProperty("os.arch").equalsIgnoreCase("armeabi-v7a")) {
System.loadLibrary("native-lib");

şu if’i kaldırmamız gerekiyor. Kaldırmazsak so dosyasını yükleyemiyor . Bu işlem için önce apktool d ololo.apk ile decompile edip ilgili yeri silin (bu sefer size bırakıyorum) ve apktool b ololo.apk ile build edin. Sign ettikten sonra apkyı telefona yükleyin.Uygulamayı açtığımızda karşımıza aşağıdaki ekran geliyor. Check’e bastığınızda crash almıyorsanız if kısmını doğru yapmışsınız demektir. Her checke basıldığında resim ve alttaki stringler değişiyor.

open

Java classlarını decompile edebilmek için önce apk’yı zip’e çevirdim ve içinden classes.dex’i çıkardım. Ardından bu dex dosyasını https://github.com/pxb1988/dex2jar/releases ile jar’a çevirdim. Jar dosyasını http://www.benf.org/other/cfr/ aracı ile java hale getirdim.

1
java -jar cfr_0_132.jar classes-dex2jar.jar > main.java

main.java dosyasını incelemeye koyuldum. Çok güzel anti-debugging methodları bulunmaktaydı. Genel olarak aaa.aie.* classlarının ilk methodu get, ikincisi de gelen parametre ile bu get’in karşılaştırılması idi.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
package aaa.aie;

import android.content.Context;
import android.telephony.TelephonyManager;

public class ekd {
public static String egdi(Context context) {
return ((TelephonyManager)context.getSystemService("phone")).getDeviceId();
}

public static boolean ehkdi(Context object, String[] arrstring) {
object = ekd.egdi(object);
int n = arrstring.length;
for (int i = 0; i < n; ++i) {
if (!arrstring[i].equalsIgnoreCase((String)object)) continue;
return true;
}
return false;
}
}

  • aaa.aie.eka.ega -> getSDKVersion
  • aaa.aie.eka.egn -> getPackageName // uygulamanın adı
  • aaa.aie.ekd.egdi -> getDeviceId
  • aaa.aie.eki.egsi -> getSubscriberId
  • aaa.aie.ekl.egsci -> getSimCountryIso
  • aaa.aie.ekpn.egln -> getLine1Number

ololo.ololo.ololo.MainActivity.getSoBody methodu res/raw altındaki resimleri alıp işleme tabi tutmaktaydı. Daha fazla işlem göremeyince asıl işin so dosyasında yapıldığını düşünüp native dosyamıza dalmaya karar verdim.

libnative-lib.so dosyamızı IDAPro’da açtım. 2 fonksiyonumuz dışında hiçbir fonksiyonun ismi hoş gözükmüyordu.

ida

O iki fonksiyonun isminin öyle olmasının nedeni apkımızın MainActivity sinde çağırılmaları. Bu fonksiyonları incelemeye koyuldum. Öncelikle sorunun ismiyle alakalı olduğu için Java_ololo_ololo_ololo_MainActivity_checkSomethings ile başladım. Fonksiyonumuz yaklaşık 90 tane variable tanımladıktan sonra 4 adet fonksiyon çağırmakta

var

Bu 4 fonksiyonun birine gittiğimde gözüme hemen paket isimleri ilişti

fonk

Tam olarak emin olmasamda aaa.aie.ekl.egsci ‘yi çağırıp dönen değeri dword_9ABC’ye atadığı sonucuna vardım. Değişkeni ve fonksiyonun adını ilgili method ne yapıyorsa ona göre adlandırdım. Bu örnek için fonksiyon ismi -> getSimCountryIso ve dword_9ABC -> strSimCountryIso

4 fonksiyonda da bu şekilde isimlendirme yaptım.

md5

j_ ile başlayan fonksiyonlarda çok fazla işlem vardı. string değerleri sırayla bu 3 fonksiyona tabi tutuluyordu. Belkii md5 ?? .. Bi ihtimal diyip v84’e md5(strSubscriberId) diyip yoluma devam ettim. Açıkcası burdan sonra biraz tahmin biraz atma tutma oldu diyebilirim. Kafamdaki senaryo cihazdan topladığı bilgilerin md5ini alıp karşılaştırıyor eğer uyuyorsa bize flagi veriyor.

md5s

Bu byte** değişkenlerindeki değerlere bakarsak;

byte

online araçlarla hepsinin karşılığını buluyoruz.

1
2
3
4
5
6
phone    = 8203412(03bec67d849e7114f1a828e1628495fe)/7793952(c377ec2ae9bc906448b6c39326e42f04)
deviceID = 89123988(e176e3acf427e59308520009b3e2a793)/01982375(b400b6e082104ce63f18f45e64c2fbfd)
iso_code = KZ(4aceb7d6b4564ec96bc6605cd5af37e7)/KG(56d721ccadb8bbfd8b47390d82a6ea4b)
subscriberID = 31231712(5b529e731eab2fb96185b0e9769fc498)
sdk_ver = 19(1f0e3dad99908345f7439f8ffabdffc4)
package_name = ololo.ololo.ololo(5b4802bc02112666dabafe0c77ac18d0)

Evet tahminlerim doğru gibi. Daha fazla arm’da boğulmadan bu değerleri döndürecek bir frida scripti yazıp denemek lazım. Eğer daha önce frida kurmadıysanız kısaca özetlersek

pip install frida ile client’a frida kuruyoruz.

https://github.com/frida/frida/releasesdan telefona veya emulatore uygun son surum server’ı indirip adb push frida-dosyaismi /data/local/tmp ile pushluyoruz. chmod +x frida-dosyaismi ./frida-dosyaismi ile serverı başlatıyoruz.
Ardından clientta frida-ps -U dersek telefonda çalışan uygulamaları görebiliriz.
Instrumentation yapıcağımız uygulamayı listeden kopyalayıp frida -U ololo.ololo.ololo -l script.js diyerek scriptimizi load edebiliyoruz.

Frida scriptimiz çok basit.

  • aaa.aie.eka.ega -> getSDKVersion
  • aaa.aie.eka.egn -> getPackageName // uygulamanın adı
  • aaa.aie.ekd.egdi -> getDeviceId
  • aaa.aie.eki.egsi -> getSubscriberId
  • aaa.aie.ekl.egsci -> getSimCountryIso
  • aaa.aie.ekpn.egln -> getLine1Number

şu fonksiyonlara md5’ini bulduğumuz değerleri döndüreceğiz.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
Java.perform(function () {
const JavaString = Java.use('java.lang.String');
var EADB = Java.use("aaa.aie.eadb");
EADB.headb.implementation = function () {
console.log("Called - aaa.aib.aib()");
return false;
}
var EKPN = Java.use("aaa.aie.ekpn"); // PhoneNumber
EKPN.egln.implementation = function () {
console.log("Called - aaa.aie.ekpn.egln()");
// return "7793952";
return "8203412";
};
var EKD = Java.use("aaa.aie.ekd"); // DeviceId
EKD.egdi.implementation = function () {
console.log("Called - aaa.aie.ekd.egdi()");
return "89123988";
// return "01982375";
};
var EKL = Java.use("aaa.aie.ekl"); // SimIsoCountry
EKL.egsci.implementation = function () {
console.log("Called - aaa.aie.ekl.egcsi()");
return "KZ";
//return "KG";
}
var EKA = Java.use("aaa.aie.eka");
EKA.ega.implementation = function () {
console.log("Called - aaa.aie.eka.ega()");
return JavaString.$new("19");
}
EKA.egn.implementation = function () {
console.log("Called - aaa.aie.eka.egn()");
return "ololo.ololo.ololo";
}
var EKI = Java.use("aaa.aie.eki");
EKI.egsi.implementation = function () {
console.log("Called - aaa.aie.eki.egsi()");
return "31231712";
}
Java.choose("ololo.ololo.ololo.MainActivity", {
onMatch : function(instance) {
instance.e.value = 0;
instance.c.value = 0;
},
onComplete : function () {}
});
});

Vee FLAG : ctfzone{1t_1s_0l0l0_g00d_4tt6mpt}

sol