Sui.

Допис

Діліться своїми знаннями.

article banner.
harry phan.
Jun 30, 2025
Стаття

Посібник хакера з підкорення ходу CTF 2025 (тиждень 1)

У безпеці блокчейну немає кращого навчального майданчика, ніж виклик Capture The Flag (CTF).

Розробники підковують свої навички в пожежах дружньої конкуренції. Виклик Move CTF 2025 Week 1 на блокчейні Sui є прекрасним прикладом, призначеним для перевірки вашого розуміння мови Move.

Ми перейдемо від налаштування середовища до аналізу захисту смарт-контракту, створення сценарію вирішувача та, нарешті, виконання транзакції, яка розкриває бажаний приз: CTF {LetsMoveCTF_week1}.

Незалежно від того, чи є ви новачком Move або досвідченим дослідником безпеки, цей посібник надасть практичну дорожню карту для вдосконалення ваших навичок. Давайте зануримося!

Крок 1: Розвідка - Розуміння Targe

Перш ніж писати один рядок коду, наше перше завдання - зрозуміти поле бою. Завдання зосереджено навколо одного модуля Moveweek1::challenge, який нам потрібно проаналізувати.

public struct Challenge has key {
    id: UID,
    secret: String,
    current_score: u64,
    round_hash: vector<u8>,
    finish: u64,
}

Наша місія, простіше кажучи, полягає в успішному виклику get_flagфункції входу. Успішний дзвінок спровокуєFlagEvent, транслюючи нашу перемогу і прапор на всю мережу.

Однак get_flagфункція захищена серією з п'яти різних перевірок перевірки. Щоб досягти успіху, ми повинні задовольнити їх усіх за одну транзакцію.

Крок 2: Деконструювання оборони - П'ять перешкод

get_flagФункція - фортеця, а її стіни складені з твер assert!джень. Давайте розберемо кожну з цих перешкод по черзі.

Перешкода 1: Перевірка рахунку

Завдання: Обчисліть хеш sha3_256 поточного рядка challenge.secret. Правильна оцінка - це число u64, отримане з перших 4 байтів цього хешу (з використанням біг-ендіанського порядку байтів).

Концепція: Це основна криптографічна проблема, яка гарантує, що ви можете правильно виконувати хешування та маніпуляції байтами, як того вимагає контракт.

Перешкода 2: Перевірка вгадування (головоломка підтвердження роботи)

Завдання: Знайдіть припущення (байтовий вектор, який діє як nonce) таким чином, щоб при хешуванні вашої здогадки та секрету разом (sha3_256 (вгадати || секрет)), перші два байти отриманого хешу збігаються з першими двома байтами виклику.round_hash.

Концепція: Це класичний механізм Proof-of-Work (PoW). Його неможливо вирішити математично; це вимагає обчислювальних зусиль («груба сила»), щоб знайти достовірну здогадку, доводячи, що ви витратили ресурси на її вирішення.

Перешкода 3: Перевірка hash_input (прив'язка ідентичності)

Завдання: Надати хеш, який правильно поєднує секрет і ваш особистий github_id. Хитрість тут полягає в тому, що секрет спочатку повинен бути серіалізований за допомогою бінарної канонічної серіалізації (bcs: :to_bytes). Це відрізняється від простого використання його необроблених байтів, оскільки BCS доповнює дані своєю довжиною. Остаточний розрахунок - sha3_256 (bcs (секрет) || github_id).

Концепція: Ця перевірка пов'язує ваше рішення з вашим унікальним ідентифікатором, не даючи іншим просто повторювати вашу успішну транзакцію. Використання BCS є загальним шаблоном у Move та ключовою деталлю, яку слід помітити.

Перешкода 4 і 5: Перевірка насіння та магічного числа

Завдання: Ці два параметри пов'язані між собою.

насіння розраховується як довжина (секрет) * 2.

magic_number обчислюється як (оцінка% 1000) + насіння.

Концепція: Це логічні головоломки, які перевіряють вашу здатність уважно читати код Move та повторювати його прості арифметичні операції.

Крок 3: Налаштування набору інструментів - середовище та розгортання

Зрозумівши теорію, настав час забруднити руки.

По-перше, переконайтеся, що ваш Sui CLI встановлено та налаштовано для тест-мережі.

# Check your Sui version
sui --version
> sui 1.50.1-homebrew

# Check your active environment
sui client envs
> testnet

# Check your active address and gas balance
sui client active-address
sui client gas

Далі побудуйте та публікуйте контракт Move в тестовій мережі Sui. Це скомпілює код і розгорне його, створюючи початковий спільний Challengeоб'єкт, з яким нам потрібно взаємодіяти.

# Build the project
sui move build

# Publish the contract to the testnet
sui client publish --gas-budget 100000000

Після успішної публікації CLI виведе результати, включаючи дві важливі відомості, які ви повинні зберегти:

Ідентифікатор пакету: адреса вашого нещодавно опублікованого контракту. Ідентифікатор об'єкта: Адреса спіль Challengeного об'єкта, створеного initфункцією.

Крок 4: Підробка ключів - створення розв'язувача Python

Тепер нам потрібно обчислити правильні аргументи для переходуget_flag. Робити це вручну нудно, тому ми напишемо сценарій Python для його автоматизації. Цей скрипт читає початковийsecret, «LetsMoveCTF_Week1", і обчислює всі п'ять необхідних параметрів.

import hashlib

# --- Configuration ---
github_id = b"qiaopengjun5162"
secret = b"Letsmovectf_week1"

# --- 1. Calculate Score ---
hash_bytes = hashlib.sha3_256(secret).digest()
score = int.from_bytes(hash_bytes[:4], 'big')
print(f"✅ Score: {score}")

# --- 2. Solve Proof-of-Work for Guess ---
target_prefix = hash_bytes[:2]
found_guess = None
for i in range(1000000): # Brute-force loop
    guess_candidate = f"guess{i}".encode()
    combined_data = guess_candidate + secret
    random_hash = hashlib.sha3_256(combined_data).digest()
    if random_hash[:2] == target_prefix:
        found_guess = guess_candidate
        print(f"✅ Guess Found: {found_guess.decode()}")
        print(f"   (as hex): {found_guess.hex()}")
        break

# --- 3. Calculate Hash Input (with BCS) ---
# BCS serialization for a string prepends its length as a ULEB128 integer.
# For short strings, this is just a single byte representing the length.
bcs_encoded_secret = bytes([len(secret)]) + secret
bcs_input_data = bcs_encoded_secret + github_id
hash_input = hashlib.sha3_256(bcs_input_data).digest()
print(f"✅ Hash Input (hex): {hash_input.hex()}")

# --- 4 & 5. Calculate Seed and Magic Number ---
secret_len = len(secret)
seed = secret_len * 2
magic_number = (score % 1000) + seed
print(f"✅ Seed: {seed}")
print(f"✅ Magic Number: {magic_number}")

Крок 5: Пограбування - виклик get_flag та захоплення призу З розрахованими нашими параметрами ми будемо використовувати інший сценарій Python для побудови та виконання кінцевої команди виклику клієнта sui. Це автоматизує виснажливий процес форматування аргументів для командного рядка.

call_get_flag.py (короткий зміст)

import subprocess

# --- Configuration (using values from previous script) ---
package_id = "0x804c92e4eef709b83f135d6cc667005ce35d7eccd49384570cbd7b1b40e32434"
challenge_id = "0xd28bc35560711a8b6ca93e2bf8e353fa6e17c15cbc426c48ece1ade9d83ce5ee"
random_id = "0x8"     # Default Random object on Sui
gas_budget = "10000000"

# --- Calculated Parameters ---
score = 1478524421
guess = [103, 117, 101, 115, 115, 55, 54, 57, 48, 56] # b'guess76908'
hash_input = [...] # The full byte array from the solver
github_id = "qiaopengjun5162"
magic_number = 455
seed = 34

# --- Construct and Execute the Sui CLI Command ---
command = [
    "sui", "client", "call",
    "--package", package_id,
    "--module", "challenge",
    "--function", "get_flag",
    "--args",
    str(score), str(guess), str(hash_input), f'"{github_id}"',
    str(magic_number), str(seed), challenge_id, random_id,
    "--gas-budget", gas_budget
]

# Execute the command and print the output
result = subprocess.run(command, capture_output=True, text=True, check=True)
print(result.stdout)

Після запуску цього скрипта транзакція надсилається. Якщо всі наші параметри правильні, на виході буде показано Status: Success і, головне, випущений flagEvent:

"ParsedJSON": {
  "flag": "CTF{Letsmovectf_week1}",
  "github_id": "qiaopengjun5162",
  "rank": "1",
  "success": true
}

Успіх! Прапор захоплений.

Добре розроблений CTF не закінчується після одного вирішення. Після нашого успішного виклику функція get_flag використовує об'єкт Random для створення нового секрету та оновлює об'єкт Challenge.

Я підтвердив це, знову запитавши об'єкт, знайшовши новий секрет і повторивши процес. Мої сценарії вирішувачів можна було використовувати повторно - мені просто потрібно було оновити секретну змінну, повторно запустити обчислення та виконати виклик знову, щоб захопити прапор вдруге та втретє, піднявшись у ряди.

https://suiscan.xyz/testnet/tx/AzJywLk8zv1Fx5Pc8p4ZrZwFZQ9hmTbtvweo14MVn8fZ

Висновок: Більше, ніж просто прапор

Вирішення виклику Move CTF 2025 Week 1 було неймовірним навчальним досвідом. Це змусило мене вийти за рамки теорії та безпосередньо взаємодіяти з блокчейном Sui, підсилюючи ключові концепції, такі як:

Розумна логіка контракту: уважно читати та розуміти код переміщення є першорядним.

Криптографія на практиці: Застосування хешування (sha3_256) та розуміння маніпулювання байтами.

Механіка ланцюга: важливість конкретних форматів серіалізації, таких як BCS.

Автоматизація: Використання скриптів для управління складними, повторюваними завданнями.

Цей виклик є свідченням сили практичного навчання. Якщо ви хочете розвинути свої навички у розробці та безпеці блокчейну, я настійно рекомендую вам перейти до

  • Sui
2
Поділитися
Коментарі
.

Sui is a Layer 1 protocol blockchain designed as the first internet-scale programmable blockchain platform.

610Пости1335Відповіді
Sui.X.Peera.

Зароби свою частку з 1000 Sui

Заробляй бали репутації та отримуй винагороди за допомогу в розвитку спільноти Sui.

Кампанія винагородЛипень