Qual Cyber Jawara umum 2024 - N2L T1
(Cyber Jawara umum 2024 writeup)

It's time for a new empire
N2L – T1
Cyber Jawara Writeup
Player :
Goodfellow
Hazy
ud1n
MISC
[100 pts] Welcome!
Description : Welcome to Cyber Jawara Quals!
Flag format: CJ{[^{}]+}
Example: CJ{Welkom_bij_CJ_nationale_qual!!!}
Author :
Attachment :
POC : Makan ayam
– FLAG : CJ{Welkom_bij_CJ_nationale_qual!!!}
[250 pts] Pyrip
Description : Is this misc or pwn?
Note: Please contact @farisv if you have solved the challenge in local but cannot connet to remote
nc 159.89.193.103 9999
Author : farisv
Attachment : pyrip.zip
Diberikan sebuah binary file pyrip dengan source codenya.
#include <fcntl.h> |
Program tersebut akan menjalan sebuah python interpreter dimana dapat melakukan inputan python. Ketika programnya crash dengan address 0xc0ffeedecaf, maka program tersebut akan mengembalikan benderanya.
Setelah mencari saya menemukan artikel tentang injecting code ke running process python
[Injecting Code in Running Processes with Python and Ptrace · ancat
](https://ancat.github.io/python/2019/01/01/python-ptrace.html)Artikel ini menggunakan ctypes untuk menyelesaikan masalah ini. Karena saya kurang mengenal library yang ada pada ctypes, saya bertanya kepada GPT payloadnya.
Akhir saya menemukan payload ini, kurang lebih yang dilakukan mengeset address 0xc0ffeedecaf sebagai pointer ke sebuah fungsi yang kemudian akan dipanggil dengan (). Program ini akan crash karena alamatnya tidak valid dan mengembalikan benderanya.
import ctypes; ctypes.cast(0xc0ffeedecaf, ctypes.CFUNCTYPE(None))() |
– FLAG : CJ{=\*= Jump, pogo, pogo, pogo, pogo, pogo, pogo, pogo =*/=}
FORENSICS
[230 pts] Whale
Description : Someone broke into our application server. Could you help to investigate what they did?
Author : farisv
Attachment : https://drive.google.com/file/d/1du2MDOLldM3d_akDkIxypSStuaOSuDP6/view?usp=sharing
Diberikan sebuah file tar.gz yang isinya adalah folder yang biasa ada di linux
Lalu terdapat Dockerfile yang isinya mengarah kedua link pastebin yang memiliki 2 variabel ID1 dan dan ID2
Dari situ saya mencoba untuk mencari value dari variable tersebut dengan command ack dan mendapatkan "ID1=YJqeFMMv" dan "ID2=fUH6jy3d"
Link : https://pastebin.com/raw/fUH6jy3d
Link : https://pastebin.com/raw/YJqeFMMv
Pada link pertama teradapat sebuah code python flask, singkatnya web app ini pada endpoint /upload bisa mengupload file dengan format base64 yang nanti nya di enkripsi menggunakan AES dan juga menggunakan key nya.
Lalu saya mencari log berdasarkan penemuan saya tadi, lalu mendapatkan
Terdapat sebuah aktivitas yang mengupload ke folder /tmp/ dan juga beberapa file yang diuploadnya, di lognya juga terdapat key yang nantinya saya pakai untuk decrypt filenya.
Dan saya menemukan lokasi dari folder /tmp/ tersebut berada di whale/var/lib/docker/overlay2/473883c2dc201325561e7ad936c8aacc8aa3f6e6dac46911adc4479c0059fb77/merged/tmp
Kode Decryptor:
Hasil dari mendecrypt beberapa file
Lalu part 2 flagnya berada pada file “interesting”
– FLAG : CJ{dae071f96aadfb8c2417ed6715711cb9e36e6c1e}
[290 pts] Grayscale
Description : A threat actor hides a secret message on this intentionally-broken GIF.
Author : farisv
Attachment : grayscale.gif
Terdapat sebuah file gif yang rusak yang hampir setengah dari hex file nya hilang
Karena tidak menemukan tools untuk recover file gif, saya iseng mencoba menambahkan hex yang kosong dengan file gif random yang tidak rusak, lalu dapat
– FLAG : CJ{_s0_15_it_pr0nounc3d_GiF_or_JiF}
CRYPTOGRAPHY
[150 pts] Permutasi
Description : Saya mendapatkan pesan yang telah diacak dengan mengacak urutannya atau permutasi. Potongan pesan aslinya diketahui tapi saya perlu pesan yang utuh.
Author : farisv
Attachment : encrypt.py, pesan.txt, rahasia.txt
Berikut isi dari encrypt.py :
Encryption diatas digunakan untuk menyembunyikan pesan yang ada pada pesan.txt :
Untuk mendapatkan flag, kita perlu mendecrypt pesan utuhnya yang sudah diacak pada rahasia.txt
Dari sini, terdapat beberapa poin penting yang perlu diperhatikan :
- Kita sudah mengetahui sebagian isi dari pesan seluruhnya.
- k (atau kita akan sebut sebagai key) berisi 10 integer random dari 0-255
- key tersebut digunakan untuk mengacak pesan dengan “custom columnar transposition cipher”
Untuk menyelesaikan masalah tersebut, kami membuat program decryption sebagai berikut :
import itertools |
Ingat kembali poin-poin tadi, karena kita mengetahui keynya memiliki length 10 dan menggunakan permutasi, kita bisa bruteforce dengan function ‘itertools.permutations’. Beberapa bagian dari pesan utuhnya juga sudah diketahui, sehingga kita bisa menggunakan pesan yang sudah ada untuk konfirmasi apabila key yang didapatkan dari bruteforce sudah benar. Kemudian tunggu beberapa menit sampai bruteforce key selesai
– FLAG : CJ{Rahasia ini hanya milikmu sekarang, gunakan dengan bijak dan jangan sampai jatuh ke tangan yang salah}
REVERSE ENGINEERING
[170 pts] ASM Raw
Description : Pseudo-C decompilation makes us lazy. Analyze this ASM output from objdump.
Flag: CJ{%s} where %s is an accepted string
Author : farisv
Attachment : asm-raw.txt
Diberikan sebuah file .txt yang berisikan assembly code. Pada code itu, terdapat dua main function yaitu ‘check’ dan ‘main’.
00000000000011c9 <check>: |
Kita lakukan analisis pelan-pelan, check function bertujuan untuk memvalidasi input string. Function tersebut memiliki loop dari 0 to (strlen / 2) - 1 yang menandakan ini adalah palindrome check. Loop tersebut membandingkan char pada posisi i dengan char pada posisi (strlen - 1 - i). Jika ada char yang tidak sama, function melakukan return 0, yang menandakan failure. Tetapi jika charnya sama, function melakukan return 1, yang menandakan success.
Main function : Input dibacakan dengan scanf pada rbp-0x70 sebagai buffer untuk user input. Kemudian pada 12b6 dilakukan length checking yang akan return 1 apabila length dari string adalah 21, dan juga 0 apabila bukan 21. Dengan ini kita bisa menyimpulkan bahwa addreses rbp-0x70 hingga rbp 0x5c adalah memori yang dialokasikan untuk user input.
Berdasarkan kesimpulan diatas, kita sudah tau kalau inputnya harus palindrome dan memiliki length 21 yang berarti kita hanya perlu tau 11 char saja. Pada assembly tersebut terdapat hint juga yang menentukan char apa yang harus diletakkan pada posisi apa seperti contoh :
12db: movzx eax,BYTE PTR [rbp-0x70] Melakukan checking apabila rbp-0x70 adalah 0x61 |
Dari sini, kita sudah mengetahui kalau input untuk index [0,2,4,7,9] adalah a, dan demikian juga untuk [11,13,16,18,20]. Kita lanjut selidiki assembly tersebut untuk clue lainnya.
1356: movzx eax,BYTE PTR [rbp-0x5d] |
Input ascii 0x6d atau ‘m’ pada 0x5d (index 19). Progress string sejauh ini adalah [ama_a__a_a_a_a__a_ama].
137d: movzx eax,BYTE PTR [rbp-0x61] |
Input ascii 0x70 atau ‘p’ pada 0x61 (index 15). Progress string sejauh ini adalah [ama_ap_a_a_a_a_pa_ama].
1403: movzx eax,BYTE PTR [rbp-0x66] |
Input ascii 0x63 atau ‘c’ pada 0x66 (index 10). Progress string sejauh ini adalah [ama_ap_a_aca_a_pa_ama].
13a4: movzx eax,BYTE PTR [rbp-0x6a] |
Input ascii dari address rbp-0x6a (0x70) dikurang 4 menjadi (0x6c) atau ‘l’ pada 0x6b (index 5). Progress string sejauh ini adalah [ama_apla_aca_alpa_ama].
1322: movzx eax,BYTE PTR [rbp-0x6f] |
Bagian ini memasukkan value dari rbp-0x6f yaitu ‘m’ pada eax, kemudian edx = ‘m’ -1 lalu dilakukan persamaan antara edx dengan eax diakhir. Sehingga kita sudah dapat jawaban untuk address rbp-0x6d yaitu ‘n’. Progress string sejauh ini adalah [amanapla_aca_alpanama].
13d8: movzx edx,BYTE PTR [rbp-0x68] |
Kita sudah tau value dari edx adalah ‘n’, sehingga string requirement untuk flagnya sudah terpenuhi.
– FLAG : CJ{amanaplanacanalpanama}
BINARY EXPLOITATION
[360 pts] Give me file
Description : I want to get the flag file with a shellcode but the char is limited :(.
nc 159.89.193.103 10002
Author : farisv
Attachment : give-me-file.zip
Diberikan sebuah file binary runner dan sandbox.
Ketika di jalankan binary ./runner meminta sebuah shellcode.
Untuk binary sandbox meminta sebuah program untuk dijalankan di arg, jadi ketika di jalankan dengan binary runner akan menjalankan program tersebut dalam binarynya.
Selanjutnya analisa dari hasil decompile runner.
local_58 = 700; |
Di dalam binary runner akan menjalankan mmap, membuat bagian memori baru 700 bytes dengan izin RWX.
puts("Enter your shellcode in hexadecimal format (e.g., \x90\x90\x90) max 700 chars:"); |
Selanjutnya programnya akan mempersiap dan meminta bagian input shellcode. Di akhir input nya akan diubah menjadi \0 untuk menghindari operasi shellcode yang berbeda dengan di input.
local_68 = 0; |
Kemudian program ini membaca apakah mulai dengan \x, jika iya maka program tersebut akan mengkonversikannya menjadi sebuah byte dan meletakkan dalam memori yang dibuat.
(undefined8 )((long)puVar6 + lVar1 + -8) = 0x1014ae; |
Terakhir programnya menjalankan dan membersihkan shellcode yang telah ditulis dalam memorinya.
Pada program sandbox, difungsi run debugger terdapat restricted syscall.
DWORD syscallnumbers[20] = |
Program tersebut hanya memperboleh beberapa syscall.
Untuk mengeksploitasi program ini, dapat membuat sebuah shellcode dengan format \x yang akan mengeksekusi ORW (Open Read Write) untuk mendapatkan konten dari flag.txt.
Sekarang saya tinggal mengikuti format pemanggilan syscall tersebut.
xor rax, rax |
Sesuai dengan syscall table, pertama set rax 0 dengan cara xor sesama, lalu dorong ke dalam stack kemudian set rdi ke rsp yang akan kita gunakan nanti untuk buka file. Lalu set rsi ke 0, rax ke 2 lalu panggil syscall. Shellcode pertama akan membuka file dari stack pointer,
Untuk shellcode kedua set rdi ke rax dimana rax bernilai 2, set rsi ke rdi hasil dari open tadi, set rdx ke 1000 (berapa panjang konten dikeluarkan) lalu set rax ke 0 dan panggil syscall. Shellcode kedua akan membaca konten dari hasil open sebelumnya.
Terakhir shellcode ketiga set rdi ke 1 yang akan dituliskan ke stdout lalu set rax ke 1 untuk memanggil syscall write. Shellcode ketiga akan menampilkan konten yang dibaca.
Tetapi sebelum itu dapat dilihat dalam DockerFile bahwa server telah mengubah nama dari flag.txt menjadi /flagggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggg.txt
FROM ubuntu:24.04 |
Apakah hal ini dapat membuat shellcode inputan menjadi tidak cukup?
Tidak, hal ini dapat diselesaikan dengan memanggil push ulang ke dalam stack karena karakter yang digunakan berulang. Jadi saya akan menggunakan rbx sebagai tempat penampung sementara.
mov rbx, 0x7478742e6767 |
0x7478742e6767 gg.txt yang direverse dalam hex. Lalu di push ke stack, set rbx 0x6767676767676767 gggggggg yang direverse dalam hex yang kemudian dipush berulang kali hingga “g” mencapai 198. Terus set rbx ke 0x676767676767616c lagggggg dalam reverse lalu push ke stack. Terakhir set bx 2 bytes dari rbx ke 0x662f /f dalam hex reverse di push ke dalam stack. Sehingga hasil akhir dari solver berikut.
#!/usr/bin/env python3 |






