Tutorial ini membahas soal reversing malemsabtuiseng. Tool yang digunakan pada tutorial ini adalah gdb. Langkah pertama adalah mencari tahu format soal tersebut (langkah ini sifatnya opsional).
Terlihat bahwa soalnya menggunakan static linking, jadi fungsi-fungsi libc yang biasanya dapat dengan mudah dikenali tidak akan terlihat jelas pada aplikasi/soal tersebut. Selanjutnya, gunakan gdb untuk me-load soal tersebut dan kemudian pasang breakpoint pada fungsi main:
Lanjutkan proses debugging dengan menjalankan soal tersebut, maka Anda akan tiba pada breakpoint pada fungsi main:
Disassemble sejumlah instruksi pada fungsi main (misalnya 30 instruksi) untuk melihat alur eksekusinya:
Untuk lebih jelasnya, berikut ini adalah gambar di atas beserta penjelasan singkat beberapa instruksi yang perlu diperhatikan:
gdb> x/30i $pc
=> 0x4009ae <main>: push rbp
0x4009af <main+1>: mov rbp,rsp
0x4009b2 <main+4>: sub rsp,0x20
0x4009b6 <main+8>: mov DWORD PTR [rbp-0x14],edi ; argc
0x4009b9 <main+11>: mov QWORD PTR [rbp-0x20],rsi ; argv <<------------------------------------,
0x4009bd <main+15>: mov rax,QWORD PTR fs:0x28 ; ^
0x4009c6 <main+24>: mov QWORD PTR [rbp-0x8],rax ; ^
0x4009ca <main+28>: xor eax,eax ; eax = 0 ^
0x4009cc <main+30>: cmp DWORD PTR [rbp-0x14],0x3 ; periksa apakah argc == 3 ^
0x4009d0 <main+34>: jne 0x400a21 <main+115> ; jika tidak, maka loncat ke alamat 0x400a21 ^
0x4009d2 <main+36>: mov rax,QWORD PTR [rbp-0x20] ; ingat ini [rbp-0x20] >>--------------------+
0x4009d6 <main+40>: add rax,0x10 ; ^
0x4009da <main+44>: mov rax,QWORD PTR [rax] ; ^
0x4009dd <main+47>: mov rsi,rax ; ^
0x4009e0 <main+50>: mov edi,0x4a1388 ; edi = "Memeriksa password %s \n" ^
0x4009e5 <main+55>: mov eax,0x0 ; ^
0x4009ea <main+60>: call 0x40f430 <printf> ; printf("Memeriksa password %s \n"); ^
0x4009ef <main+65>: mov rax,QWORD PTR [rbp-0x20] ; ingat ini [rbp-0x20] >>--------------------'
0x4009f3 <main+69>: add rax,0x10 ;
0x4009f7 <main+73>: mov rax,QWORD PTR [rax] ;
0x4009fa <main+76>: mov esi,0x4a13a1 ; esi = "_init_array"
0x4009ff <main+81>: mov rdi,rax ; rdi = argumen ke-3 pada command line
0x400a02 <main+84>: call 0x400360 ; panggil fungsi strcmp
0x400a07 <main+89>: test eax,eax ; periksa hasilnya
0x400a09 <main+91>: jne 0x400a17 <main+105> ; jika tidak sama, maka lompat ke sini -----.
0x400a0b <main+93>: mov edi,0x4a13b0 ; edi = "Anda telah berhasil masuk, ..." v
0x400a10 <main+98>: call 0x40fe30 <puts> ; puts("Anda telah berhasil masuk, ..."); v
0x400a15 <main+103>: jmp 0x400a21 <main+115> ; lompat ke alamat 0x400a21 v
0x400a17 <main+105>: mov edi,0x4a141d ; edi = "sedikit lagi masuk " <<------------'
0x400a1c <main+110>: call 0x40fe30 <puts> ; puts("sedikit lagi masuk ");
Dari potongan kode disassembly di atas, bisa terlihat bahwa soal tersebut memeriksa jumlah parameter yang diberikan pada commandline. Jika jumlahnya adalah 3, maka password yang terdapat pada parameter ke-3 akan diperiksa menggunakan fungsi strcmp yang tidak terlihat jelas karena soal tersebut menggunakan static linking. Password yang dimasukkan sebagai parameter ke-3 pada commandline akan dibandingkan dengan string "_init_array". Jika hasilnya sama, maka akan ditampilkan pesan:
"Anda telah berhasil masuk, jika lewat bypass tidak tau passwordnya, kalau tau passwordnya itulah jawabannya"
Anda dapat melihat string-string tersebut menggunakan perintah seperti ini:
Ada beberapa jebakan pada soal tersebut. Misalnya, jika kita tidak memasukkan jumlah argumen yang tepat pada commandline, maka instruksi pada alamat 0x4009d0 akan dieksekusi dan kita akan tiba pada alamat 0x400a21. Dan pada alamat tersebut, kembali akan dilakukan pemeriksaan jumlah argumen pada commandline, yaitu pada kedua baris ini:
0x400a21 <main+115>: cmp DWORD PTR [rbp-0x14],0x2 ; periksa apakah argc == 2
0x400a25 <main+119>: jne 0x400a60 <main+178> ; jika tidak, maka lompat ke alamat 0x400a60
Jika argumen pada commandline yang Anda masukkan berjumlah 2, maka Anda akan terkena jebakan betmen ini:
Jebakan di atas adalah ilusi dan hanya akan menampilkan pesan yang seakan-akan memeriksa nomor keberuntungan, padahal tidak. Seperti yang bisa dilihat pada baris disassembly ini:
0x400a4c <main+158>: mov edi,0x4a1470 ; edi = "Memeriksa nomor keberuntungan anda ... "
0x400a51 <main+163>: call 0x40fe30 <puts> ; puts("Memeriksa nomor keberuntungan anda ... ");
0x400a56 <main+168>: mov edi,0x4a1498 ; edi = "Nilai yang anda masukkan salah "
0x400a5b <main+173>: call 0x40fe30 <puts> ; puts("Nilai yang anda masukkan salah ");
Jebakan berikutnya adalah, jika Anda tidak memasukkan parameter pada commandline. Anda akan tiba pada alamat 0x400a60. Pada alamat tersebut, akan dilakukan pemeriksaan jumlah parameter pada commandline, yaitu pada baris berikut ini:
0x400a60 <main+178>: cmp DWORD PTR [rbp-0x14],0x1 ; periksa apakah argc == 1 (tidak ada parameter)
0x400a64 <main+182>: jne 0x400a9f <main+241> ; jika tidak, maka lompat ke alamat 0x400a9f
Dan berikut ini adalah potongan kode dari jebakan betmen yang ke-2 tersebut:
Jebakan terakhir adalah pemeriksaan jika sama sekali tidak ada argumen pada aplikasi. Hal ini tidak akan terpenuhi, karena aplikasi/soal tersebut minimal memiliki satu argumen, yaitu nama aplikasi/soal tersebut, dalam hal ini "malemsabtuiseng". Jadi potongan kode berikut ini yang merupakan jebakan betmen, akan senantiasa mengeksekusi lompatan ke alamat 0x400ade jika Anda parameter pada commandline lebih dari 3:
Karena jebakan di atas tidak akan dieksekusi, maka jebakan betmen terakhir yang terdapat pada alamat 0x400ade hanya akan membuat aplikasi berhenti (exit).
Sebagai kesimpulan akhir. Soal tersebut memerlukan 3 parameter (termasuk nama aplikasi), dan parameter ke-3 adalah string "_init_array" seperti yang dapat dilihat pada gambar berikut ini:
Sekian tutorial ini, semoga bermanfaat. Terima kasih.