Sunday, March 1, 2015

Boston Key Party 2015: Sullivan Square

 

Soal ini termasuk soal sulit dlam kategori reversing dengan nilai 350. Soalnya:

sullivan-square

ternyata kita diberi file dengan ekstensi rbc dan satu file dengan ekstensi dump. Setelah membaca-baca, ternyata rbc adalah file hasil kompilasi ruby dengan rubinius. Di soal disebutkan versinya adalah 2.5.2. Langkah pertama adalah menginstall dulu rubinius dengan mengcompile dari source codenya.

Pengetahuan Ruby saya sangat terbatas, jadi sebagian besar adalah dengan coba-coba saja plus logika sederhana.

Tapi sayangnya ketika dijalankan, hasilnya:

./run.sh
An exception occurred evaluating command line code:

/home/yohanes/trie/trie_harder.rbc (Rubinius::InvalidRBC)

Backtrace:

      Rubinius::CodeLoader#load_compiled_file at kernel/delta/code_loader.rb:227
               Rubinius::CodeLoader#load_file at kernel/delta/code_loader.rb:175

 

Saya tidak berhasil mencari tahu kenapa itu terjadi. Jadi terpaksa membaca sourcenya rubinius, ternyata masalahnya adalah kode versi dalam file RBC.

Di file yang didownload, headernya seperti ini:

!RBIX
10184465365783055646

Setelah saya compile program hello world, ternyata headernya:

!RBIX
17720602882280116705

Dengan mengganti 10184465365783055646 menjadi 17720602882280116705, hasilnya program bisa dijalankan:

sullivan-square2

Tampaknya tanpa source codenya, akan sulit menyelesaikan ini. Setelah mencoba-coba debuggernya rbx ( rbx -Xdebug -I.), ternyata ini pun sulit. Tapi saya mendapatkan beberapa info berharga. Saya tidak tahu di mana titik main eksekusi untuk breakpoint, jadi saya break saja di Object#puts

Ketika sampai main, saya lakukan “dis all”, dan hasilnya:

sullivan-square3

Seperti yang saya nyatakan sebelumnya: saya tidak terlalu mengerti Ruby, apalagi bytecodenya. Tapi karena sudah mengerti bytecode berbagai bahasa lain, saya bisa menebak bahwa kodenya kira-kira:

a = Marshal.load(File.read('trie.dump'))

Saya mencoba-coba mendump kelas trie, seperti ini:

Rubinius::CodeLoader.require_compiled 'trie'

a = Marshal.load(File.read('trie.dump'))

puts a.methods - Object.methods
puts "--"
puts a.private_methods  - Module.private_methods

puts a.instance_variables

Ternyata kelas Trie ini cuma punya instance variable @root yang tipenya Trie.Node, kelas Trie.Node ini memiliki 6 instance variable:

[:@end, :@left, :@value, :@right, :@char, :@mid]

Karena jarang memakai struktur data Trie, saya baca lagi di wikipedia:

https://en.wikipedia.org/wiki/Trie

Berdasarkan deskripsinya, left, right, mid,end sudah jelas. Lalu value dan char bisa kita print saja. Setelah saya dump Trie-nya, hasilnya adalah teks yang tidak terbaca di bagian char, dan teks yang terbaca di bagian value, misalnya:

- “not the flag but a true statement ;)”

- “wow not this either”

- “nope lots of fake flags”

- “stop being such a n00b and get the flag”

- “1 c4n r34d th15 ju57 l1k3 x86 0r 3n6L15h!”

Tapi itu semua bukan flag. Saya lihat ada kelas cipher, tapi bagaimana cara kerjanya? membaca bytecodenya bisa pusing, jadi saya akali, pertama saya coba instansiasi langsung:

Cipher.new

Tapi:

method 'initialize': given 0, expected 1 (ArgumentError)

Berarti kelas ini perlu sebuah parameter, tapi saya tidak tahu apa. Jadi saya buatkan sebuah kelas pengganti Cipher:

rbx compile cipher.rb –o cipher.rbc

./run.sh

Hasilnya:

 

So, you can tell me now... what's the flag? 1
["K", "D", "w", "X", "H", "3", "e", "1", "S", "B", "g", "a", "y", "v", "I", "6", "u", "W", "C", "0", "9", "b", "z", "T", "A", "q", "U", "4", "O", "o", "E", "N", "r", "n", "m", "d", "k", "x", "P", "t", "R", "s", "J", "L", "f", "h", "Z", "j", "Y", "5", "7", "l", "p", "c", "2", "8", "M", "V", "G", "i", " ", "Q", "F"]An exception occurred evaluating command line code:

undefined method `encrypt' on an instance of Cipher. (NoMethodError)

Ternyata Cipher perlu dipanggil menggunakan tabel sebagai inputnya. Setelah dicoba, ada method decrypt, jadi ini saya pakai untuk mendump isi Trie.

Hasil dump yang menarik adalah:

N = WyXcXAFAp9F0Wc8FDHcveFypMWF288i
rmd1dy y0u tr13 be1ng m04r 2337

Saya tidak sempat mempelajari kenapa ada huruf “rm” dan “y” (stelah d1d), sepertinya itu adalah marker (mungkin “right”,”middle”) dan indikator (“yes”). Tapi dari tebakan saya, flagnya adalah: d1d y0u tr13 be1ng m04r 2337

Dan ternyata setelah dicoba di command line benar.

Source solusi (sorry jelek banget kodenya, ga pernah coding ruby in real life):

2 comments: