HKCERT24 Rev bashed 和 MBTI Radar WP
字数 1333 2025-08-20 18:17:48

HKCERT24逆向题目解析:bashed与MBTI Radar

bashed题目解析

题目概述

  • 提供一个名为❤️.sh的bash脚本文件
  • 脚本接受一个87字符长度的flag作为参数
  • 使用大量emoji进行数据处理和流程控制
  • 最终检查标志位GALF是否为0来验证flag

Bash关键特性分析

特性一:不严格的函数定义

  • Bash中变量和函数可以同名,函数优先执行
  • 当函数名作为参数传递时,会被当作字符串处理
  • 题目中emoji同时作为函数名和参数使用

特性二:动态更新与执行顺序

  • 脚本使用wget动态更新自身内容
  • Bash执行时会一次性读入脚本内容到内存
  • 行末的\会影响PC(程序计数器)的移动规则:
    • 执行完带\的行后,会跳过后续连续带\的行
    • 动态修改后,以新文件内容重新判断\的影响

特性三:整数溢出

  • Bash使用64位整数运算
  • 连续乘法会导致高位溢出,最终可能得到0
  • 题目利用此特性进行最终验证

题目逻辑解析

  1. emoji_table结构

    • 256行emoji_line组成
    • 每行第一个emoji定义函数,其余为参数
    • 共88个不同的emoji_table文件
  2. 执行流程

    • emoji_line[0]函数将emoji_line[1:8]重排序
    • 检查flag子串的sha1值(emoji_line[1:3])
    • 根据检查结果:
      • 成功:GALF *= emoji_line[6],跳转emoji_line[4]
      • 失败:GALF *= emoji_line[7],跳转emoji_line[5]
    • 行号idx根据\规则递增
  3. 算法模型

    • 88张emoji_table,每张256行
    • 根据flag子串sha1值决定跳转路径
    • 最终要求GALF溢出为0

解题步骤

1. 深度遍历搜索

def calc_next_idx(emoji_filename, idx):
    table = g_emoji_table[emoji_filename]
    line = table[idx]
    while line[-1] == "\\":
        idx += 1
        line = table[idx]
    return idx + 1

def search_correct(emoji_filename, emoji_line, GALF, idx):
    start = ord(emoji_line[0]) - ord('ear') 
    length = ord(emoji_line[1]) - ord('ear')
    c_1 = hex(ord(emoji_line[2]) - ord('ear')[2:]
    
    if GALF*ord(emoji_line[5]) & 0xffffffffffffffff != 0 and len(c_1) == 1:
        GALF *= ord(emoji_line[5])
        GALF &= 0xffffffffffffffff
        target = emoji_line[3]
        idx = calc_next_idx(emoji_filename, idx)
        if len(g_emoji_table[target]) < idx or idx >= 256:
            return True
        new_line = g_emoji_table[target][idx]
        g_result[idx]=(start, start+length, True, c_1)
        new_line = mapping_emojis(new_line[0], new_line, g_emoji_mapping)
        search_correct(target, new_line, GALF, idx)
    
    if GALF*ord(emoji_line[6]) & 0xffffffffffffffff != 0:
        target = emoji_line[4]
        GALF *= ord(emoji_line[6])
        GALF &= 0xffffffffffffffff
        idx = calc_next_idx(emoji_filename, idx)
        if len(g_emoji_table[target]) < idx or idx >= 256:
            return True
        new_line = g_emoji_table[target][idx]
        g_result[idx]=(start, start+length, False, c_1)
        new_line = mapping_emojis(new_line[0], new_line, g_emoji_mapping)
        search_correct(target, new_line, GALF, idx)

2. 回溯搜索flag

from hashlib import sha1

def get_sha1_second_char(s):
    return sha1(s.encode()).hexdigest()[1]

def backtrack(current_string, n, constraints, index_constraints):
    if len(current_string) == n:
        return current_string

    for c in "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_{}":
        current_string += c
        valid = True
        for (start, end, target_char) in index_constraints.get(len(current_string), []):
            substring = current_string[start:end]
            if get_sha1_second_char(substring) != target_char:
                valid = False
                break

        if valid:
            result = backtrack(current_string, n, constraints, index_constraints)
            if result:
                return result
        current_string = current_string[:-1]

    return None

MBTI Radar题目解析

题目概述

  • Unity游戏程序,使用IL2CPP编译
  • 输入1-6字符的名字,生成MBTI类型序列
  • 需要预测随机数生成结果匹配目标序列

关键逻辑分析

  1. 初始化阶段

    • 输入字符映射到0123456789abcdefghijklmnopqrstuvwxyz的下标
    • 转换为36进制整数作为随机数种子
  2. 随机数生成

    • 使用类似MT算法的伪随机数生成器
    • 生成浮点数范围在0-1之间
    • 乘以201后映射到MBTI类型
  3. 验证逻辑

    • 共6个阶段,输入长度1-6的字符
    • 生成的MBTI序列与目标比较
    • 完全匹配则记录flag部分

解题步骤

1. 实现随机数生成器

class MyRandom(object):
    def __init__(self):
        self.random_num = [0] * 8
        self.table = "0123456789abcdefghijklmnopqrstuvwxyz"

    def random_seed(self, seed):
        self.random_num[0] = seed
        for i in range(1,4,1):
            self.random_num[i] = (self.random_num[i-1] * 0x6C078965 + 1)&0xffffffff

    def get_random_seed(self):
        v1 = self.random_num[0] ^ ((self.random_num[0] << 11)&0xffffffff)
        self.random_num[0] = self.random_num[1]
        self.random_num[1] = self.random_num[2]
        v2 = self.random_num[3]
        self.random_num[2] = self.random_num[3]
        self.random_num[3] = v1 ^ v2 ^ ((v1 ^ (v2 >> 11)) >> 8)
        n = (self.random_num[3] & 0x7FFFFF)
        return n * 0.0000001192093

2. MBTI类型映射

def get_ans(n):
    if n < 54.0:
        if n < 33.0:
            if n < 12.0:
                StrTagObj = "INFJ"
                if n >=3.0: StrTagObj = "INFP"
            else:
                StrTagObj = "ENFP"
                if n >= 28.0: StrTagObj = "ENFJ"
        elif n <44.0:
            StrTagObj = "INTJ"
            if n >= 37.0: StrTagObj = "INTP"
        else:
            StrTagObj = "ENTP"
            if n >= 50.0: StrTagObj = "ENTJ"
    elif n <147.0:
        if n <105.0:
            StrTagObj = "ISTJ"
            if n > 77.0: StrTagObj = "ISFJ"
        else:
            StrTagObj = "ESTJ"
            if n >= 122.0: StrTagObj = "ESFJ"
    elif n < 176.0:
        StrTagObj = "ISTP"
        if n >= 158.0: StrTagObj = "ISFP"
    else:
        StrTagObj = "ESTP"
        if n > 184.0: StrTagObj = "ESFP"
    return StrTagObj

3. 爆破搜索

stage = 5
target = mbti[stage].split(' ')

for seed in range(36**stage,36**(stage+1)):
    mr = MyRandom()
    mr.random_seed(seed)
    res = []
    for i in range(50):
        n = mr.get_random_seed()
        each_mbti = get_ans(n*201.0)
        if each_mbti != target[i]: break
        res.append(each_mbti)
    if len(res) == 50:
        ans = ''
        while seed > 0:
            ans = mr.table[seed % 36] + ans
            seed //= 36
        print(ans)
        exit(0)

总结与技巧

bashed题目关键点

  1. 理解bash中函数和变量的同名机制
  2. 掌握动态脚本修改对执行流程的影响
  3. 利用整数溢出特性进行最终验证
  4. 将复杂bash逻辑转化为可搜索的算法模型

MBTI Radar题目关键点

  1. 识别IL2CPP编译的Unity程序结构
  2. 分析随机数生成算法并实现等效版本
  3. 理解种子生成机制(36进制转换)
  4. 使用爆破方法搜索符合条件的输入

通用逆向技巧

  1. 对于混淆代码,编写小型测试程序验证猜测
  2. 动态调试与静态分析结合
  3. 将复杂逻辑分解为可管理的部分
  4. 注意数据类型的转换和边界条件
HKCERT24逆向题目解析:bashed与MBTI Radar bashed题目解析 题目概述 提供一个名为❤️.sh的bash脚本文件 脚本接受一个87字符长度的flag作为参数 使用大量emoji进行数据处理和流程控制 最终检查标志位GALF是否为0来验证flag Bash关键特性分析 特性一:不严格的函数定义 Bash中变量和函数可以同名,函数优先执行 当函数名作为参数传递时,会被当作字符串处理 题目中emoji同时作为函数名和参数使用 特性二:动态更新与执行顺序 脚本使用wget动态更新自身内容 Bash执行时会一次性读入脚本内容到内存 行末的 \ 会影响PC(程序计数器)的移动规则: 执行完带 \ 的行后,会跳过后续连续带 \ 的行 动态修改后,以新文件内容重新判断 \ 的影响 特性三:整数溢出 Bash使用64位整数运算 连续乘法会导致高位溢出,最终可能得到0 题目利用此特性进行最终验证 题目逻辑解析 emoji_ table结构 : 256行emoji_ line组成 每行第一个emoji定义函数,其余为参数 共88个不同的emoji_ table文件 执行流程 : emoji_ line[ 0]函数将emoji_ line[ 1:8 ]重排序 检查flag子串的sha1值(emoji_ line[ 1:3 ]) 根据检查结果: 成功:GALF * = emoji_ line[ 6],跳转emoji_ line[ 4 ] 失败:GALF * = emoji_ line[ 7],跳转emoji_ line[ 5 ] 行号idx根据 \ 规则递增 算法模型 : 88张emoji_ table,每张256行 根据flag子串sha1值决定跳转路径 最终要求GALF溢出为0 解题步骤 1. 深度遍历搜索 2. 回溯搜索flag MBTI Radar题目解析 题目概述 Unity游戏程序,使用IL2CPP编译 输入1-6字符的名字,生成MBTI类型序列 需要预测随机数生成结果匹配目标序列 关键逻辑分析 初始化阶段 : 输入字符映射到 0123456789abcdefghijklmnopqrstuvwxyz 的下标 转换为36进制整数作为随机数种子 随机数生成 : 使用类似MT算法的伪随机数生成器 生成浮点数范围在0-1之间 乘以201后映射到MBTI类型 验证逻辑 : 共6个阶段,输入长度1-6的字符 生成的MBTI序列与目标比较 完全匹配则记录flag部分 解题步骤 1. 实现随机数生成器 2. MBTI类型映射 3. 爆破搜索 总结与技巧 bashed题目关键点 理解bash中函数和变量的同名机制 掌握动态脚本修改对执行流程的影响 利用整数溢出特性进行最终验证 将复杂bash逻辑转化为可搜索的算法模型 MBTI Radar题目关键点 识别IL2CPP编译的Unity程序结构 分析随机数生成算法并实现等效版本 理解种子生成机制(36进制转换) 使用爆破方法搜索符合条件的输入 通用逆向技巧 对于混淆代码,编写小型测试程序验证猜测 动态调试与静态分析结合 将复杂逻辑分解为可管理的部分 注意数据类型的转换和边界条件