Bài viết
Chia sẻ kiến thức của bạn.
Hướng dẫn của Hacker để chinh phục động thái CTF 2025 (Tuần 1)
Trong bảo mật blockchain, không có nơi đào tạo nào tốt hơn thử thách Capture The Flag (CTF).
Các nhà phát triển rèn luyện kỹ năng của họ trong đám cháy cạnh tranh thân thiện. Thử thách Move CTF 2025 Tuần 1 trên blockchain Sui là một ví dụ hoàn hảo được thiết kế để kiểm tra sự hiểu biết của bạn về ngôn ngữ Move.
Chúng ta sẽ đi từ việc thiết lập môi trường đến phân tích khả năng phòng thủ của hợp đồng thông minh, tạo ra một kịch bản giải quyết và cuối cùng thực hiện giao dịch tiết lộ giải thưởng đáng thèm muốn: CTF {LetsMoveCTF_week1}.
Cho dù bạn là một người mới làm quen với Move hay một nhà nghiên cứu bảo mật dày dạn kinh nghiệm, hướng dẫn này sẽ cung cấp một lộ trình thực tế để nâng cao kỹ năng của bạn. Hãy đi sâu vào!
Bước 1: Trinh sát - Hiểu Targe
Trước khi viết một dòng mã duy nhất, công việc đầu tiên của chúng tôi là hiểu chiến trường. Thách thức tập trung xung quanh một mô-đun Move duy nhấtweek1::challenge
, mà chúng ta cần phân tích.
public struct Challenge has key {
id: UID,
secret: String,
current_score: u64,
round_hash: vector<u8>,
finish: u64,
}
Nhiệm vụ của chúng tôi, nói một cách đơn giản, là gọi thành công get_flag
chức năng nhập. Một cuộc gọi thành công sẽ kích hoạt một FlagEvent
cuộc gọi, phát sóng chiến thắng của chúng tôi và lá cờ cho toàn bộ mạng.
Tuy nhiên, get_flag
chức năng được bảo vệ bởi một loạt năm kiểm tra xác thực riêng biệt. Để thành công, chúng ta phải thỏa mãn tất cả trong một giao dịch duy nhất.
Bước 2: Giải cấu trúc phòng thủ - Năm rào cản
Chức get_flag
năng là một pháo đài, và các bức tường của nó được tạo thành từ các assert!
tuyên bố. Chúng ta hãy phá vỡ từng rào cản này từng cái một.
Rào cản 1: Kiểm tra điểm
Nhiệm vụ: Tính toán hash sha3_256 của chuỗi challenge.secret hiện tại. Điểm chính xác là một số u64 bắt nguồn từ 4 byte đầu tiên của hash đó (sử dụng trật tự byte big-endian).
Khái niệm: Đây là một thách thức mật mã cơ bản để đảm bảo bạn có thể thực hiện chính xác thao tác băm và byte theo yêu cầu của hợp đồng.
Rào cản 2: Kiểm tra đoán (Câu đố chứng minh công việc)
Nhiệm vụ: Tìm một phép đoán (một vectơ byte, hoạt động như một nonce) sao cho khi bạn băm đoán và bí mật với nhau (sha3_256 (đoán || bí mật)), hai byte đầu tiên của hash kết quả khớp với hai byte đầu tiên của challenge.round_hash.
Khái niệm: Đây là một cơ chế Proof-of-Work (PoW) cổ điển. Nó không thể giải được bằng toán học; nó đòi hỏi nỗ lực tính toán (“brute force”) để tìm ra một dự đoán hợp lệ, chứng minh bạn đã dành tài nguyên để giải nó.
Rào cản 3: Kiểm tra hash_input (Liên kết nhận dạng)
Nhiệm vụ: Cung cấp một hash kết hợp chính xác bí mật và github_id cá nhân của bạn. Bí quyết ở đây là bí mật trước tiên phải được nối tiếp bằng cách sử dụng Binary Canonical Serialization (bcs: :to_bytes). Điều này khác với việc chỉ sử dụng byte thô của nó, vì BCS đặt trước dữ liệu với độ dài của nó. Tính toán cuối cùng là sha3_256 (bcs (bí mật) || github_id).
Khái niệm: Kiểm tra này liên kết giải pháp của bạn với mã định danh duy nhất của bạn, ngăn người khác chỉ đơn giản phát lại giao dịch thành công của bạn. Việc sử dụng BCS là một mô hình phổ biến trong Move và là một chi tiết quan trọng cần chú ý.
Rào cản 4 & 5: Kiểm tra hạt giống và số ma thuật
Nhiệm vụ: Hai tham số này được liên kết.
hạt giống được tính là chiều dài (bí mật) * 2.
magic_number được tính là (điểm% 1000) + hạt giống.
Khái niệm: Đây là những câu đố logic kiểm tra khả năng đọc mã Move một cách cẩn thận và sao chép các phép toán số học đơn giản của nó.
Bước 3: Thiết lập Bộ công cụ của bạn - Môi trường và triển khai
Với lý thuyết đã được hiểu, đã đến lúc làm bẩn tay của chúng ta.
Trước tiên, hãy đảm bảo Sui CLI của bạn được cài đặt và cấu hình cho testnet.
# 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
Tiếp theo, xây dựng và xuất bản hợp đồng Move lên mạng thử nghiệm Sui. Điều này sẽ biên dịch mã và triển khai nó, tạo ra Challenge
đối tượng chia sẻ ban đầu mà chúng ta cần tương tác với.
# Build the project
sui move build
# Publish the contract to the testnet
sui client publish --gas-budget 100000000
Sau khi xuất bản thành công, CLI sẽ xuất ra kết quả, bao gồm hai phần thông tin quan trọng bạn phải lưu:
ID gói: Địa chỉ hợp đồng mới được công bố của bạn.
ID đối tượng: Địa chỉ của Challenge
đối tượng được chia sẻ được tạo bởi init
hàm.
Bước 4: Rèn các phím - Tạo trình giải Python
Bây giờ, chúng ta cần tính toán các đối số chính xác để chuyển đếnget_flag
. Làm điều này theo cách thủ công là tẻ nhạt, vì vậy chúng tôi sẽ viết một tập lệnh Python để tự động hóa nó. Tập lệnh này đọc phần đầusecret
, “LetsMoveCTF_Week1" và tính toán tất cả năm tham số bắt buộc.
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}")
Bước 5: The Heist - Gọi get_flag và giành giải thưởng Với các tham số của chúng tôi được tính toán, chúng tôi sẽ sử dụng một tập lệnh Python khác để xây dựng và thực hiện lệnh gọi sui client cuối cùng. Điều này tự động hóa quá trình định dạng các đối số tẻ nhạt cho dòng lệnh.
call_get_flag.py (tóm tắt)
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)
Khi chạy script này, giao dịch sẽ được gửi đi. Nếu tất cả các tham số của chúng tôi là chính xác, đầu ra sẽ hiển thị Trạng thái: Thành công và quan trọng nhất là FlagEvent được phát ra:
"ParsedJSON": {
"flag": "CTF{Letsmovectf_week1}",
"github_id": "qiaopengjun5162",
"rank": "1",
"success": true
}
Thành công! Lá cờ đã bị bắt.
Một CTF được thiết kế tốt không kết thúc sau một lần giải quyết. Sau cuộc gọi thành công của chúng tôi, hàm get_flag sử dụng đối tượng Random để tạo một bí mật mới và cập nhật đối tượng Challenge.
Tôi đã xác nhận điều này bằng cách truy vấn lại đối tượng, tìm một bí mật mới và lặp lại quá trình. Các tập lệnh giải của tôi có thể tái sử dụng được — tôi chỉ cần cập nhật biến bí mật, chạy lại tính toán và thực hiện lại cuộc gọi để bắt cờ lần thứ hai và thứ ba, leo lên thứ hạng.
https://suiscan.xyz/testnet/tx/AzJywLk8zv1Fx5Pc8p4ZrZwFZQ9hmTbtvweo14MVn8fZ
Kết luận: Không chỉ là một lá cờ
Giải quyết thử thách Move CTF 2025 Tuần 1 là một trải nghiệm học tập đáng kinh ngạc. Nó buộc tôi phải vượt ra ngoài lý thuyết và tham gia trực tiếp với blockchain Sui, củng cố các khái niệm chính như:
Logic hợp đồng thông minh: Đọc kỹ và hiểu mã Move là tối quan trọng.
Mật mã trong thực tế: Áp dụng hashing (sha3_256) và hiểu thao tác byte.
Cơ học trên chuỗi: Tầm quan trọng của các định dạng sê-ri cụ thể như BCS.
Tự động hóa: Sử dụng các tập lệnh để làm cho các tác vụ phức tạp, có thể lặp lại có thể quản lý được.
Thử thách này là một minh chứng cho sức mạnh của việc học tập thực hành. Nếu bạn đang tìm cách phát triển kỹ năng của mình trong phát triển và bảo mật blockchain, tôi thực sự khuyến khích bạn nhảy vào
- Sui
Sui is a Layer 1 protocol blockchain designed as the first internet-scale programmable blockchain platform.
Kiếm phần của bạn từ 1000 Sui
Tích lũy điểm danh tiếng và nhận phần thưởng khi giúp cộng đồng Sui phát triển.

- ... SUIBigSneh+1396
- ... SUISuiLover+1333
- ... SUI0xduckmove+1207
- ... SUIThorfin+1202
- ... SUIOwen+970
- ... SUIharry phan+847
- ... SUItheking+742
- Tại sao BCS yêu cầu thứ tự trường chính xác để khử chuỗi khi cấu trúc Move có các trường được đặt tên?53
- Nhiều lỗi xác minh nguồn” trong các ấn phẩm về mô-đun Sui Move - Giải quyết lỗi tự động43
- Giao dịch Sui thất bại: Đối tượng được dành riêng cho giao dịch khác25
- Làm thế nào để các ràng buộc về khả năng tương tác với các trường động trong các bộ sưu tập không đồng nhất?05