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.
Kita coba dengan key yang benar, hasilnya adalah program game dieksekusi.
Berikut ini vulnerability pada si deprecated function gets(), jika user memasukkan input yang sangat panjang, program akan error.
Sekarang kita akan memanfaatkan bug
program itu dengan melihat dari GNU Debugger (gdb), apa segmentation
fault ini bisa sampai memenuhi buffer dengan inputan user.
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:
Atau ini adalah gambaran dari gdb nya:
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.
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:
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:
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:
0 komentar:
Posting Komentar