吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 532|回复: 4
收起左侧

[CTF] 论坛2025春节红包web简略writeup

[复制链接]
苏紫方璇 发表于 2025-2-13 00:08
本帖最后由 苏紫方璇 于 2025-2-13 00:08 编辑

flag11

flag11是一个抽奖,抽奖的算法在题目中已经给出,所以可以使用python写一个计算脚本。通过获取blockHash,计算出特定的中奖号码和抽奖人数

import requests
import json

while True:
    # 手动输入blockNumber
    block_number = input("请输入 blockNumber: ")
    if block_number == "q":
        break
    user_count_threshold = int(input("请输入 threshold: "))
    # 获取blockHash
    url_block = 'https://api.upowerchain.com/apis/v1alpha1/block/get'
    headers = {'Content-type': 'application/json'}
    data_block = f'{{"number":"{block_number}"}}'

    # 请求获取blockHash
    response = requests.post(url_block, headers=headers, data=data_block, verify=False)

    # 如果返回的 JSON 有 data 和 blockHash 字段,继续执行
    try:
        block_hash = response.json()['data']['blockHash']
        # 输出获取到的blockNumber和blockHash
        print(f"获取的 blockNumber: {block_number}")
        print(f"获取的 blockHash: {block_hash}")
        found = 0  # 找到的结果计数器
        # 转换blockHash为整数(去掉前缀 '0x')
        block_hash_int = int(block_hash, 16)

        # 计算当userCount为不同值时,userIndex > 9980的条件
        #user_count_threshold = 9980
        user_count = 10000  # 初始userCount值,可以调整来查找最小值
        found = 0  # 找到的结果计数器

        # 修改循环条件为找到3个结果
        while found < 3:
            user_index = block_hash_int % user_count
            if user_index > user_count_threshold:
                print(f"找到第{found+1}个解:当 userCount = {user_count} 时,userIndex = {user_index} > {user_count_threshold}")
                found += 1
            user_count += 1
    except KeyError:
        print("未能正确获取 blockHash,检查 blockNumber 是否有效")
    except requests.exceptions.RequestException as e:
        print(f"请求错误: {e}")

然后再将网页修改一下,添加一个批量提交的按钮,输入中奖号码和总人数,程序会将自动提交,非中奖号码时在uid前补0。提交时就需要一些运气了,毕竟都在提交,会干扰。所以尽量卡在0时提交完毕,或者少提交几个。

Screenshot_20250211041300.jpg

<div class="join">
        <p>免费抽奖!绝对公平公正!</p>
        <p>抽奖奖品:一个 flag</p>
        <p class="timer"></p>
        <p>
            UID: <input type="text" name="uid">
            <button type="submit">参加抽奖</button>
        </p>

        <!-- 新增自动填充区域 -->
        <hr>
        <h2>自动填充抽奖入口(批量提交)</h2>
        <p>
            目标总参与数 (包含9980个机器人):<br>
            <input type="number" id="usercount" placeholder="输入总参与数"><br><br>
            命中序号 (当参与序号等于此数时使用固定 uid):<br>
            <input type="number" id="winningIndex" placeholder="输入命中序号"><br><br>
            <button id="autoSubmitButton">开始自动提交</button>
        </p>
    </div>

        /*********************
         * 自动批量提交逻辑 *
         *********************/
                 let joinCount = 1;
    let lastJoinIndex = 0;
    let timestamp;
    let lastTimestampUpdate = Math.floor(Date.now() / 1000);  // 初始化上次更新时间戳
    let lastVerifyCode = '';  // 存储上一次的验证码

    // 生成符合范围 [1, 2500000) 的随机 UID(必须是字符串)
    function randomUID() {
        return "0".repeat(joinCount) + "212618"; // 非中奖时前面补 0
    }

    /**
     * 获取当前时间戳(每60秒生成一个新的时间戳)
     */
    function getTimestamp() {
        const currentTimestamp = Math.floor(Date.now() / 1000);
        if (currentTimestamp - lastTimestampUpdate >= 60) {
            // 如果当前时间与最后更新时间差超过 60 秒,则更新 timestamp
            lastTimestampUpdate = currentTimestamp;
            timestamp = currentTimestamp;
            // 更新时重新计算验证码
            lastVerifyCode = getVerifyCode(`${timestamp}|`);
        }
        return timestamp;
    }

    /**
     * submitJoin 自动提交 UID:
     *   - 中奖序号时 UID 固定为 "212618"
     *   - 其他情况 UID 在 [1, 2500000) 之间随机
     */
    function submitJoin(targetUserCount, targetWinningIndex) {
        const expectedJoinIndex = lastJoinIndex + 1;
        let uidToSubmit = (expectedJoinIndex === targetWinningIndex) ? "212618" : randomUID();

        // 获取当前的时间戳(如果需要更新时间戳,则重新计算验证码)
        const reqTimestamp = getTimestamp();
        const req = {
            timestamp: reqTimestamp,
            uid: uidToSubmit,  // 确保 UID 是字符串
            verify_code: lastVerifyCode  // 使用上次计算的验证码
        };

        fetch('/api/lottery/join', {
            method: 'POST',
            headers: { 'Content-Type': 'application/json' },
            body: JSON.stringify(req),
        })
        .then(res => res.json())
        .then(res => {
            if (res.code === 0) {
                lastJoinIndex = res.data.user_index;
                console.log(`参与成功:序号 #${lastJoinIndex}, UID: ${uidToSubmit}`);
                                if(uidToSubmit=="212618")
                                        alert("已提交uid,等待后续提交");
                joinCount++;
                // 判断是否达到目标总参与数
                if (lastJoinIndex < targetUserCount) {
                    setTimeout(() => submitJoin(targetUserCount, targetWinningIndex), 100);  // 100ms 延时
                } else {
                    alert("所有提交完成,已达到目标总参与数:" + targetUserCount);
                }
            } else {
                alert("提交失败:" + res.msg);
            }
        })
        .catch(err => console.error(err));
    }

    // 绑定自动提交按钮事件
    document.getElementById('autoSubmitButton').addEventListener('click', function(){
        const targetUserCount = parseInt(document.getElementById('usercount').value);
        const targetWinningIndex = parseInt(document.getElementById('winningIndex').value);

        if (isNaN(targetUserCount) || isNaN(targetWinningIndex)) {
            alert("请输入有效的数字!");
            return;
        }

        // 重置全局变量
        lastJoinIndex = 0;
        timestamp = Math.floor(Date.now() / 1000);  // 初始化时间戳
        lastTimestampUpdate = timestamp;  // 初始化时间戳更新时间
        lastVerifyCode = getVerifyCode(`${timestamp}|`);  // 初次计算验证码

        // 开始自动提交
        submitJoin(targetUserCount, targetWinningIndex);
    });

flag10

flag10的内容在抽奖页的源代码中有提示,具体的函数时在wasm中导出,calc_flag10_uid_timestamp_resultbufptr_resultbuflen_return_resultlen函数名写的十分清晰,所以直接写一个调用就可以了

WebAssembly.instantiateStreaming(fetch('get_verify_code.wasm'))
  .then(({ instance }) => {
    const exports = instance.exports;
    const memory = new Uint8Array(exports.memory.buffer);
    const calcFlag10 = exports.calc_flag10_uid_timestamp_resultbufptr_resultbuflen_return_resultlen;

    // 分配缓冲区(避开WASM内部使用的地址0-15)
    const bufferPtr = 16; // 起始地址
    const bufferSize = 64; // 缓冲区大小
    const resultBuffer = new Uint8Array(memory.buffer, bufferPtr, bufferSize);

    // 设置输入参数
    const uid = 212618;
    const timestamp = 1738934615;

    // 调用函数
    const resultLen = calcFlag10(uid, timestamp, bufferPtr, bufferSize);

    // 解码结果
    const flag10 = new TextDecoder().decode(resultBuffer.subarray(0, resultLen));
    console.log("flag10:", flag10);
  });

flag9

题目说需要用到ai和web,既然10-11是web了,那么这题一定是ai,猜想是从ai口中套出flag9。
不过在对话之前,需要将验证码计算函数替换掉,抽奖页面会告诉你这个 getVerifyCode 的 wasm 实现比 blueimp-md5 js 实现快 20 倍。
可以直接在控制台输入抽奖页面那段调用wasm的代码来重载,然后就可以开始对话啦。

WebAssembly.instantiateStreaming(fetch('get_verify_code.wasm')).then(({instance}) => {
            window.getVerifyCode = (prefix) => {
                console.log('prefix:', prefix);
                const startTime = Date.now();
                const memory = new Uint8Array(instance.exports.memory.buffer);
                const prefixBufPtr = 16;
                const prefixBufLen = ((new TextEncoder()).encodeInto(prefix, memory.subarray(prefixBufPtr))).written;
                const resultBufPtr = 0;
                const resultBufLen = 16;
                const resultLen = instance.exports.get_verify_code(prefixBufPtr, prefixBufLen, resultBufPtr, resultBufLen);
                const code = (new TextDecoder()).decode(memory.subarray(resultBufPtr, resultBufPtr + resultLen));
                console.log(`solved: ${prefix + code} ${(Date.now() - startTime) / 1000}s`);
                return code;
            };
        });

我也是试了好多,最后使用这两句获得了flag
Screenshot_20250210230614.jpg
Screenshot_20250210230649.jpg

免费评分

参与人数 1热心值 +1 收起 理由
浮尘晓梦 + 1 谢谢@Thanks!

查看全部评分

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

呱呱生 发表于 2025-2-13 03:44
非常好啊啊啊
李亲顾 发表于 2025-2-13 07:05
正己 发表于 2025-2-13 15:53
Ganlv 发表于 2025-2-14 12:50
本帖最后由 Ganlv 于 2025-2-14 12:52 编辑
正己 发表于 2025-2-13 15:53
笑死,相比之下,大模型傻得可爱

感觉骗大模型把密码告诉自己,就像坏人骗小孩开门一样。
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2025-4-9 23:50

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表