Prinsip Cara Membuat Crack Untuk Aplikasi/Game

       Pada kesempatan kali ini saya ingin menulis tentang (salah satu cara) bagaimana cracker membuat crack pada aplikasi/game. Ini salah satu ya, tentu banyak cara lainnya tidak harus melalui celah yang saya tuliskan sekarang ini. Tetapi pada intinya cracker pasti akan melakukan reverse engineering dan debugging seperti yang akan kita lakukan saat ini. Tapi contoh ini sangat sederhana, kenyataannya untuk meng-crack suatu program tidak semudah ini hehe. Emang para pembuat crack di real-world pasti jago-jago dah! Hehehe.
         Langsung saja, berikut ini terdapatlah suatu source code program game. Ini bukan game beneran, bisa dilihat dari source ini, program hanya akan mengeksekusi si game() jika key yang dimasukkan benar:
/* created by @inan19x for fun only */

#include <stdio.h>
#include <string.h>

game(){
 printf("====================\n");
 printf("welcome to the game!\n");
 printf("====================\n");
}

main(){
 char key[4];
 printf("masukkan key anda: ");
 gets(key);
 if(strcmp("asdf",key)==0){
  game();
 }
 else{
  printf("maaf key anda salah, program exit...\n");
 }
}
Challenge untuk kode diatas sekaligus menjadi sebuah pertanyaan untuk posting blog ini adalah:
Bisakah kita bermain game tanpa menggunakan key “asdf”?
         Ini tidak mungkin ‘kan, karena key “asdf” sudah di hard-coded di program. Kita tidak mungkin melawan logika program ini. Tapi dari celah keamanan pada fungsi gets di atas, kita bisa memanfaatkan bug program ini hehehe. Kembali ke awal dulu, singkat cerita bagi yang belum paham maksud program tesrebut, mari kita jalankan program di atas itu.
Program Gagal Running: Key Salah
Program Gagal Running: Key Salah
Kita coba dengan key yang benar, hasilnya adalah program game dieksekusi.
Program Berhasil Running:  Key Benar
Program Berhasil Running: Key Benar
Berikut ini vulnerability pada si deprecated function gets(), jika user memasukkan input yang sangat panjang, program akan error.
Program Error: Key Terlalu Panjang
Program Error: Key Terlalu Panjang
Sekarang kita akan memanfaatkan bug program itu dengan melihat dari GNU Debugger (gdb), apa segmentation fault ini bisa sampai memenuhi buffer dengan inputan user.
Debugging Error Step 1
Debugging Error Step 1
           Voila, ternyata input user sudah memenuhi buffer hingga meng-overwrite register EIP yang bertugas untuk mengeksekusi instruksi program selanjutnya. Kalau diperhatikan, register EIP di overwrite oleh value 0x6c6b6a69 atau kalau di convert ke ASCII adalah huruf “lkji”. Perlu diketahui bahwa sistem memory di sistem little endian di simpan terbalik seperti itu. Berarti byte ke-9 s/d 12 yang diinput user bisa sampai menimpa EIP.
             Oh ya untuk melakukan cracking ini, sangat dianjurkan untuk mengetahui lebih dulu tentang serangan stack-based buffer overflow. Pada contoh di bawah ini, saya mencoba memasukkan input 8x huruf “a” kemudian 4x huruf “b”. Untuk struktur memori dari program kita yang sedang di debug ini, mungkin bisa digambarkan stack nya adalah seperti ini:
Ilustrasi Stack dengan Input User: "aaaaaaaabbbb"
Ilustrasi Stack dengan Input User: “aaaaaaaabbbb”
Atau ini adalah gambaran dari gdb nya:
Program Memory Stack
Program Memory Stack
Mari kita coba input “abcdefghaaaa” (byte ke-9 sampai 12 dengan huruf “a”). Jika program error dengan alasan segmentation fault karena register EIP memiliki nilai 0x616161 (0x61 adalah hex untuk huruf “a”), maka ini adalah titik cerah.
Debugging Error Step 2
Debugging Error Step 2
Yippie, benar sekali. Berarti kita tinggal menimpa EIP dengan alamat memory yang seharusnya a.k.a alamat memory tempat function game() disimpan. Kita akan melakukan bypass logika if() pada program ini hehe.
Pertama-tama, mari kita disassemble fungsi game() terletak di alamat memory mana dengan gdb:
Disassemble game()
Disassemble game()
Fungsi game tersimpan di alamat memory 0x080484ac. Untuk itu kita akan menimpa EIP sedemikian sehingga akan teroverwrite dengan nilai “0x080484ac” tsb. Pada dasarnya yang akan kita lakukan sekarang adalah memasukkan 8 byte “dummy” dan byte ke-9 s/d 12 dengan alamat 0x080484ac. Kalau dicontohkan, kita harus melakukan input seperti: “aaaabbbb(0xac)(0x84)(0x04)(0x08)”.  Dengan 8 byte awal itu tentu saja sebenarnya terserah bisa diisi apa saja. Sehingga stack yang diinginkan terlihat seperti di bawah ini:
Ilustrasi Stack yang Diharapkan: Memanggil game()
Ilustrasi Stack yang Diharapkan: Memanggil game()
Nah, tetapi masalahnya bagaimana cara memberikan output dengan nilai hex? Beruntung command linux printf bisa membantu kita memasukkan hex tersebut ke dalam inputan. Berikut ini adalah caranya:
Bypass Logic Program Untuk Langsung Eksekusi: game()
Bypass Logic Program Untuk Langsung Eksekusi: game()

0 komentar:

Posting Komentar