# Write Up Capture The Flag Hology 8.0 TelSec - Peserta ![image](https://hackmd.io/_uploads/H1K8-_v3ee.png) --- Category <a href="#misc"> misc </a> * <a href="#25"> Free Flag </a> <a href="#web"> web </a> * <a href="#21"> pyjail? </a> <a href="#rev"> rev </a> * <a href="#23"> ObligatoryFlagCheckerThatIsPacked </a> * <a href="#24"> Hidden Factory </a> * <a href="#10"> Bit Buffet </a> <a href="#crypto"> crypto </a> * <a href="#15"> The Architect’s Hasty Encryption </a> <a href="#foren"> foren </a> * <a href="#17"> Paranoid Archivist </a> ## <a id=misc> misc </a> ### <center><a id="25"> Free Flag </a></center> <center>50</center> <center>Give us critique and you'll get a free flag. https://forms.gle/tUUTVkiBm5VzacSNA Author: Current HOLOGY CTF Probset</center> **Flag : ** --- ## <a id=web> web </a> ### <center><a id="21"> pyjail? </a></center> <center>100</center> <center>I hope I patched all the unintended ways... Author: avocado</center> ![image](https://hackmd.io/_uploads/Hkt_WOP2xx.png) SANITY CHECK INI MAH WKWK **Flag : HOLOGY8{h0l1_m0l1_r3g3x_g07_pwn3d??_51ff8a6c}** --- ## <a id=rev> rev </a> ### <center><a id="23"> ObligatoryFlagCheckerThatIsPacked </a></center> <center>100</center> <center>Title should suffice. Author: OFF5E7</center> #### Ringkasan Challenge - Binary: `packed_rev` (ELF 64-bit, statically linked) - Gejala: Saat dijalankan meminta flag lewat STDIN, output “THATS NOT RIGHT” jika salah. - Petunjuk: “Title should suffice.” → indikasi binary dipack. #### 1) Deteksi Packing - Cek header dan strings cepat: - `xxd` menunjukkan signature `UPX!` → UPX-packed. - `file packed_rev` menampilkan “statically linked, no section header” → ciri packed. #### 2) Unpack Biner Gunakan UPX untuk meng-unpack: ```bash upx -d -o /tmp/packed_rev.unpacked packed_rev file /tmp/packed_rev.unpacked ``` Hasil: ELF 64-bit, BuildID terlihat, tidak di-strip (lebih mudah dianalisis). #### 3) String Menarik & .rodata Cari strings pada biner hasil unpack: ```bash rg -n -a "easy_key|WHATS THE FLAG|THATS NOT RIGHT|YAY YOU GOT IT RIGHT" /tmp/packed_rev.unpacked ``` Dan dump .rodata di alamat terkait: ```bash objdump -s --start-address=0x47a000 --stop-address=0x47a0d0 /tmp/packed_rev.unpacked ``` Potongan penting: - `0x47a050`: `easy_key` (kunci XOR berulang 8 byte) - `0x47a010 .. 0x47a02f`: `partA` (30 byte) - `0x47a030 .. 0x47a04f`: `partB` (30 byte) - Pesan: “WHATS THE FLAG, SEARGEANT.”, “THATS NOT RIGHT”, “YAY YOU GOT IT RIGHT” #### 4) Analisis Disassembly Disassembly fungsi `main` (ringkas): - Cetak prompt dan baca input hingga 0x100 byte. - Set `len = 0x1e (30)` dan tolak jika panjang tidak sesuai. - Bangun array target `T[i]` dari dua konstanta di .rodata: - `T[i] = partA[i] XOR rol8(partB[i], 3)` - Ambil key 8-byte `key = "easy_key"` dan validasi: - `if ( (input[i] XOR key[i%8]) != T[i] )` → salah. - Jika semua cocok → benar. Terlihat jelas ada fungsi `rol8` dan loop pembentukan target, lalu loop verifikasi terhadap input yang di-XOR dengan key. #### 5) Rekonstruksi Flag Karena `input[i] XOR key[i%8] == T[i]`, maka `input[i] = T[i] XOR key[i%8]`. Ekstrak bytes `partA`, `partB`, dan hitung flag: ```python import subprocess, re def parse_line(line): m = re.match(r"\s*([0-9a-fA-F]{6,})\s((?:[0-9a-fA-F]{8}\s){3}[0-9a-fA-F]{8})", line) if not m: return None hexgroups = m.group(2).strip().split() bs = bytearray() for g in hexgroups: for i in range(0,8,2): bs.append(int(g[i:i+2],16)) return bytes(bs) def get_bytes(start, stop): out = subprocess.check_output(['objdump','-s',f'--start-address={start}',f'--stop-address={stop}','/tmp/packed_rev.unpacked']).decode() bs = bytearray() for line in out.splitlines(): part = parse_line(line) if part: bs.extend(part) return bytes(bs) partA = get_bytes('0x47a010','0x47a030')[:30] partB = get_bytes('0x47a030','0x47a050')[:30] key = b'easy_key' rol8 = lambda x,n: ((x<<n)|(x>>(8-n))) & 0xff T = bytes([a ^ rol8(b,3) for a,b in zip(partA, partB)]) flag = bytes([T[i] ^ key[i%len(key)] for i in range(len(T))]) print(flag.decode()) ``` Output: ![image](https://hackmd.io/_uploads/BJ-5b_D3le.png) **Flag : HOLOGY8{n33d3d_4_4_r3v_p4ck3r}** --- ### <center><a id="24"> Hidden Factory </a></center> <center>100</center> <center> Welcome to the "Hidden Factory"! A secretive manufacturing facility has protected their critical blueprints using an intricate multi-layer encryption system. The factory's security engineers have implemented a sophisticated data transformation pipeline that processes sensitive information through multiple encoding chambers. Can you unravel their encryption methodology and extract the original blueprint? The solution requires dissecting their security architecture, reversing each protective layer, and recovering the authentic manufacturing documentation. </center> <center>author: Lorem</center> <center>`nc ctf.hology.id 1000`</center> --- #### Ciphertext (dari `hasil nc ctf.hology.id 1000`): Ciphertext (dari `hasil nc ctf.hology.id 1000`): ``` Sd9CG5TC4Xrz6ISW830mryN0qzBXwV/lyRt+cA2ifxAxXJPRAbLYR65qQWzv1HrKAJb1CBEwt+F8tvNnYfsBdAoQifQnjNi/GLHB ``` #### Analisis Biner (chall.c) Dari `chall.c` (yang dihasilkan dari `chall.pyx`) terlihat kelas `HiddenFactory` dengan tiga tahap transformasi sebelum output akhir dicetak: 1) _stage1_transform (Caesar shift pada alfabet kustom) - Alfabet: `ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789{}_` (panjang 65) - Operasi: untuk setiap char `c` yang ada di alfabet, - `old = alphabet.index(c)` - `new = (old + magic_offset) % len(alphabet)` dengan `magic_offset = 23` - gantikan `c` dengan `alphabet[new]` - Karakter di luar alfabet dibiarkan utuh. 2) _stage2_scramble (XOR posisi) - Untuk setiap indeks `i` dan char `c` hasil tahap 1, hitung `val = (i * secret_multiplier + magic_offset) % 256` dengan `secret_multiplier = 7` dan `magic_offset = 23`. - Keluarkan `chr(ord(c) ^ val)`. 3) _stage3_encode (Base64 + substitusi alfabet) - Konversi string hasil tahap 2 ke bytes Latin‑1. - Base64 standar terhadap bytes → string `encoded`. - Substitusi alfabet Base64 standar ke alfabet kustom: - Standar: `ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/` - Kustom: `0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz+/` - Setiap karakter Base64 standar pada posisi `i` dipetakan menjadi karakter alfabet kustom pada posisi `i` yang sama. Output akhir yang dicetak service adalah hasil tahap 3. #### Strategi Dekripsi (membalik tahap) Urutan balik dari output tahap 3 ke plaintext: 1) Balik tahap 3 (Base64 + substitusi alfabet) - Peta balik tiap char `c` di ciphertext dari alfabet kustom → indeks → ambil char pada indeks sama dari alfabet Base64 standar. - Lakukan Base64 decode → dapatkan bytes, decode `latin-1` → string tahap 2. 2) Balik tahap 2 (XOR posisi) - Operasi XOR adalah involutif (membalik dengan operasi yang sama). - Untuk setiap indeks `i` dan char `c` dari string tahap 2: `val = (i*7 + 23) % 256` lalu `c_rev = chr(ord(c) ^ val)` → string tahap 1. 3) Balik tahap 1 (Caesar shift) - Lakukan pergeseran mundur sebesar 23 pada alfabet `A‑Za‑z0‑9{}_` (panjang 65): - Jika `c` ada di alfabet: `new = (alphabet.index(c) - 23) % 65`, ambil `alphabet[new]`. - Selain itu: biarkan apa adanya. #### Solver Kode Python berikut menerapkan seluruh pembalikan: ```python import base64 enc = "Sd9CG5TC4Xrz6ISW830mryN0qzBXwV/lyRt+cA2ifxAxXJPRAbLYR65qQWzv1HrKAJb1CBEwt+F8tvNnYfsBdAoQifQnjNi/GLHB" # Tahap 3 (balik substitusi alfabet Base64 kustom → standar, lalu base64-decode) standard = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/" custom = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz+/" mapped = ''.join(standard[custom.index(c)] if c in custom else c for c in enc) s2_bytes = base64.b64decode(mapped) s2 = s2_bytes.decode('latin-1') # Tahap 2 (balik XOR posisi — pakai operasi yang sama) secret_multiplier = 7 magic_offset = 23 s1_chars = [] for i, ch in enumerate(s2): val = (i*secret_multiplier + magic_offset) % 256 s1_chars.append(chr(ord(ch) ^ val)) s1 = ''.join(s1_chars) # Tahap 1 (balik Caesar shift −23 pada alfabet kustom) alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789{}_" L = len(alphabet) plain = [] for ch in s1: if ch in alphabet: old = alphabet.index(ch) new = (old - 23) % L plain.append(alphabet[new]) else: plain.append(ch) print(''.join(plain)) ``` **Flag : HOLOGY8{f4ct0ry_r3v3rs3_3ng1n33r1ng_m4st3r_0f_th3_h1dd3n_bluepr1nt_cr4ck3r}** --- ### <center><a id="10"> Bit Buffet </a></center> <center>499</center> <center>gurt : yo pc, run this rq pc : (consumes bits) Author: avocado</center> #### Deskripsi Singkat Diberikan satu berkas `FLAG.bin` yang berisi deretan bit “0/1”. Jika didekode per 8‑bit, hasilnya adalah kode mesin x86‑64 (flat binary, bukan ELF). Kode tersebut menyalin sebuah tabel pointer fungsi lalu memanggil setiap entri. Sejumlah fungsi “leaf” masing‑masing mengembalikan satu karakter (melalui `mov eax,<imm8>; pop rbx; ret`). Dengan merekonstruksi urutan pemanggilan berdasarkan tabel pointer, kita bisa merangkai seluruh karakter menjadi flag. --- #### Berkas - `FLAG.bin` — ASCII bitstring (satu baris sangat panjang) - Panjang bit: 163,712 bit → 20,464 byte - SHA256: `a1083f6e2546689173047e6f881232165d2d92225f7820d086d5f2da3a65a5cd` #### Recon Cepat - `file FLAG.bin` menunjukkan “ASCII text … with no line terminators”. - Dikonversi per 8‑bit → bytes → terlihat pola x86‑64: - Banyak instruksi `f3 0f 1e fa` (ENDBR64), setup stack, loop, dsb. - Bukan ELF; ini semacam “.text” flat dengan data di ekor file. #### Inti Analisis 1. Decode bit → byte, lalu disassembly sebagai x86‑64 “binary”: - Gunakan `objdump -b binary -m i386:x86-64 -M intel --adjust-vma=0x401000`. - Terlihat routine yang: - Menyalin array fungsi dari `0x406020` ke stack (`rep movs`), - Lalu melakukan loop: `call [rbx]`, `rbx += 8`, sampai `rbx == rbp`. 2. Cari fungsi “leaf” yang meng-encode karakter flag: - Pola epilog: `mov eax,<imm8>; pop rbx; ret`. - Masing‑masing `imm8` adalah ASCII 1 karakter. - Jika hanya dibaca “urutan kemunculan di file”, string yang didapat tampak acak karena urutan pemanggilan ditentukan oleh tabel pointer, bukan urutan layout di file. 3. Tabel pointer fungsi: - Dekat ekor file terdapat qword‑qword alamat fungsi (little‑endian). - Contoh hexdump (offset sekitar `0x4eb0`): ``` a03a400000000000 -> 0x403aa0 1028400000000000 -> 0x402810 804b400000000000 -> 0x404b80 8015400000000000 -> 0x401580 b024400000000000 -> 0x4024b0 ... ``` - Itulah urutan panggilan fungsi “leaf”; setiap entri memetakan ke fungsi yang mengembalikan satu byte ASCII. 4. Rangkai karakter sesuai urutan tabel: - Mapping alamat fungsi → dekatnya epilog `mov eax,<imm8>; pop rbx; ret`. - Hasil penyusunan karakter berdasarkan tabel menghasilkan flag yang valid. #### Langkah Reproduksi ##### 1) Konversi bitstring → bytes ```bash # Decode dari bitstring setiap 8-bit ke byte python3 - << 'PY' bits = open('FLAG.bin','rt').read().strip() bs = bytes(int(bits[i:i+8], 2) for i in range(0, len(bits), 8)) open('blob.bin','wb').write(bs) print('wrote', len(bs), 'bytes') PY ``` Opsional: intip tipe/hex: ```bash file blob.bin hexdump -C blob.bin | head ``` ##### 2) Disassembly cepat (opsional, untuk verifikasi) ```bash objdump -b binary -m i386:x86-64 -D -M intel --adjust-vma=0x401000 blob.bin | sed -n '1,220p' ``` Perhatikan di sekitar `0x4010a0` ada `rep movs` yang menyalin tabel fungsi dan loop `call [rbx]`. ##### 3) Ekstrak flag dari tabel pointer Script Python yang: - Mencari semua fungsi “leaf” dengan pola `B8 ?? 00 00 00 5B C3` (mov eax, imm8; pop rbx; ret), - Membaca qword tabel pointer (di ekor file), - Memetakan tiap alamat ke fungsi “leaf” terdekat, - Menyusun karakter sesuai urutan tabel. ```python import struct from pathlib import Path bs = Path('blob.bin').read_bytes() base = 0x401000 # 1) Kumpulkan lokasi fungsi return 1-char: B8 imm8 00 00 00 5B C3 ret_sites = [] for i in range(len(bs) - 7): if bs[i] == 0xB8 and i + 6 < len(bs) and bs[i+5] == 0x5B and bs[i+6] == 0xC3: ret_sites.append(i) # 2) Baca qword table dekat ekor (heuristik: mulai 0x4eb0) entries = [] for i in range(0x4eb0, len(bs) - 8, 8): q = struct.unpack('<Q', bs[i:i+8])[0] if q != 0: entries.append((i, q)) # (file_offset, vma) # 3) Untuk tiap alamat di tabel, cari fungsi 'leaf' terdekat sesudahnya def char_from_addr(addr): off = addr - base for j in ret_sites: if 0 <= j - off <= 0x300: return chr(bs[j+1]) # imm8 return None flag_chars = [] for off, addr in entries: c = char_from_addr(addr) if c: flag_chars.append((off, addr, c)) flag_chars.sort() # urutkan sesuai urutan di tabel flag = ''.join(c for _,_,c in flag_chars) print('Recovered:', flag) ``` ![image](https://hackmd.io/_uploads/Hy1nWdv2xe.png) **Flag : HOLOGY8{Wh0_4t3_a11_mY_b1t5_a3f9c8b2}** --- ## <a id=crypto> crypto </a> ### <center><a id="15"> The Architect’s Hasty Encryption </a></center> <center>200</center> <center>An emergency ping from the System crackles through your interface. The Architect’s module spins up, whispering of keys tempered in unstable instant magic and relics humming with old power. The gate won’t open itself. Plug in, look around, and figure out what the System wants from you. `nc ctf.hology.id 31337` Author: R1v3r</center> --- #### Bahan dari server (nc ctf.hology.id 31337) ##### Mission ``` n = 1189752…56133103109 e = 7872299…6277646485925 c = 1489592…534759588584 ``` ##### Artefacts ``` ART-A: nA = 8960178…7435739883181 eA = 65537 cA = 3716410…268954488372 ART-B: nB = 7149376…041023108447 eB = 65537 cB = 7043932…781336498428 ``` --- #### Langkah Teknis ##### 1) Artefacts: shared prime via `gcd` Hitung `g = gcd(nA, nB)` → ketemu **prime bersama p** berukuran **512-bit**. Faktorkan: * `p = g` * `qA = nA / p`, `qB = nB / p` * `φA = (p-1)(qA-1)`, `φB = (p-1)(qB-1)` * `dA = eA^-1 mod φA`, `dB = eB^-1 mod φB` * Dekripsi: `mA = cA^dA mod nA` → **“This path is flawed.”** `mB = cB^dB mod nB` → **“The artefact is void.”** → jelas ini **decoy**, tapi kita simpan nilai `g`. ##### 2) Mission: Wiener’s attack (small-d) Jalankan **Wiener** pada `(n, e)` Mission → dapat `d`. Dekripsi: `m = c^d mod n` → bytes ke string: ``` "SYSTEM-KEY:Arise.Now!" ``` ##### 3) Unlock Prompt “Key Entry” minta **HEX** dari plaintext penuh (termasuk prefiks). ASCII → HEX: ``` SYSTEM-KEY:Arise.Now! -> 53 59 53 54 45 4D 2D 4B 45 59 3A 41 72 69 73 65 2E 4E 6F 77 21 HEX: 53595354454D2D4B45593A41726973652E4E6F7721 ``` Masukkan itu untuk membuka sistem. ##### 4) Susun Flag (“gabungkan” + “trim its echo”) ![image](https://hackmd.io/_uploads/r1FpWODhxg.png) Instruksi author: hex yang dipakai untuk Unlock **digabung** dengan nilai dari Art A & B (yakni `g`), lalu dihitung **token** (SHA-256 full hex). Versi yang benar di sini adalah: * **gabung sebagai bytes**: `payload = b"SYSTEM-KEY:Arise.Now!" + str(g).encode()` ← `str(g)` = **ASCII desimal** dari `g` * **flag = sha256(payload).hexdigest()** Hasilnya cocok dengan flag yang valid: ``` 7ec2c6c4821ffe2bd9fa2045ef69791a22e595425e2948844e9b1fd3b37d54ca ``` --- #### Skrip Solver ```python import math, hashlib # ==== paste angka dari server ==== nA = int("89601783146076639326364551407391502056271453443585246403649518438739752197494453923912974590899704931799581808032848316945260608111602748641703034997071964641315226587094382131797946753938962375613837592569299860517918221636743443778609978573146453307287583692315622846949125803253541040690934297435739883181") eA = 65537 cA = int("37164104401076955077929653377412649499999712575049262615292256531432516530571888616103801152199060505086659571068915973058637089017531878490869019675349634664132877152506966368040680398438581696665793537909931060790220071739813385689555564918515689872228674428349534724902336052648318438921439321268954488372") nB = int("71493767682388193849018589142479453283796995156288303116503481698801388306223320772707598662122426469246149798256468802035651070345590713963988243090267155746488347787303474889624656335696596744993627750777136008351227588332875099728429462600325768652684066344324632574166525422011238099309853433041023108447") eB = 65537 cB = int("70439328908161407341748425421351243758222210153608544322212776759779840716935385163189188990383591871234782470265831205164904425451219055808713980664935582721819455648294588980175137551394128412355820943736415438043996050633633784118117657930546568264457192232822394652221065226217230553865130964781336498428") n = int("118975278847882844478683131487868863553725152941956385376607379430849467048838708654069858644026954641749865240483330886219744793766833535926332100442592236221964464629086823731578384477967425988583085618036341173204020994858998976972451248939014925597663289020083223001589858821506863031665806280615633043109") e = int("78722994310795625787105874655414923877307070249189124463403140397655605380213935536641528349788466972195773144530181458717471436560300040208738019374063797133171592591063777462750908244973898762467133495510521814795449800707766962786128955094379100191369241506884856300121048756989959313055477346277646485925") c = int("1489592032962799350792622713559294238291304015341650628646017299080863217451013943513044691837221873369753719076665779904675468457738769104175316344931340145854665918203359431685266438359786079681976203346113217786542373724335126764982653802084157053665772223172341072257906623599220597555287161534759588584") # ================================= # helper def i2b(x): return x.to_bytes((x.bit_length()+7)//8, "big") # 1) shared prime g = math.gcd(nA, nB) # (opsional) verifikasi decoy phiA = (g-1) * (nA//g - 1) phiB = (g-1) * (nB//g - 1) dA = pow(eA, -1, phiA) dB = pow(eB, -1, phiB) mA = i2b(pow(cA, dA, nA)) # b'This path is flawed.' mB = i2b(pow(cB, dB, nB)) # b'The artefact is void.' # 2) Wiener's attack (ringkas) import math def cont_frac(n, d): out = [] while d: a = n // d out.append(a) n, d = d, n - a*d return out def convs(cf): h1, h2 = 1, 0 k1, k2 = 0, 1 for a in cf: h = a*h1 + h2 k = a*k1 + k2 yield h, k h2, h1 = h1, h k2, k1 = k1, k def wiener(e, n): for h, k in convs(cont_frac(e, n)): if h == 0 or k == 0: continue if (e*k - 1) % h != 0: continue phi = (e*k - 1)//h s = n - phi + 1 disc = s*s - 4*n if disc < 0: continue t = math.isqrt(disc) if t*t != disc: continue p = (s + t)//2 q = (s - t)//2 if p*q == n: return k # d return None d = wiener(e, n) plaintext = i2b(pow(c, d, n)) # b'SYSTEM-KEY:Arise.Now!' # 3) flag: concat bytes + ascii decimal(g), sha256 payload = b"SYSTEM-KEY:Arise.Now!" + str(g).encode() flag = hashlib.sha256(payload).hexdigest() print("HOLOGY8{" + flag + "}") ``` Output: ![image](https://hackmd.io/_uploads/rJMyf_v3lx.png) --- **Flag : HOLOGY8{7ec2c6c4821ffe2bd9fa2045ef69791a22e595425e2948844e9b1fd3b37d54ca}** --- ## <a id=foren> foren </a> ### <center><a id="17"> Paranoid Archivist </a></center> <center>323</center> <center>this guy uses way too much passwords, i also heard he likes using edge for some reason (no bruteforce needed) https://drive.google.com/file/d/1K0ilDreURzWnPkYb7wmgvc0OKO5s7WLE/view?usp=sharing password: 9xD4Lo72HWE12XcFBZ7m Author: avocado</center> Diberikan sebuah file .ad1, yang berisi folder dari C:\Users\. Melihat dari deskripsi challenge, ini ada sesuatu yang berhubungan dengan Browser Edge. #### 1. Mount file ad1 Menggunakan tools AD1-Tools, kita dapat menggunakan ad1mount untuk membuka file tersebut dari situ, saya menemukan beberapa file menarik: - `AppData/Local/Microsoft/Edge/User Data/Default/History` (History Edge) - `/home/bbayugt/Downloads/AD1-tools/AD1Tools/out/Documents/flag.docx` (Dokumen flag yang terenskripsi password) - `/home/bbayugt/Downloads/AD1-tools/AD1Tools/out/Downloads/1000.zip` (Zip yang terenskripsi password) #### 2. Mencari password zip file Dengan menggunakan tools sqlite viewer, kita dapat menemukan sebuah link pastebin ![image](https://hackmd.io/_uploads/H15zzOw2el.png) Didalamnya terdapat 1000 line password ![image](https://hackmd.io/_uploads/Sk6gzOwnex.png) #### 3. Unzip file menggunakan password Gunakan shell script ini untuk unzip secara rekursif ```shell= #!/bin/bash # Add newline to the password file if it doesn't exist if [ -n "$(tail -c1 pastebin_passwords_unix.txt)" ]; then echo "" >> pastebin_passwords_unix.txt fi zip_file="1000.zip" # Loop from 1000 down to 1 for i in $(seq 1000 -1 1); do if [ ! -f "$zip_file" ]; then echo "File $zip_file not found. Stopping." break fi echo "Cracking ${zip_file}..." # Get the i-th password from the file password=$(sed -n "${i}p" pastebin_passwords_unix.txt) # Try to extract the zip file with the current password if 7z x -y -p"$password" "$zip_file" > /dev/null 2>&1; then echo "Password for ${zip_file} is: ${password}" else echo "Password not found for ${zip_file} with password: $password" break fi # Update zip_file for the next iteration next_i=$((i-1)) if [ "$next_i" -gt 0 ]; then zip_file="${i}/${next_i}.zip" fi done ``` #### 4. Decode notes pada `1`, terdapat notes yang berisi ```! VE9QIFNFQ1JFVCBSRUNJUEUNCjIvMyB0ZWFzcG9vbiBzYWx0DQoxLzIgdGVhc3Bvb24gdGh5bWUNCjEvMiB0ZWFzcG9vbiBiYXNpbA0KMS8zIHRlYXNwb29uIG9yZWdhbm8NCjEgdGVhc3Bvb24gY2VsZXJ5IHNhbHQNCjEgdGVhc3Bvb24gYmxhY2sgcGVwcGVyDQoxIHRlYXNwb29uIGRyaWVkIG11c3RhcmQNCjQgdGVhc3Bvb25zIHBhcHJpa2ENCjIgdGVhc3Bvb25zIGdhcmxpYyBzYWx0DQoxIHRlYXNwb29uIGdyb3VuZCBnaW5nZXINCjMgdGVhc3Bvb25zIHdoaXRlIHBlcHBlcg0KDQpteSBzZWNyZXQgd29yZCBmaWxlIHBhc3N3b3JkLCBqdXN0IGluIGNhc2UgaSBmb3Jnb3QNCml2Qm9qVUFGcVdjTGRTRG51bGdRSzZMQThhRkhkREM2 ``` yang dapat di decode dengan base64 menjadi ```! TOP SECRET RECIPE 2/3 teaspoon salt 1/2 teaspoon thyme 1/2 teaspoon basil 1/3 teaspoon oregano 1 teaspoon celery salt 1 teaspoon black pepper 1 teaspoon dried mustard 4 teaspoons paprika 2 teaspoons garlic salt 1 teaspoon ground ginger 3 teaspoons white pepper my secret word file password, just in case i forgot ivBojUAFqWcLdSDnulgQK6LA8aFHdDC6 ``` #### 5. Membuka flag.docx pada Documents Setelah mendekripsi password, hanya ada ini, kemungkinan text hidden ![image](https://hackmd.io/_uploads/Skk4zOPnee.png) Pada OnlyOffice, kita dapat menghapus enkripsi dengan fitur protect -> Delete password lalu extract dengan 7z ada text tersembunyi yang berisi: `SECRETs EveRyWhere whiSper aloNg HallWayS` Setelah menganalisa text, ternyata flag nya ada di font pada hidden text, bukan text itu sendiri, dan kapital dari huruf hidden tersebut menentukan apakah font tersebut harus kapital atau tidak ```python= import xml.etree.ElementTree as ET def get_final_flag(xml_file): tree = ET.parse(xml_file) root = tree.getroot() flag = "" # The namespace for the 'w' prefix ns = {'w': 'http://schemas.openxmlformats.org/wordprocessingml/2006/main'} count = 0 for r_element in root.findall('.//w:r', ns): vanish = r_element.find('.//w:rPr/w:vanish', ns) if vanish is not None: count += 1 if count % 2 == 0: # Get the hidden text character t_element = r_element.find('.//w:t', ns) hidden_char = '' if t_element is not None and t_element.text is not None: hidden_char = t_element.text if hidden_char.isspace(): continue # Get the font name rfonts = r_element.find('.//w:rPr/w:rFonts', ns) if rfonts is not None: font_name = rfonts.get('{http://schemas.openxmlformats.org/wordprocessingml/2006/main}ascii') if font_name: first_letter = font_name[0] if hidden_char.isalpha(): if hidden_char.islower(): flag += first_letter.lower() else: flag += first_letter.upper() else: flag += first_letter return flag if __name__ == "__main__": xml_file = "output/word/document.xml" final_flag = get_final_flag(xml_file) print(f"HOLOGY8{{{final_flag[7:]}}}") ``` ![image](https://hackmd.io/_uploads/B1JrGuD2eg.png) walaupun beberapa teks duplikat, tetapi sudah ada yang terbaca, dan menambahkan underscore pada setiap kata, kita mendapatkan flag nya! **Flag : HOLOGY8{Su5PiC1ou5_looKing_fonT_zM7k3X6aB}** ---