Skip to main content

Command Palette

Search for a command to run...

PETIR - Regen 2025 (Rev)

Updated
11 min read
PETIR - Regen 2025 (Rev)

Selamat datang di blog pertama saya yang akan membagikan how to solve Reverse Engineering Challenge by Part of PETIR, dan ngga semua saya tulis ya, karna ada banyak challenge nya jadi saya ambil yang menurutku menarik untuk dibahas. Oiya dan by the way, saya menyumbangkan 1 challenge yang saya buat untuk challenge ctf ini.

PETIR Vault

Category : Reverse Engineering
Points : 500
Difficulty : Hard

breaking classic vaults kinda boring... let's give a shot to our strongest vault the "PETIRVAULT" 😈

Author: gengi

Oke disini diberikan apk dan kita langsung aja coba decompile pakai apktool, mungkin buat beberapa orang lebih enak pakai jadx dan tool lain sebagainya, tapi kalo saya prefer ke apktool.

Setelah di decompile, langsung saja kita lihat file “AndroidManifest.xml”, dan ternyata bisa dilihat bahwa Mainactivity nya ada di “com.gengi.petirvault.MainActivity”

Oke setelah di analisa di dalam file smali_classes3/com/gengi/petirvault/MainActivity.smali kita bisa lihat fungsi utamanya adalah validasi password dengan function checkFlag

.method private final native checkFlag(Ljava/lang/String;)Z
.end method

.line 31
    .local v0, "input":Ljava/lang/String;
    invoke-direct {p1, v0}, Lcom/gengi/petirvault/MainActivity;->checkFlag(Ljava/lang/String;)Z

Dan di kode ini juga kita tahu bahwa Implementasi JNI dari fungsi checkFlag akan berada dalam file library native (biasanya .so di Android) yang dimuat oleh kode ini.

.line 14
    sget-object v0, Lcom/gengi/petirvault/LiveLiterals$MainActivityKt;->INSTANCE:Lcom/gengi/petirvault/LiveLiterals$MainActivityKt;
    invoke-virtual {v0}, Lcom/gengi/petirvault/LiveLiterals$MainActivityKt;->String$arg-0$call-loadLibrary$class-Companion$class-MainActivity()Ljava/lang/String;
    move-result-object v0
    invoke-static {v0}, Ljava/lang/System;->loadLibrary(Ljava/lang/String;)V

karna merujuk pada library .so, maka kita coba check menggunakan disassambler Ida di file lib/x86_64/libpetirvault.so

Kita analisa yang penting penting saja ya, jadi seperti ini

1. memcpy(dest, &unk_131A0, sizeof(dest)); & v9 = xmmword_132A0; //Data hardcoded disalin ke buffer untuk validasi.
2. sub_21B50(v11, &v7, v8); //Process Encrypt.
3. v6 = (sub_21C40(v11, &v9) & 1) != 0; //Pembanding input dengan output yg diharapkan.
4. return v6; //Mengembalikan hasil validasi

Oke, dari informasi penting tersebut kita coba lihat proses enkripsinya gimana.

Kita analisa yang penting penting lagi ya, jadi seperti ini

v5 = *a2;  // Mengambil referensi ke data hardcoded
v3 = (unsigned __int8 *)sub_21D10(a3, i);  // Mengambil karakter ke-i dari password
v6 = *(_BYTE *)sub_21CF0(v5, *v3);  // Memproses karakter dengan data hardcoded
*(_BYTE *)sub_21D40(a1, i) = v6;  // Menyimpan hasil di buffer output
memset(a1, 0, 0x25uLL); //37

Oke dari informasi yang kita udah dapetin kita kumpulin jadi seperti ini

1. Var unk 131A0 : Validasi value
2. Var xmmword 132A0 : Perbandingannya
3. Function sub 21B50 : algoritma transformasi
gef➤  x/256 0x131A0
0x131a0:    0xd56a0952    0x38a53630    0x9ea340bf    0xfbd7f381
0x131b0:    0x8239e37c    0x87ff2f9b    0x44438e34    0xcbe9dec4
0x131c0:    0x32947b54    0x3d23c2a6    0xb954cee    0x4ec3fa42
0x131d0:    0x66a12e08    0xb224d928    0x49a25b76    0x25d18b6d
0x131e0:    0x64f6f872    0x16986886    0xcc5ca4d4    0x92b6655d
0x131f0:    0x5048706c    0xdab9edfd    0x5746155e    0x849d8da7
0x13200:    0xabd890    0xad3bc8c    0x558e4f7    0x645b3b8
0x13210:    0x8f1e2cd0    0x20f3fca    0x3bdafc1    0x6b8a1301
0x13220:    0x4111913a    0xeadc674f    0xcecff297    0x73e6b4f0
0x13230:    0x2274ac96    0x8535ade7    0xe837f9e2    0x6edf751c
0x13240:    0x0    0x0    0x0    0x0
0x13250:    0x0    0x0    0x0    0x0
0x13260:    0x0    0x0    0x0    0x0
0x13270:    0x0    0x0    0x0    0x0
0x13280:    0x0    0x0    0x0    0x0
0x13290:    0x0    0x0    0x0    0x0
0x132a0:    0xa4fd686c    0xbcab0348    0x8cb806f7    0xcad84584
0x132b0:    0x84bc0fe4    0x1eabe4b8    0x84af1ed8    0xb8d845d8
0x132c0:    0x8fe48faf    0x13    0x0    0x0
0x132d0:    0x19    0x0    0x14    0x0
0x132e0:    0x61766f63    0x6e616972    0x65722074    0x6e727574
0x132f0:    0x75687420    0x74206b6e    0x3c00206f    0x2b2b00
0x13300:    0x7265706f    0x726f7461    0x6f003d5e    0x61726570
0x13310:    0x3c726f74    0x6f6e003d    0x36387820    0x2034365f
0x13320:    0x616f6c66    0x65722074    0x74736967    0x737265
0x13330:    0x6e6b6e75    0x206e776f    0x6e696f70    0x20726574
0x13340:    0x6f636e65    0x676e6964    0x63656400    0x7079746c
0x13350:    0x3e002865    0x7974003d    0x64696570    0x6f002820
0x13360:    0x61726570    0x3e726f74    0x6f003d3e    0x61726570
0x13370:    0x3c726f74    0x6c003e3d    0x676e6f    0x72616863
0x13380:    0x745f3233    0x62696c00    0x69776e75    0x203a646e
0x13390:    0x666c616d    0x656d726f    0x57442064    0x4146435f
0x133a0:    0x6765725f    0x65747369    0x57442072    0x20465241
0x133b0:    0x69776e75    0x202c646e    0x32676572    0x6f6f7420
0x133c0:    0x67696220    0x696c000a    0x776e7562    0x3a646e69
0x133d0:    0x6c616d20    0x6d726f66    0x44206465    0x46435f57
0x133e0:    0x61765f41    0x666f5f6c    0x74657366    0x2066735f
0x133f0:    0x52415744    0x6e752046    0x646e6977    0x6572202c
0x13400:    0x6f742067    0x6962206f    0x78000a67    0x356d6d
0x13410:    0x316d6d78    0x2e0031    0x6874002f    0x776f72
0x13420:    0x61686377    0x745f72    0x7265706f    0x726f7461
0x13430:    0x7473007e    0x623a3a64    0x63697361    0x7274735f
0x13440:    0x676e69    0x6c636564    0x65707974    0x74756128
0x13450:    0x4400296f    0x74656c65    0x76206465    0x75747269
0x13460:    0x66206c61    0x74636e75    0x206e6f69    0x6c6c6163
0x13470:    0x216465    0x3a647473    0x6378653a    0x69747065
0x13480:    0x78006e6f    0x336d6d    0x6d726574    0x74616e69
0x13490:    0x20676e69    0x68746977    0x20732520    0x65637865
0x134a0:    0x6f697470    0x666f206e    0x70797420    0x73252065
0x134b0:    0x6e6f6300    0x635f7473    0x747361    0x75003e3e
0x134c0:    0x6769736e    0x2064656e    0x6e695f5f    0x38323174
0x134d0:    0x65706f00    0x6f746172    0x65642072    0x6574656c
0x134e0:    0x65706f00    0x6f746172    0x3d3e72    0x69776e75
0x134f0:    0x705f646e    0x65736168    0x696c0032    0x776e7562
0x13500:    0x3a646e69    0x6c616d20    0x6d726f66    0x44206465
0x13510:    0x46435f57    0x65645f41    0x66635f66    0x57442061
0x13520:    0x20465241    0x69776e75    0x202c646e    0x20676572
0x13530:    0x206f6f74    0xa676962    0x74656700    0x42454c53
0x13540:    0x383231    0x53746567    0x64657661    0x69676552
0x13550:    0x72657473    0x31317200    0x70797400    0x666e6965
0x13560:    0x616e206f    0x6620656d    0x20726f    0x7265706f
0x13570:    0x726f7461    0x77656e20    0x64747300    0x756e3a3a
0x13580:    0x74706c6c    0x745f72    0x636a626f    0x6a626f5f
0x13590:    0x746365    0x3a647473    0x6461623a    0x6c6c615f
gef➤  x/37 0x132A0
0x132a0:    0xa4fd686c    0xbcab0348    0x8cb806f7    0xcad84584
0x132b0:    0x84bc0fe4    0x1eabe4b8    0x84af1ed8    0xb8d845d8
0x132c0:    0x8fe48faf    0x13    0x0    0x0
0x132d0:    0x19    0x0    0x14    0x0
0x132e0:    0x61766f63    0x6e616972    0x65722074    0x6e727574
0x132f0:    0x75687420    0x74206b6e    0x3c00206f    0x2b2b00
0x13300:    0x7265706f    0x726f7461    0x6f003d5e    0x61726570
0x13310:    0x3c726f74    0x6f6e003d    0x36387820    0x2034365f
0x13320:    0x616f6c66    0x65722074    0x74736967    0x737265
0x13330:    0x6e6b6e75

Oke, dari ketiga informasi penting tersebut bisa kita buat code untuk mendapatkan flagnya.

def inikahrev():
    with open("libpetirvault.so", "rb") as f:
        a = f.seek(0x131A0)
        table = list(f.read(256)) #_BYTE dest[256];
        b = f.seek(0x132A0)
        output = list(f.read(37)) #memset(a1, 0, 0x25uLL); decimal : 37
        reverse = {v: i for i, v in enumerate(table)}
        flag = ''.join(chr(reverse[b]) for b in output)
        return flag
print(inikahrev())
PETIR{behold_native_library_analysis}

Shrink

Category : Reverse Engineering
Points : 496
Difficulty : Medium

Recently, I downloaded a malware and try running it. I think it's just sending all files in my computer to the attacker server. Upon reversing it, I found out that before sending, he run a program that shrinks the filesize. I try using a normal unzip command but it doesn't work. Can you help me reverse the following program. Here I also have a sample file that being compressed with the program.

author: Lyo

Oke, di challenge satu ini kita diberikan 2 file, executable(elf) dan output.zip yang dimana secara overview, kita diminta untuk reverse encryption agar dapat membaca isi dalam output.zip nya. Mari kita langsung analisa.

TL;DR
ada beberapa function utama, saya bakalan ambil yang penting penting aja.

1. Function produce zip : 
- Magic Bytes 7305548
- Takes dictionary code and an input file, then reads the input byte by byte, looks up each byte's code in the dictionary, and writes the encoded bits to an output file.

2. Function make dictionary : 
- Recursively traverses the Huffman tree to build a dictionary mapping each byte value to its Huffman code.

3. Function write out : 
- Converts the binary string representation ('0's and '1's) to actual binary data, working 8 bits at a time.

4. Function make tree : 
- Shows the Huffman tree structure used

dan ada beberapa function penambahnya.

1. Function print list: 
- Only debug

2. Function List and Node : 
- These are utility functions for creating data structures, but understanding their implementation details is less critical than understanding how the data structures are used.

3. Function insert :
- While important for building the tree, it's less relevant for the reverse process.

4. Function merge :
- Combines two nodes into a new internal node with the combined frequency.

Oke dari informasi yang kita dapat, kita bisa buat function untuk parse Huffman code dictionary terlebih dahulu

def parse_huffman_dictionary(data, dict_pos):
    huffman_dict = {}
    pos = dict_pos + 4  # Lewati magic number

    while pos + 4 <= len(data):
        # Setiap entri dictionary adalah 4 byte
        entry = struct.unpack('<I', data[pos:pos+4])[0]

        # Ekstrak komponen entri
        byte_asli = entry & 0xFF               # 8 bit pertama
        panjang_kode = (entry >> 8) & 0xFF     # 8 bit kedua
        kode_huffman = (entry >> 16) & 0xFFFF  # 16 bit terakhir

        # Hanya proses entri yang valid
        if panjang_kode > 0:
            # Ambil representasi binary dari Huffman code
            kode_biner = format(kode_huffman, '016b')[:panjang_kode]
            huffman_dict[kode_biner] = byte_asli

        pos += 4

    return huffman_dict

setelah itu kita bisa buat function decompress data

def decompress_data(compressed_data, huffman_dict):
    hasil = bytearray()
    buffer_bit = ""

    # Proses setiap byte data terkompresi
    for byte in compressed_data:
        # Byte dalam file terkompresi di-NOT, jadi kita NOT kembali
        byte_terbalik = ~byte & 0xFF
        buffer_bit += format(byte_terbalik, '08b')
        while True:
            ditemukan = False

            for kode, nilai in huffman_dict.items():
                if buffer_bit.startswith(kode):
                    # Cocok! Tambahkan byte yang didekompresi
                    hasil.append(nilai)
                    # Hapus kode yang cocok dari buffer
                    buffer_bit = buffer_bit[len(kode):]
                    ditemukan = True
                    break

            # Jika tidak ada yang cocok, kita butuh lebih banyak bit
            if not ditemukan:
                break

    return hasil

Oke, karna sudah dibuat function untuk parse Huffman dictionary dan udah bikin function buat decompress data, sekarang langsung kita buat untuk decompress filenya pakai huffman dictionary yg sudah kita dapatkan.

def decompress_huffman(input_file='output.zip', output_file='decompressed.bin'):
    with open(input_file, 'rb') as f:
        data = f.read()

    # 2. Cari magic number (pemisah antara data terkompresi dan kamus)
    magic_number = bytes([0x4c, 0x79, 0x6f, 0x00])  # "Lyo\0"
    dict_pos = data.find(magic_number)

    if dict_pos == -1:
        print("Error: Format file tidak valid")
        return bytearray()

    # 3. Pisahkan data terkompresi
    compressed_data = data[:dict_pos]

    # 4. Buat kamus Huffman dari header
    huffman_dict = parse_huffman_dictionary(data, dict_pos)

    # 5. Dekompresi data
    hasil = decompress_data(compressed_data, huffman_dict)

    # 6. Simpan hasil dekompresi
    with open(output_file, 'wb') as f:
        f.write(hasil)

    print(f"Berhasil mendekompresi {len(compressed_data)} byte menjadi {len(hasil)} byte")
    print(f"Output disimpan ke {output_file}")

    return hasil

dan gg bagus btw

PETIR{Pow3r_1snt_d3term1neD_by_y0ur_51ze_but_th3_5iz3_of_your_he4rT_4nd_Dre4ms}

zsaxor’s Machine

Category : Reverse Engineering
Points : 500
Difficulty : Hard

This appears to be a simple image classifier trained on 10 classes. But there's more than meets the eye...
https://huggingface.co/spaces/zsaxor/PETIR_Machine/tree/main
_
author: Yobel

Dann yapp, ini challenge yang saya buat dan saya akan menjelaskan how to solve it sampai dapat flag, btw ini challenge saya buat dan terburu buru juga jadi buat dapet part of flagnya ada yg dukun dikit hehe sorry.

Okee, di link tersebut kita disediakan 2 file penting yaitu App.py dan MachineLearning model nya.
Saya akan meringkas apa yang App.py lakukan.

class FlagHiddenModel(nn.Module):
    def __init__(self):
        super(FlagHiddenModel, self).__init__()
        self.conv1 = nn.Conv2d(3, 16, 3, padding=1)
        self.conv2 = nn.Conv2d(16, 32, 3, padding=1)
        self.conv3 = nn.Conv2d(32, 64, 3, padding=1)
        self.pool = nn.MaxPool2d(2, 2)
        self.fc1 = nn.Linear(64 * 4 * 4, 512)
        self.fc2 = nn.Linear(512, 10)
        self.extra1 = nn.Linear(10, 10)
        self.extra2 = nn.Linear(10, 15)
    def forward(self, x):
        x = self.pool(F.relu(self.conv1(x)))
        x = self.pool(F.relu(self.conv2(x)))
        x = self.pool(F.relu(self.conv3(x)))
        x = x.view(-1, 64 * 4 * 4)
        x = F.relu(self.fc1(x))
        x = self.fc2(x)
        x = self.extra1(x)
        x = self.extra2(x)
        return x

model = FlagHiddenModel()
model_path = os.path.join(os.path.dirname(__file__), "Petir_model.pth")
model.load_state_dict(torch.load(model_path))
model.eval()

Oke dari file App.py tersebut kita mendapatkan beberapa informasi sebagai berikut :

FlagHiddenModel adalah sebuah Convolutional Neural Network dengan:
- 3 layer konvolusi (16, 32, 64 filter)
- Layer pooling untuk mengurangi dimensi
- Fully connected layer untuk klasifikasi
- 2 layer tambahan (extra1, extra2)

Struktur proses:
- Input gambar RGB (3 channel)
- Diproses melalui konvolusi dan pooling
- Diubah ke bentuk vektor (flattened)
- Diproses melalui fully connected layers
- Output akhir berukuran 15 (kemungkinan 15 kelas)

defined model:
- Memuat bobot pre-trained dari file "Petir model.pth"
- Mengatur model ke mode evaluasi (untuk prediksi, bukan training)

Oke, dari 3 point informasi tersebut kita coba buat extract bias yang ada di dalam model tersebut

import torch

# Defined model (same as app.py)
class FlagHiddenModel(torch.nn.Module):
    def __init__(self):
        super(FlagHiddenModel, self).__init__()
        self.conv1 = torch.nn.Conv2d(3, 16, 3, padding=1)
        self.conv2 = torch.nn.Conv2d(16, 32, 3, padding=1)
        self.conv3 = torch.nn.Conv2d(32, 64, 3, padding=1)
        self.pool = torch.nn.MaxPool2d(2, 2)
        self.fc1 = torch.nn.Linear(64 * 4 * 4, 512)
        self.fc2 = torch.nn.Linear(512, 10)
        self.extra1 = torch.nn.Linear(10, 10)
        self.extra2 = torch.nn.Linear(10, 15)

# Load model
model = FlagHiddenModel()
model.load_state_dict(torch.load("Petir_model.pth"))

# Ekstrak layer extra1 dan extra2
extra1_weights = model.extra1.weight.data
extra1_bias = model.extra1.bias.data
extra2_weights = model.extra2.weight.data
extra2_bias = model.extra2.bias.data

print("Extra1 weights:", extra1_weights)
print("Extra2 weights:", extra2_weights)

Ini outputnya

Extra1 weights: tensor([[ 1.5200e+02,  2.3600e+02,  5.0212e-02,  7.8991e-02, -2.5542e-01,
         -2.2602e-01, -2.9875e-01, -1.3114e-01, -1.1334e-01, -9.5279e-02],
        [ 1.0200e+02,  1.0200e+02,  7.9076e-02,  5.0860e-02, -5.5287e-02,
         -9.0633e-02, -1.3254e-01, -1.4084e-01,  1.4269e-01,  7.1517e-02],
        [ 1.9400e+02,  2.2800e+02, -7.6083e-02, -9.5965e-02,  1.5007e-02,
          2.2705e-01, -1.7065e-01,  3.1315e-01,  2.4081e-01,  2.6580e-01],
        [ 2.2800e+02,  2.8283e-01,  3.0254e-01,  2.1410e-02,  2.8588e-01,
          4.4408e-02, -2.7380e-01,  1.2713e-01, -2.5916e-01, -9.2629e-02],
        [ 2.2000e+02, -1.4661e-01,  1.8783e-01, -2.3814e-01, -2.9129e-01,
         -3.0149e-01,  2.1264e-01, -5.5419e-02,  1.8151e-01, -1.0675e-01],
        [ 2.2000e+02,  1.3276e-01,  2.0293e-01, -1.2853e-01,  2.8207e-01,
          2.6152e-01, -3.1244e-01, -2.3554e-01,  1.6658e-01,  2.2507e-01],
        [ 2.2000e+02,  2.9162e-01, -2.1391e-01,  1.9614e-01,  2.7321e-03,
          2.0751e-01,  2.5662e-01, -1.7780e-01, -6.1063e-02, -2.6174e-01],
        [ 1.9000e+02, -5.2718e-02, -1.7661e-01,  6.7452e-02, -1.3959e-01,
          1.7214e-01,  2.8350e-01, -1.4134e-01, -2.3724e-01,  1.1451e-01],
        [ 1.6400e+02,  2.5500e-01, -2.9938e-01,  2.4451e-01,  4.4782e-02,
         -1.5596e-01,  2.7163e-01, -2.2657e-01,  1.5377e-01, -1.1760e-01],
        [ 1.0200e+02,  3.5624e-02, -1.2795e-01,  8.8012e-02, -3.8057e-02,
         -6.7770e-02,  2.5786e-01,  1.8688e-01,  3.0476e-01,  3.0181e-02]])
Extra2 weights: tensor([[ 5.3372e-02, -1.2206e-01, -2.0157e-01, -2.9304e-01,  2.6919e-01,
         -2.1101e-02, -6.5590e-02, -3.1418e-02,  5.6984e-02, -9.4244e-02],
        [ 9.0629e-02,  2.6126e-01, -1.9399e-01,  1.2757e-01, -2.1429e-01,
          2.1943e-01,  1.5627e-01, -2.9416e-01,  9.8999e-02,  1.2509e-01],
        [-2.1022e-01,  6.5313e-02, -1.3623e-01, -2.9161e-01, -1.8392e-01,
         -3.9290e-02,  2.6822e-01, -3.0914e-01,  2.9929e-01,  1.3942e-01],
        [ 2.7668e-01,  4.5285e-02, -2.3130e-01, -5.7253e-02,  1.1654e-01,
          9.1768e-02, -2.7198e-01, -2.1697e-02, -2.9954e-01, -1.0575e-02],
        [ 2.2817e-01, -2.1630e-01,  1.4259e-01,  1.2182e-01, -1.8079e-02,
         -1.3866e-01, -2.3029e-01, -1.2908e-01,  2.2787e-01, -4.8569e-03],
        [ 2.4511e-01, -1.4637e-01,  1.9247e-01, -1.9916e-01, -1.5090e-01,
          2.7718e-02, -1.1462e-01,  2.7909e-01,  1.9089e-01,  2.2465e-01],
        [ 2.2524e-01, -7.0634e-02, -2.7436e-01,  1.4859e-01, -1.6495e-01,
         -1.7987e-01, -1.3293e-01,  1.3432e-01,  1.8223e-01,  1.3136e-01],
        [-5.8470e-02, -1.1194e-01,  2.8960e-01, -1.0045e-01,  2.5031e-05,
          1.9365e-01,  2.3421e-01, -2.2163e-01, -2.1082e-02, -8.5013e-02],
        [ 2.3026e-01, -2.2223e-01,  4.4447e-02, -2.1648e-01, -1.6877e-01,
         -1.1029e-01, -2.2788e-02,  2.7822e-01, -2.6018e-01, -5.6159e-02],
        [ 2.1871e-01,  1.2413e-01,  2.5761e-01,  1.5136e-01,  9.7616e-02,
          2.1411e-01, -1.2809e-01,  3.8235e-02, -1.4118e-02,  8.8137e-02],
        [-3.1106e-01,  1.5345e-01,  2.6579e-01,  1.6218e-01, -2.3825e-01,
         -3.1617e-01, -2.2299e-02,  1.8913e-01, -5.7825e-03, -1.7779e-01],
        [ 2.2653e-01,  2.0688e-01, -1.9616e-02,  7.6638e-02, -1.4879e-03,
          2.7510e-01, -1.7237e-01,  2.9675e-01,  2.9563e-01,  1.4176e-01],
        [-3.3684e-02,  5.6850e-02, -1.5909e-01,  1.3998e-02, -1.5619e-01,
          2.2956e-01, -1.8440e-01,  2.5275e-01, -2.6133e-01, -2.8207e-01],
        [-7.1596e-02,  9.3479e-02,  1.9835e-01,  2.1726e-02,  3.1389e-01,
          1.5087e-01, -2.0211e-01,  2.6250e-01,  1.4254e-01, -4.9675e-02],
        [ 2.8417e-01,  2.4641e-01, -2.1065e-01, -6.6874e-02,  3.8335e-02,
         -2.1096e-01,  2.9706e-01,  3.0813e-01, -2.5225e-01,  3.7253e-02]])

Oke ada yang menarik Di extra1_weights (kolom pertama), nilai-nilainya sangat besar (100-230) dibandingkan nilai parameter neural network biasa yang umumnya kecil (-1 hingga 1). Jadi mari kita coba untuk translate ke ascii karna biasanya flag di simpan menjadi ascii di dalam model.

def extract_flag_part1(model):
    flag_chars = []
    with torch.no_grad():
        for i in range(len(model.fc1.bias)):
            val = int(model.fc1.bias[i].item())
            if val < 32 or val > 126:  # Range karakter ASCII yang dapat dibaca
                break
            flag_chars.append(chr(val))
    return ''.join(flag_chars)

Oke dengan code tersebut, kita dapat flag part 1

Flag Part 1: PETIR{Machine

Biasanya kalo part 1 flagnya ascii, part selanjut selanjutnya kemungkinan besar ngga jauh dari sana, jadi saya baca lagi tapi Sebagian besar nilainya kecil (antara -0.3 dan 0.3), yang merupakan ciri khas neural network weights. Tidak ada pola yang jelas yang menunjukkan ascii code. setelah cukup lama trial n error, saya ngga sengaja ternyata menemukan polanya ternyata hanya dibagi 2, jadi tetap di ascii codenya.

def extract_flag_part2(model):
    flag_chars = []
    with torch.no_grad():
        rows, cols = model.extra1.weight.size(0), model.extra1.weight.size(1)
        for i in range(rows * cols):
            row = i % rows
            col = i // rows
            val = int(model.extra1.weight[row][col].item() / 2)
            if val < 32 or val > 126:  # Range karakter ASCII yang dapat dibaca
                break
            flag_chars.append(chr(val))
    return ''.join(flag_chars)

Oke dengan code tersebut, kita berhasil dapat flag part 2

Flag Part 2: L3arnnn_R3v3r

Okee dan sekarang last part dari flag nya, jujur ini kesalahanku tapi adaa aja yang solve Jagoo jagoo emang PETIR ini, btw harusnya buat dapetin last flag ini ada hint “The Ultimate Question of Life, the Universe, and Everything” di dalam deskripsi challenge, tapi anggap saja tidak ada, kita pakai cara bruteforce aja buat dapat last char yaitu ( } )

def brute_force_part3(model):
    results = []
    bias_values = model.extra2.bias.data

    # Operasi pengurangan (subtraction)
    for val in range(1, 1000):
        flag = ""
        for i in range(len(bias_values)):
            float_val = float(bias_values[i])
            char_val = int(round(float_val - val))

            if 32 <= char_val <= 126:  # Range karakter ASCII yang dapat dibaca
                flag += chr(char_val)
            else:
                if len(flag) > 0:
                    break

        if '}' in flag:
            print(f"Found: subtract {val} -> {flag}")
            results.append(('subtract', val, flag))

    # Operasi penambahan (addition)
    for val in range(1, 1000):
        flag = ""
        for i in range(len(bias_values)):
            float_val = float(bias_values[i])
            char_val = int(round(float_val + val))

            if 32 <= char_val <= 126:
                flag += chr(char_val)
            else:
                if len(flag) > 0:
                    break

        if '}' in flag:
            print(f"Found: add {val} -> {flag}")
            results.append(('add', val, flag))

    # Operasi perkalian (multiplication)
    for val in range(1, 1000):
        flag = ""
        for i in range(len(bias_values)):
            float_val = float(bias_values[i])
            char_val = int(round(float_val * val))

            if 32 <= char_val <= 126:
                flag += chr(char_val)
            else:
                if len(flag) > 0:
                    break

        if '}' in flag:
            print(f"Found: multiply {val} -> {flag}")
            results.append(('multiply', val, flag))

    # Operasi pembagian (division)
    for val in range(1, 1000):  # Skip 0 untuk menghindari division by zero
        if val == 0:
            continue

        flag = ""
        try:
            for i in range(len(bias_values)):
                float_val = float(bias_values[i])
                char_val = int(round(float_val / val))

                if 32 <= char_val <= 126:
                    flag += chr(char_val)
                else:
                    if len(flag) > 0:
                        break

            if '}' in flag:
                print(f"Found: divide {val} -> {flag}")
                results.append(('divide', val, flag))
        except ZeroDivisionError:
            continue

    return results

Dann akhirnya dapat last part flag, tapi dengan cara bruteforce sekali lagi saya minta maaf.

PETIR{MachineL3arnnn_R3s33333_zsaxor}
338 views