week1::challenge挑战概述在本次week1挑战中,是一个围绕哈希运算和秘密值进行交互的智能合约挑战。核心结构模块中定义了一个Challenge结构体,它包含了以下关键字段:id:对象的唯一标识符。secret:一个字符串类型的秘密值,初始值为Letsmov
<!--StartFragment-->
week1::challenge
挑战概述在本次 week1
挑战中,是一个围绕哈希运算和秘密值进行交互的智能合约挑战。
模块中定义了一个 Challenge
结构体,它包含了以下关键字段:
id
: 对象的唯一标识符。secret
: 一个字符串类型的秘密值,初始值为 Letsmovectf_week1
。current_score
: 当前得分,可能是衡量玩家进度或攻击成功与否的指标。round_hash
: 每一轮挑战的哈希值,用于验证玩家的猜测。finish
: 可能表示挑战是否结束或达到某个特定状态。此外,还有一个 FlagEvent
事件结构体,用于记录挑战结果,包括发送者、获得的 Flag、GitHub ID、成功状态以及排名等信息。
代码源码:
module week1::challenge {
use std::bcs;
use std::hash::sha3_256;
use std::string::{Self, String};
use sui::event;
use sui::random::{Self, Random};
use sui::transfer::share_object;
const EINVALID_GUESS_HASH: u64 = 0;
const EINVALID_HASH: u64 = 1;
const EINVALID_MAGIC: u64 = 2;
const EINVALID_SEED: u64 = 3;
const EINVALID_SCORE: u64 = 4;
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,
github_id: String,
success: bool,
rank: u64,
}
fun init(ctx: &mut TxContext) {
let secret = b"Letsmovectf_week1";
let secret_hash = sha3_256(secret);
let challenge = Challenge {
id: object::new(ctx),
secret: string::utf8(secret),
current_score: 0,
round_hash: secret_hash,
finish: 0
};
share_object(challenge);
}
#[allow(lint(public_random))]
public entry fun get_flag(
score: u64,
guess: vector<u8>,
hash_input: vector<u8>,
github_id: String,
magic_number: u64,
seed: u64,
challenge: &mut Challenge,
rand: &Random,
ctx: &mut TxContext
) {
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));
assert!(score == expected_score, EINVALID_SCORE);
challenge.current_score = score;
let mut guess_data = guess;
vector::append(&mut guess_data, *string::as_bytes(&challenge.secret));
let random = sha3_256(guess_data);
let prefix_length = 2;
assert!(compare_hash_prefix(&random, &challenge.round_hash, prefix_length), 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);
challenge.secret = getRandomString(rand, ctx);
challenge.round_hash = sha3_256(*string::as_bytes(&challenge.secret));
challenge.current_score = 0;
challenge.finish = challenge.finish + 1;
event::emit(FlagEvent {
sender: tx_context::sender(ctx),
flag: string::utf8(b"CTF{Letsmovectf_week1}"),
github_id: string::utf8(b"a83d43dd-1a0c-4159-ab1c-b9de4a2587ec"),
success: true,
rank: challenge.finish
});
}
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, 32);
let mut rand_vec: vector<u8> = b"";
while (str_len != 0) {
let rand_num = random::generate_u8_in_range(&mut gen, 34, 126);
vector::push_back(&mut rand_vec, rand_num);
str_len = str_len - 1;
};
string::utf8(rand_vec)
}
fun compare_hash_prefix(hash1: &vector<u8>, hash2: &vector<u8>, n: u64): bool {
if (vector::length(hash1) < n || vector::length(hash2) < n) {
return false
};
let mut i = 0;
while (i < n) {
if (*vector::borrow(hash1, i) != *vector::borrow(hash2, i)) {
return false
};
i = i + 1;
};
true
}
}
发布到链上,可以发现传入八个参数进行交互,拿到结果
在终端的交互命令格式
sui client call \
--package <PACKAGE_ID> \
--module challenge \
--function get_flag \
--args \
\ # 参数 1(u64)
"" \ # 参数 2(vector<u8>)
“” \ # 参数 3(vector<u8>)
<github_id> \ # 参数 4(String)
"" \ # 参数 5(u64)
"" \ # 参数 6(u64)
<challenge_id> \ # 参数 7(Challenge 对象)
0x8 \ # 参数 8(Random 对象)
--gas-budget 1000000 \
根据在move语言里面对参数的加密形式(在get_flag里面),对其进行解密。 <!--EndFragment-->
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!