Move CTF 共学营由 HOH 水分子社区联合 Cyclens 及 Movebit 共同推出。本期共学将于25年6月中旬正式开始,通过4周线上视频录播课程、有奖Task任务以及CTF挑战赛等多种方式,帮助大家快速了解 Web3 领域安全问题、提升在网络安全领域的实战能力。
Move CTF 共学营由 HOH 水分子社区联合 Cyclens 及 Movebit 共同推出。本期共学将于25年6月中旬正式开始,通过4周线上视频录播课程、有奖Task任务以及CTF挑战赛等多种方式,帮助大家快速了解 Web3 领域安全问题、提升在网络安全领域的实战能力。 详细信息请参考:https://platform.cyclens.tech/activity/1
本文分析 Week1 的 Move CTF 挑战,该挑战实现了一个多重验证的智能合约游戏。
week1::challenge
public struct Challenge has key {
id: UID, // 对象唯一标识符
secret: String, // 当前轮次的密钥
current_score: u64, // 当前分数
round_hash: vector<u8>, // 当前轮次的哈希值
finish: u64, // 完成次数/排名计数器
}
public struct FlagEvent has copy, drop {
sender: address, // 发送者地址
flag: String, // CTF flag内容
github_id: String, // GitHub ID
success: bool, // 是否成功
rank: u64, // 排名
}
验证逻辑:
let secret_hash = sha3_256(*string::as_bytes(&challenge.secret));
let expected_score = (((*vector::borrow(&secret_hash, 0) as u64) << 24) |
((*vector::borrow(&secret_hash, 1) as u64) << 16) |
((*vector::borrow(&secret_hash, 2) as u64) << 8) |
(*vector::borrow(&secret_hash, 3) as u64));
计算方式:
验证逻辑:
let mut guess_data = guess;
vector::append(&mut guess_data, *string::as_bytes(&challenge.secret));
let random = sha3_256(guess_data);
assert!(compare_hash_prefix(&random, &challenge.round_hash, 2), EINVALID_GUESS_HASH);
工作量证明机制:
验证逻辑:
let mut bcs_input = bcs::to_bytes(&challenge.secret);
vector::append(&mut bcs_input, *string::as_bytes(&github_id));
let expected_hash = sha3_256(bcs_input);
assert!(hash_input == expected_hash, EINVALID_HASH);
计算步骤:
验证逻辑:
let expected_magic = challenge.current_score % 1000 + seed;
assert!(magic_number == expected_magic, EINVALID_MAGIC);
计算公式:
验证逻辑:
let secret_bytes = *string::as_bytes(&challenge.secret);
let secret_len = vector::length(&secret_bytes);
assert!(seed == secret_len * 2, EINVALID_SEED);
计算公式:
# 伪代码示例
secret_hash = sha3_256(secret.encode())
score = int.from_bytes(secret_hash[:4], 'big')
seed = len(secret) * 2
magic_number = (current_score % 1000) + seed
bcs_secret = bcs_encode(secret)
hash_input = sha3_256(bcs_secret + github_id.encode())
# 伪代码示例
for guess in range(0, 2**32):
guess_bytes = guess.to_bytes(4, 'little')
combined = guess_bytes + secret.encode()
hash_result = sha3_256(combined)
if hash_result[:2] == round_hash[:2]:
return guess_bytes
使用计算出的所有参数调用合约的get_flag函数。
challenge.secret = getRandomString(rand, ctx);
challenge.round_hash = sha3_256(*string::as_bytes(&challenge.secret));
challenge.current_score = 0;
challenge.finish = challenge.finish + 1;
每次成功获取flag后:
share_object
创建共享对象Random
模块生成随机数event::emit
发出事件定义了5个错误常量:
EINVALID_GUESS_HASH
: 猜测哈希无效EINVALID_HASH
: 哈希输入无效 EINVALID_MAGIC
: 魔数无效EINVALID_SEED
: 种子无效EINVALID_SCORE
: 分数无效这个CTF挑战综合考验了:
挑战的核心在于理解各个验证步骤的逻辑,正确计算静态参数,并通过暴力破解找到合适的guess值。成功解题需要对Move语言和区块链开发有深入理解。
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!