本文主要介绍了MoveCTF有关的概念,通过check_in挑战我们了解了如何通过验证和生成哈希,成功获取新的标志,并通过智能合约与区块链互动。
CTF(Capture The Flag)中文一般叫夺旗赛,主要涉及以下活动: <!--StartFragment-->
<!--EndFragment-->
<!--StartFragment-->
<!--EndFragment-->
<!--StartFragment-->
0x914099b4d1b4f5513acc8aaa4fdc1f67578522b81d818f61bae527d590c6d87d
0xc8dcd54baa7724177593a9f70598a09ae6a4286f996542e058f248209db08147
0x8
module check_in::check_in {
use std::ascii::{String, string};
use std::bcs;
use std::hash::sha3_256;
use std::vector;
use sui::event;
use sui::object;
use sui::random;
use sui::random::Random;
use sui::transfer::share_object;
use sui::tx_context::{Self, TxContext};
const ESTRING: u64 = 0;
public struct Flag has copy, drop {
sender: address,
flag: bool,
ture_num: u64,
github_id: String
}
public struct FlagString has key {
id: UID,
str: String,
ture_num: u64
}
fun init(ctx: &mut TxContext) {
let flag_str = FlagString {
id: object::new(ctx),
str: string(b"LetsMoveCTF"),
ture_num: 0
};
share_object(flag_str);
}
entry fun get_flag(
flag: vector<u8>,
github_id: String,
flag_str: &mut FlagString,
rand: &Random,
ctx: &mut TxContext
) {
// 定义一个可变的字节向量
let mut bcs_flag = bcs::to_bytes(&flag_str.str);
// 将GitHub ID对应的字节追加到bcs_flag字节向量后面
vector::append<u8>(&mut bcs_flag, *github_id.as_bytes());
// 验证传入的标志(flag)与 bcs_flag是否一致
assert!(flag == sha3_256(bcs_flag), ESTRING);
// 调用getRandomString函数,获取一个随机字符串
// 更新FlagString结构体中的str字段,替换原来的字符串内容
flag_str.str = getRandomString(rand, ctx);
// 将FlagString结构体中的ture_num字段值加1
flag_str.ture_num = flag_str.ture_num + 1;
// 触发一个事件(event)
// 更新后的ture_num值以及传入的GitHub ID等信息
event::emit(Flag {
sender: tx_context::sender(ctx),
flag: true,
ture_num: flag_str.ture_num,
github_id
});
}
fun getRandomString(rand: &Random, ctx: &mut TxContext): String {
let mut gen = random::new_generator(rand, ctx);
let mut str_len = random::generate_u8_in_range(&mut gen, 4, 30);
let mut rand: vector<u8> = b"";
while (str_len != 0) {
let rand_num = random::generate_u8_in_range(&mut gen, 34, 126);
vector::push_back(&mut rand, rand_num);
str_len = str_len - 1;
};
string(rand)
}
}
get_flag函数主要逻辑是,利用 assert!
宏进行验证,将传入的 flag
(以字节向量形式表示的外部传入的标志数据)与对构造好的 bcs_flag
数据进行 sha3_256
哈希计算后的结果做比较。如果两者不相等,则会触发错误(错误码由常量 ESTRING
表示),意味着标志验证失败;若相等,则说明传入的标志符合预期,验证通过,继续后续逻辑。
获取flag_str.str可以直接用Sui cli命令直接获取,下面截图仅供参考,我当时任务返回的str是“\T2R”
sui client object 0xc8dcd54baa7724177593a9f70598a09ae6a4286f996542e058f248209db08147
注意:这里需要注意sui里面一些特殊转义符,可能导致Hash计算的结果不正确。
将flag_str和GitHubID进行哈希计算后的字符串
#[test_only]
module check_in::check_in_tests {
use std::debug;
use std::vector;
use std::bcs;
use std::hash::sha3_256;
use std::ascii::{String, string};
// uncomment this line to import the module
// use check_in::check_in;
const ENotImplemented: u64 = 0;
const ESTRING: u64 = 0;
#[test]
fun test_check_in() {
// pass
let flag_str= string(b"\\T2R");
let github_id = string(b"LeonDev1024");
let mut bcs_flag = bcs::to_bytes(&flag_str);
vector::append<u8>(&mut bcs_flag, *github_id.as_bytes());
debug::print(&sha3_256(bcs_flag));
//assert!(flag == sha3_256(bcs_flag), ESTRING);
}
}
运行单元测试sui move test --skip-fetch-latest-git-deps
用CLI调用get_flag方法进行验证
这是一个简单的 CTF(Capture The Flag) 挑战,玩家需要通过验证给定的标志(flag)来获取一个新的标志,并触发事件。 通过CTF 题目我们了解了如何通过验证和生成哈希,成功获取新的标志,并通过智能合约与区块链互动。
对于单测和CLI常用命令可以参考: <!--StartFragment-->
Sui Move 调试Debugging和test_scenario单测工具使用 Sui move单测从入门到精通 Sui CLI常用指令介绍 Sui Client CLI 命令行详解
<!--EndFragment-->
<!--StartFragment-->
关注《HOH水分子》公众号,我们将持续分享和制作变成语言教程,让大家对编程产生化学反应。
<!--EndFragment-->
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!