Reverse Engineering

Defeating the “Crying” Ransomware : Misc & Reversing CTF Writeup


Pada kesempatan ini, Author ingin membagikan Writeup tentang salah satu challenge pada kompetisi CTF Wreck IT 4.0 yang diselenggarakan oleh Politeknik Siber dan Sandi Negara. Soal yang diselesaikan berkategori Miscellaneous dan perlu sedikit pemahaman tentang Reverse Engineering.

Challenge Description & Attachment

Berikut adalah deskripsi dari challenge yang akan dibahas. Silakan download melalui link berikut.

Lakukan Koneksi ke Host Server

Setelah membaca deskripsi soal, Author memulai tantangan ini dengan melakukan remote secure shell connection dengan perintah berikut.


Namun, perintah tersebut tentunya akan memunculkan pesan permission denied. Dalam melakukan secure connection, server perlu memvalidasi user sebelum memberikan akses ke dalam server. Dengan memasukkan username dan password, server dapat memastikan bahwa user yg ingin masuk ke dalam server adalah orang yang diizinkan dalam mengakses server tersebut.


ssh <username>@<server-address> -p <port-number>


Untuk itu, kita perlu memenuhi ketentuan di atas. Bagaimana cara tahu username, atau bahkan passwordnya?

Pada attachment soal diberikan string aneh yang sebenarnya merupakan interpretasi dari bahasa pemrograman Brainfuck. Author hanya perlu mendecode string tersebut dan hasilnya adalah malbi:77U37dg261yyyo1

Author berasumsi bahwa hasil decode string Brainfuck tersebut merupakan kredensial yang diperlukan saat melakukan koneksi SSH. Lakukan koneksi dengan malbi dan password: 77U37dg261yyyo1


ssh [email protected] -p 35022
Menemukan File Binary Ransomware

Dengan memasukkan kredensial tersebut maka akan berhasil melakukan koneksi ke server. Biasanya flag disimpan dalam directory root. Namun setelah menelusuri tiap folder, Author mendapat flag pada path /opt.


Sayangnya, permission untuk flag.txt hanya dapat diread saja. Kita perlu jalan lain untuk membukanya. Pada deskripsi soal dituliskan Binary ransomwarenya bernama “crying”. Author mencari file tersebut dengan :

find / -name "crying"


Memang ada beberapa directory yang perlu hak akses root, tapi ternyata Author menemukan file itu di /usr/bin/crying. Saat dijalankan, program tersebut hanya menampilkan string “Sob” saja.

Mengunduh File Binary ke Local Machine

Author punya ide untuk menjalankannya melalui local machine agar setidaknya bisa dijalankan menggunakan decompiler atau debugger. Ada beberapa cara untuk mendownload file crying dari host ke local machine. Lagi-lagi, karena file ownernya adalah root, kita tidak akan bisa berbuat banyak. Kita perlu menemukan directory dimana user biasa bisa melakukan read, write, dan execute.


Copy file binary tadi dari /usr/bin/crying ke /tmp. Setelah di copy maka file ownernya akan berubah menjadi user saat ini. Sekarang, tujuannya adalah mendownload file ini ke local machine. Bisa make beberapa cara, seperti secure copy, python http server, ataupun sftp. Disini author menjalankan perintah SFTP dari terminal lokal untuk mendownload file dari server.


Melakukan Reverse Engineering

Lalu, apa yang harus dilakukan? setelah dapat filenya, kita akan lihat dekompilasi programnya. Bagi yang masih pemula dalam Reverse Engineering, dekompilasi yaitu proses untuk mengubah kode program yg sudah dikompilasi kembali menjadi source code asalnya. Biasanya file binary terdiri atas beberapa segmen, diantaranya :

  • .bss (Block Started by Symbol): Segmen ini berisi variabel yang diinisialisasi dengan nilai 0, atau belum diinisialisasi dengan suatu nilai.
  • .got (Global Offset Table): Segmen ini berisi alamat untuk fungsi dan variabel global yang digunakan dalam program.
  • .rodata (Read-Only Data): Berisi data yang bersifat statis dan hanya dapat dibaca. Data pada segmen ini tidak dapat diubah selama runtime.
  • .data (Initialized Data): Berisi variabel yang diinisialisasi dengan nilai tertentu. Variabel pada segmen ini dapat diubah selama runtime.
  • .text (Code): berisi kode bahasa pemrograman yang terdiri atas logika utama dan alur kontrol dari program.

Author menggunakan Ghidra dan Radare2 untuk melakukan dekompilasi dan membaca alur program. Berdasarkan penjelasan di atas, kita bisa mulai bermain pada segmen .text karena merupakan bagian utama dari suatu program.

Membaca Alur Kode dan Block Program

Kita mulai dengan menganalisis address memori 0x402540 karena address ini adalah entry point, atau main programnya. Intinya, fungsi pada address ini akan memanggil fungsi di address lain, yaitu 0x403df0.


Lakukan dekompilasi fungsi pada rentang address 0x403000 sampai 0x403fff. Dari sini kita mendapat kata kunci yang penting untuk dicatat. Pada address 0x403e6d terdapat str._MEIPASS yang merupakan variabel yang digunakan oleh PyInstaller untuk mengakses file-file yang telah disertakan dalam sebuah program yang dibungkus ke dalam sebuah executable. Lihat gambar berikut.


Berdasarkan gambar di atas juga terdapat PYI_ONEDIR_MODE yang digunakan PyInstaller untuk membuat direktori tunggal yang berisi semua file yang diperlukan oleh program.

Kemudian setelah lama mengeksplorasi alur program, terdapat fungsi pada address 0x00405fb0 yang memanggil 0x00407280. Jika ditampilkan dengan Function Graph pada Ghidra, maka berikut adalah tampilannya.



Pada 2 gambar di atas, terdapat kata kunci lagi yaitu PYINSTALLER_STRICT_UNPACK_MODE yang bertujuan untuk membundle program ke dalam sebuah executable.

Decompiling File Binary Ransomware

Oke, berdasarkan banyak keyword yang sudah kita dapat diatas, bisa disimpulkan bahwa semua nya akan mengerucut ke PyInstaller. Author punya ide untuk mengekstrak konten yang ada di file crying kembali ke bentuk semula (sebelum dibundle dengan PyInstaller). Untungnya ada repository github yang bisa melakukan hal ini (thanks to extremecoders).

Setelah diextract menggunakan tools github tersebut, akan muncul konten file dari binary crying tadi. Dari sekian banyak file yg muncul, ada file yang namanya sama dengan file binary sebelum diextract, yaitu crying.pyc.



Dapat dilihat bahwa file ini di compile dengan python versi 3.8. File ekstensi .pyc tidak bisa dibaca langsung oleh IDE atau editor apapun karena berisi bytecode yang dihasilkan oleh interpreter Python. Oleh karena itu kita perlu Python decompiler untuk mengembalikan kode tersebut ke bentuk aslinya. Untuk itu kita bisa menggunakan uncompyle6.


Wow, akhirnya kita menemukan Big Clue dari challenge ini. Berdasarkan logika pada kode tersebut, flag akan muncul jika domain Pada gambar di atas bisa diakses oleh mesin host. Mari kita buat koneksi ulang seperti semula.

ssh [email protected] -p 35022
Menemukan Flag pada Host Machine

Agar domain bisa diakses oleh mesin, pindah ke directory /etc. Disana kita perlu mengedit nilai dari file bernama hosts. File /etc/hosts berguna untuk menentukan alamat IP dari sebuah host ketika kita ingin terhubung ke host tersebut. Isi dari file /etc/hosts biasanya terdiri dari dua kolom yang dipisahkan oleh spasi atau tab. Kolom pertama berisi alamat IP dari host, sedangkan kolom kedua berisi nama host

Langkah terakhir.. kita hanya perlu menambahkan IP Address dari web apapun yang bisa diakses secara publik ke hosts. Untungnya hosts bersifat writable dan bukan dimiliki root sehingga kita bisa menulis sesuatu disitu.

echo "XX.XX.XX.XX yieywvciwyefiowuteyrt63257486gdfewytifuywewhfg.co.ph" > hosts


Dalam hal ini, isi dari file /etc/hosts akan berisi mapping antara alamat IP "XX.XX.XX.XX" dengan nama domain seperti yang ada di hasil dekompilasi. Mapping ini digunakan untuk menentukan alamat IP dari sebuah host ketika sebuah aplikasi ingin terhubung ke host tersebut, sehingga jika kita menjalankan file crying pada host machine kita akan mendapat flag.


Flag : WRECKIT40{R34l_c453_0f_w4NN4cRY}