HOH共学-week1

  • Muet-X
  • 发布于 1天前
  • 阅读 48

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&lt;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&lt;u8>,
        hash_input: vector&lt;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) &lt;&lt; 24) |
            ((*vector::borrow(&secret_hash, 1) as u64) &lt;&lt; 16) |
            ((*vector::borrow(&secret_hash, 2) as u64) &lt;&lt; 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&lt;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&lt;u8>, hash2: &vector&lt;u8>, n: u64): bool {
        if (vector::length(hash1) &lt; n || vector::length(hash2) &lt; n) {
            return false
        };
        let mut i = 0;
        while (i &lt; n) {
            if (*vector::borrow(hash1, i) != *vector::borrow(hash2, i)) {
                return false
            };
            i = i + 1;
        };
        true
    }
}

发布到链上,可以发现传入八个参数进行交互,拿到结果

image.png 在终端的交互命令格式

sui client call \
  --package &lt;PACKAGE_ID> \
  --module challenge \
  --function get_flag \
  --args \
     \          # 参数 1(u64)
    "" \       # 参数 2(vector&lt;u8>)
    “”    \     # 参数 3(vector&lt;u8>)
    &lt;github_id> \      # 参数 4(String)
    "" \   # 参数 5(u64)
    "" \           # 参数 6(u64)
    &lt;challenge_id> \   # 参数 7(Challenge 对象)
     0x8 \      # 参数 8(Random 对象)
  --gas-budget 1000000 \

根据在move语言里面对参数的加密形式(在get_flag里面),对其进行解密。 <!--EndFragment-->

  • 原创
  • 学分: 2
  • 分类: Sui
  • 标签:
点赞 0
收藏 0
分享
本文参与登链社区写作激励计划 ,好文好收益,欢迎正在阅读的你也加入。

0 条评论

请先 登录 后评论
Muet-X
Muet-X
0xb4e3...31Fb
江湖只有他的大名,没有他的介绍。