Pembahasan Noosc CTF 2014 - Challenge 8.1

Post ini merupakan bagian dari rangkaian pembahasan cara penyelesaian challenges ajang kompetisi Noosc CTF 2014 Election Series. Penyelesaian challenge lainnya dapat dilihat pada link berikut:

Catatan Panitia

Challenge 8.1 dimaksudkan untuk menunjukkan salah satu konsep penting yang perlu diperhatikan saat merancang sistem keamanan, yakni: proteksi software seperti apapun pasti bisa ditaklukkan jika penyerang telah memiliki akses penuh ke sistem operasi.

Pengembang aplikasi memang bisa memakai teknik-teknik obfuscation untuk coba mempersulit cracker — namun jika seluruh binary dan file yang dibutuhkan untuk menjalankan aplikasi telah dimiliki penyerang, dan ia memiliki kontrol terhadap lingkungan eksekusi aplikasi tersebut (OS maupun hardware), maka pembobolan sistem proteksi aplikasi tersebut hanyalah menjadi masalah waktu saja. Kondisi mendasar inilah yang menyebabkan mengapa proteksi macam DRM itu sulit diterapkan secara efektif tanpa adanya dukungan hardware khusus yang bersifat tamper resistant.

Dalam challenge 8.1 ini, teknik obfuscation memang sengaja tidak dipakai karena memperhitungkan waktu kompetisi yang terbatas. Namun harapan kami keterbatasan proteksi software sebagaimana dijelaskan di atas tetap menjadi "take away message" untuk para peserta yang sempat mengerjakan skenario ini. Bagaimana juga, teknik security through obscurity seperti obfuscation hanyalah berguna untuk memperlambat dan mengalihkan perhatian saja, dan perlu ditopang teknik pengamanan lainnya untuk bisa lebih efektif. Kesalahan yang banyak terjadi dalam dunia nyata, adanya proteksi macam obfuscation justru menjadi alasan bagi developer untuk lebih lengah dalam menerapkan proteksi di bagian lain — dan ini yang perlu kita coba hindari bersama.

Skenario

Setelah pengambilan suara selesai, Penyelenggara Pemilu kini dapat fokus untuk menelusuri jejak komplotan hacker yang sebelumnya sering melakukan serangan-serangan untuk mengacaukan jalannya Pemilu. Setelah proses investigasi awal, Anda berhasil menemukan suatu aplikasi Android (.apk) buatan tim hacker yang hanya dapat dijalankan di gadget anggota kelompok mereka. Aplikasi ini diduga dipakai oleh anggota tim hacker untuk mendapatkan key unik masing-masing, yang selanjutnya dapat dipakai anggota untuk mengakses sistem internal tim hacker.

Challenge

Anda diminta untuk menemukan key (flag) salah satu anggota tim hacker.

Solusi

Untuk misi ini, penggunaan emulator dan SDK Android tidak mutlak diperlukan. Disini kita menggunakan tool yang umum dipakai, yaitu:

Pertama yang harus kita lakukan adalah mengkonversi file .apk menjadi .jar menggunakan tool dex2jar. Selanjutnya kita buka file hasil konversi menggunakan tool jd-gui.

Tool jd-gui memperlihatkan bahwa aplikasi ini terdiri dari beberapa package. Kita hanya perlu fokus ke satu package saja, yaitu com.anonymouse.access yang terdiri dari beberapa class seperti yang diperlihatkan pada gambar berikut.

Langkah berikutnya yaitu kita mencari fungsi utama yang menjalankan proses generate key. Fungsi utama ini bisa kita temukan di class FormActivity seperti yang bisa kita lihat di bawah.

 public void onClick(View paramView){
String str1 = UUID.randomUUID().toString();
String str2 = FormActivity.this.editTextMember.getText().toString();
byte[] arrayOfByte1 = { 97, 108, 103, 101, 98, 114, 97 };
byte[] arrayOfByte2 = { 102, 97, 114, 97, 98, 105 };
byte[] arrayOfByte3 = { 101, 117, 108, 101, 114 };
byte[] arrayOfByte4 = { 103, 97, 117, 115, 115 };
byte[] arrayOfByte5 = { 100, 101, 115, 99, 97, 114, 116, 101, 115 };
String str3 = new String(arrayOfByte1);
if (str2.equals(str3)){
FormActivity.this.editTextKey.setText(Utils.b(FormActivity.this.a + str3.charAt(3)));
return;
}
if (str2.equals(new String(arrayOfByte2).toString())){
FormActivity.this.editTextKey.setText(Utils.b(FormActivity.this.a + new String(arrayOfByte2).charAt(3)));
return;
}
if (str2.equals(new String(arrayOfByte3).toString())){
FormActivity.this.editTextKey.setText(Utils.b(FormActivity.this.a + new String(arrayOfByte3).charAt(2)));
return;
}
if (str2.equals(new String(arrayOfByte4).toString())){
FormActivity.this.editTextKey.setText(Utils.b(FormActivity.this.a + new String(arrayOfByte4).charAt(3)));
return;
}
if (str2.equals(new String(arrayOfByte5).toString())){
FormActivity.this.editTextKey.setText(Utils.b(FormActivity.this.a + new String(arrayOfByte5).charAt(6)));
return;
}
if (str2.length() < 2){
FormActivity.this.editTextKey.setText(FormActivity.this.getString(2131230761));
return;
}
FormActivity.this.editTextKey.setText(str1);
}

Fungsi ini juga menjalankan fungsi lain di luar class FormActivity, yaitu fungsi b() yang ada di class Utils seperti yang terlihat seperti di bawah.

 public static final String b(String paramString) {
try {
MessageDigest localMessageDigest = MessageDigest.getInstance(new String(new byte[] { 77, 68, 53 }));
localMessageDigest.update(paramString.getBytes());
byte[] arrayOfByte = localMessageDigest.digest();
StringBuffer localStringBuffer = new StringBuffer();
int i = 0;
if (i >= arrayOfByte.length)
return localStringBuffer.toString();
String str;
for (Object localObject = Integer.toHexString(0xFF & arrayOfByte[i]); ; localObject = str){
if (((String)localObject).length() >= 2){
localStringBuffer.append((String)localObject);
i++;
break;
}
str = "0" + (String)localObject;
}
}
catch (Exception localException){
localException.printStackTrace();
}
return (String)"";
}

Code ini butuh penyesuaian, karena hasil output jd-gui agak sedikit berantakan di bagian for loop. Sehingga code baru akan nampak seperti dibawah

 public static String b(String paramString) throws NoSuchAlgorithmException{
MessageDigest localMessageDigest = MessageDigest.getInstance(new String(new byte[] { 77, 68, 53 }));
localMessageDigest.update(paramString.getBytes());
byte[] arrayOfByte = localMessageDigest.digest();
StringBuffer localStringBuffer = new StringBuffer();
int i = 0;
String str="";
for (;;){
if (i >= arrayOfByte.length)
 return localStringBuffer.toString();
String localObject = Integer.toHexString(0xFF & arrayOfByte[i]);
if (((String)localObject).length() < 2){
str = "0" + (String)localObject;
localObject = str
}
localStringBuffer.append((String)localObject);
i++;
}
}

Kemudian kita tinggal mencari satu komponen lagi, yaitu variabel FormActivity.this.a. Variabel ini di-assign di dalam fungsi initFacebookInfo()

 private void initFacebookInfo(){
Session localSession = Session.getActiveSession();
Request.newMeRequest(localSession, new Request.GraphUserCallback(localSession){
public void onCompleted(GraphUser paramGraphUser, Response paramResponse){
if ((this.val$session == Session.getActiveSession()) && (paramGraphUser != null)){
FormActivity.this.profilePicture.setProfileId(paramGraphUser.getId());
FormActivity.this.textUsername.setText(paramGraphUser.getName());
FormActivity.this.a = paramGraphUser.getUsername();
}
if (paramResponse.getError() != null)
 Toast.makeText(FormActivity.this.getApplicationContext(), "Failed to get user info", 0).show();
}
}).executeAsync();
}

Sekarang kita tinggal menulis ulang apa-apa yang telah kita dapatkan di atas.

 import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

public class Main {

public static String b(String paramString) throws NoSuchAlgorithmException{
MessageDigest localMessageDigest = MessageDigest.getInstance(new String(new byte[] { 77, 68, 53 }));
localMessageDigest.update(paramString.getBytes());
byte[] arrayOfByte = localMessageDigest.digest();
StringBuffer localStringBuffer = new StringBuffer();
int i = 0;

String str="";
for (;;){
if (i >= arrayOfByte.length)
return localStringBuffer.toString();
String localObject = Integer.toHexString(0xFF & arrayOfByte[i]);
if (((String)localObject).length() < 2){
str = "0" + (String)localObject;
localObject = str;
}
localStringBuffer.append((String)localObject);
i++;
}
}

public static void clickButton(String str2) throws NoSuchAlgorithmException{
byte[] arrayOfByte1 = { 97, 108, 103, 101, 98, 114, 97 };
byte[] arrayOfByte2 = { 102, 97, 114, 97, 98, 105 };
byte[] arrayOfByte3 = { 101, 117, 108, 101, 114 };
byte[] arrayOfByte4 = { 103, 97, 117, 115, 115 };
byte[] arrayOfByte5 = { 100, 101, 115, 99, 97, 114, 116, 101, 115 };
String str3 = new String(arrayOfByte1);
System.out.println(Main.b(str2+new String(arrayOfByte5).charAt(6)));
}

public static void main(String[] args) throws NoSuchAlgorithmException {
if (args.length > 0) {
String str2 = args[0]; //facebook username
Main.clickButton(str2);
}else{
System.out.println("Please supply valid username");
}
}
}

Kemudian kita lakukan kompilasi menggunakan JDK dan jalankan aplikasi dengan argumen username. Setiap peserta akan mendapatkan flag yang unik :)


Comments

Blog Categories

Blog Tags

Latest Tweets

@noosc @agiant Oke baik, kita tampung dulu ya sarannya :) #NOOSC April 11, 2014, 4:52 p.m.
@noosc @ic4love Gpp, ini buat entry-level, bisa dicoba dulu. Selama sudah ada minatnya, mungkin saja cocok bisa :) April 10, 2014, 8:59 p.m.
@noosc Job Opportunity: Information Security Analyst. Right now we have an opening for entry-level position in our SOC Team http://t.co/H6mlkqW47D April 10, 2014, 2:45 p.m.
@noosc Pembahasan challenges dalam Noosc CTF 2014 sudah bisa diakses di http://t.co/7F014QoeOL ! April 8, 2014, 7:57 p.m.
@noosc Setelah melakukan proses verifikasi, kami dari Noosc Global mengucapkan selamat kepada janglapuk (abijafar) sebagai pemenang Noosc CTF 2014! April 8, 2014, 6:04 p.m.