PICOCTF 2021 WRITEUP
Pada artikel CTF kali ini, kami akan membahas mengenai PICOCTF 2021 yang bisa kalian akses soalnya di https://picoctf.org/. Soal yang akan kami jelaskan adalah soal Reverse Engineering yang bernama Transformation dengan nilai 20 poin.
Attached file content:
enc :
灩捯䍔䙻ㄶ形楴獟楮獴㌴摟潦弸彥ㄴㅡて㝽 |
Analisa Soal
Diberikan sebuah text yang nampaknya sudah terenkripsi menggunakan code python yang telah diberikan. Kami mencoba untuk memodifikasi code tersebut agar lebih mudah dimengerti. Setelah dianalisa, code tersebut dapat kita rekonstruksi menjadi seperti ini:
def encrypted(flag): enc = “” for i in range(0, len(flag), 2): enc += chr((ord(flag[i]) << 8) + ord(flag[i + 1])) dec = ”.join(enc) print(dec) |
Alur code:
- Fungsi encrypted akan menerima string flag.
- Fungsi akan mengambil per 2 karakter. Dimana karakter pertama akan diubah ke bentuk desimal dan di-shift sebanyak 8 bit ke kiri. Kemudian hasilnya akan ditambahkan dengan nilai desimal karakter setelahnya. Jumlah nilai ini akan dijadikan karakter baru melalui fungsi chr().
- Proses ini dilakukan secara repetitif hingga seluruh karakter dari string flag terenkripsi.
*catatan: Karena fungsi mengambil per 2 karakter, maka total panjang hasil enkripsi akan berjumlah setengahnya dari string flag. Hal itu menandakan bahwa panjang flag pasti genap.
Solusi
Berarti yang harus kami lakukan adalah men-shift setiap karakter yang telah dienkripsi sebanyak 8 kali ke kanan. Dan beginilah scriptnya:
file = open(“enc”, “r”).read() shifted = “” for i in file: shifted += chr(ord(i) >> 8) print(shifted) |
Output:
pcCF1_isis3do__1107 |
Dari pola output yang kita temukan, mulai terbentuk format flag “picoCTF{”. Jika kita perhatikan, ada huruf-huruf yang hilang dari flag orisinil, yaitu setiap karakter di urutan genap. Jadi apabila digambarkan flag sesungguhnya akan berbentuk seperti di bawah ini:
p*c*C*F*1*_*i*s*i*s*3*d*o*_*_*1*1*0*7* |
Bagaimana cara mendapatkan karakter-karakter yang hilang tersebut? Sebelumnya kita ketahui bahwa karakter hasil enkripsi tersusun dari karakter yang sudah di-shift 8 kali dan dijumlahkan dengan nilai desimal karakter setelahnya. Sekarang coba kita bandingkan nilai desimal karakter-karakter hasil enkripsi dengan nilai desimal karakter output yang kita temukan, namun di-shift 8 ke kanan.
Decimal Karakter Hasil Enkripsi | Decimal 8 bit Shifted Output |
28777 | 28672 |
25455 | 25344 |
17236 | 17152 |
18043 | 17920 |
12598 | 12544 |
24418 | 24320 |
26996 | 26880 |
29535 | 29440 |
26990 | 26880 |
29556 | 29440 |
13108 | 13056 |
25695 | 25600 |
28518 | 28416 |
24376 | 24320 |
24421 | 24320 |
12596 | 12544 |
12641 | 12544 |
12390 | 12288 |
14205 | 14080 |
Jika dibandingkan, ada selisih antara hasil enkripsi dengan shifted output. Nilai selisih itu adalah nilai desimal dari karakter-karakter yang hilang. Mengapa? Karena pada proses enkripsi nilai yang ter-shift dijumlahkan dengan angka-angka ini. Jadi, yang perlu kita lakukan adalah mengubah nilai selisih tersebut menjadi bentuk karakter. Contohnya, selisih nilai pada karakter pertama adalah 105 atau “i” dalam bentuk desimal. Artinya, karakter flag yang kedua adalah “i”.
Untuk mempermudah, bisa kita gunakan kode seperti ini:
shifted2 = “” for j in range(len(file)): shifted2 += chr(ord(file[j])-(ord(shifted[j]) << 8)) print(shifted2) |
Output:
ioT{6bt_nt4_f8e4af} |
Dikarenakan kita sudah mendapatkan setiap karakter urutan genap. Kita dapat menggabungkan output hasil ganjil dengan output hasil genap. Berikut script lengkap yang digunakan:
file = open(“enc”, “r”).read() shifted = “” #pcCF1_isis3do__1107 for i in file: shifted += chr(ord(i) >> 8) shifted2 = “” #ioT{6bt_nt4_f8e4af} for j in range(len(file)): shifted2 += chr(ord(file[j])-(ord(shifted[j]) << 8)) for i in range(len(shifted)): print(shifted[i], end=“”) print(shifted2[i], end=“”) |
Output:
picoCTF{16_bits_inst34d_of_8_e141a0f7} |