WHUCTF2026
PWN
使用gpt-plus codex gpt-5.4中等推理 辅助解题
无能的pwn手
题目提示
提示如下:
部署服务的文件夹下只有pwn、libc.so.6和flag文件三个文件,注意,flag文件的文件名不是flag
如果卡住了,你的队友或许能给你提供帮助
本题容器为web服务。首次访问时卡顿或无响应大概率是网络问题,尝试多次刷新即可解决。后续测试中如果打崩程序或异常无响应、拒绝连接,则需要重启容器。
解题过程
先连接上尝试直接getflag
~ nc 127.0.0.1 37359 INT took 19s |
似乎使用HTTP头
于是发送GET / HTTP/1.1\r\nHost: localhost\r\n\r\n
得到
HTTP/1.1 200 OK |
给了提示
于是尝试/flag和/pwn,被禁止了,于是尝试绕过,flag文件名不确定,于是尝试绕过pwn,使用./pwn成功得到pwn附件,接受字节写入文件中
from pwn import * |
ai一把梭
> 查看wsl中home的WHUCTF2026的dump.elf告诉我如何getflag |
照抄payload后直接getshell
然后查找flag文件
find / -type f 2>/dev/null | grep -viE '/proc|/sys|/dev' | grep -i 'flag' |
然后cat对应文件就行了
ZombieSurvival Server
题目提示
本题难点在于协议还原,但是因为给出了附件,所以基本没有难点
ret2win
关注 IL2CPP 字符串对象的布局,尤其是长度字段和字符区
意味着ai很适合梭
过程
> 分析assembly_csharp |
修改脚本后
#!/usr/bin/env python3 |
ZombieSurvival Server Hard
同样接着上面的ZombieSurvival Server的对话,一样交给ai分析,看看有什么不同
> 现在安全防护升级了,这是一个新文件,再次尝试,提示: |
实际上不可打通,发现是canary格串偏移错位了
随便连了一个2.35-0ubuntu3_amd,gdb进去调试计算出canary泄露的格串偏移,即可完成
LEAK_FMT = b'%15$p|%37$p'->LEAK_FMT = b'%43$p|%37$p'
#!/usr/bin/env python3 |
ezProtobuf
先ai逆向分析
> 阅读/chall文件夹的/chall,这是一个photobuf的pwn题,帮我分析思路 |
让ai建立交互脚本
> 帮我生成这题的Python protobuf 类\\wsl.localhost\Ubuntu\home\ubuntu\WHUCTF2026\chall |
生成了文件,先是chall_pb2.py
# -*- coding: utf-8 -*- |
和chall.proto
syntax = "proto3"; |
文件目录
~/WHUCTF2026/chall tree |
接着和ai交互
> 快速写出框架,我自己修改和调试先 |
一开始打算打__exit_funcs但是好像拿不到pointer_guard,于是尝试打exit->IO链+setcontext
先add一个大堆块再free再show得到libc地址,先add一个小堆块再free再show得到heap地址,可以顺带做tcache_posion于是先add两个相同大小的小堆块再free其中一个再show得到heap地址,再delete另一个然后edit这个堆块的fd指针(Safe Linking),修改到_IO_list_all,申请两个堆块出来,得到的第二个堆块就是_IO_list_all,在里面写入一个受控的堆地址,然后在这个受控的堆地址中伪造虚假的FILE结构体实现setcontext+orw,但是似乎出现了问题,在没到_IO_cleanup时就崩了,于是从头到尾调试一次,结果在一个堆块中发现了栈地址,于是可以tcache分配到栈上进行orw
先add堆块进行show得到栈地址,然后下面的大同小异,将tcache->fd控制为当前栈帧的rbp上,得到栈上的堆后就可以写orw的rop了
脚本如下
#!/usr/bin/env python3 |
效果如下
~/WHUCTF2026/chall python3 exp.py P |
即可拿到flag
login
提示
login 时候的 auth_cache 是全局共享的
设置 session 时候似乎没有用 auth_cache 中的 user?
了解一下 pthread 库和线程、条件竞争相关内容
登录过的用户是会保存在 session 数组的。分析一下选项8的作用
过程
ai逆向
> 分析/login文件夹的pwn程序漏洞 |
是一道竞争题目,那么先注册一个用户,然后向服务器不断发送两个不同登录信号,一个是admin,另一个是我们注册的用户,密码都使用我们注册的用户密码
def race(p): |
重复0x20次尝试后发现中间确实可以登录到admin,这是因为在admin登录时并发的aaa登录校验把aaa密码写进了auth全局变量里,这样admin的密码被认为是auth全局变量中的aaa,校验是就有了f(aaa)=f(aaa),校验通过就登陆到了admin
一开始是不知道如何准确停下,考虑到recv会影响交互速度,影响竞争,题目提示发现可以通过session_switch登录上已经登录过的用户
于是尝试本地果然可以稳定得到admin,然而发现远程交互的速度远远慢于本地交互速度,本地瞬间出现结果然而远程得登上半分钟,竞争是肯定没有办法的,于是删去所有的p.recvuntil然后写入一个函数中,每一次竞争后都加入一次数据接收,查看是否成功登录,这样远程交互更加快速和稳定,果然远程交互速度得到极大地加快,并且可以得到admin登录
登录到admin后,就可以使用负索引漏洞,users的负索引可以修改_IO_2_1_stdout_的内容
先修改_IO_2_1_stdout_泄露libc,将_flags位修改为0xfbad1800,将_IO_write_base末尾字节修改为\x00,中间的变量_IO_read_ptr _IO_read_end _IO_read_base直接填充为0
p64(0xfbad1800)+p64(0)*3+'\x00' |
后续程序在调用puts函数时,就会泄露出存在libc中的地址,找到对应的偏移就能得到libc基址
再次修改_IO_2_1_stdout_的内容,使用house of apple2的板子就行了
脚本如下
#!/usr/bin/env python3 |
效果如下
~/WHUCTF2026/login python3 exp.py P |
vmpp
提示
std::cin 在向定长缓冲区输入时是可溢出的 |
过程
ai逆向
整体流程 |
先通过退出的cin溢出覆盖到std::function
查询std::function内存布局
这很像 GCC 的 libstdc++ 里 std::function<void()> 的典型布局: |
发现需要控制invoker指针,指向main函数返回重新构建一个VM结构,此时因为已经update了,updatefunc不会再次调用
只有旧版的func可以使用syscall,没有沙箱可以直接调用execve(0x3b)
需要reg[0]=0x3b,reg[1]=addr->/bin/sh,reg[2]=reg[3]=0
调试时发现push 0x3b再pop reg会变成0x3b00000000000000,那么“/bin/sh”要变成“00hs/nib/”,之类的,再让字符串地址对齐,尝试垫些指令,发现add刚好可以,于是先add在push “00hs/nib/”,而vm_data_load可以支持负索引data进入reg,那么意味着可以使用VM的std::function的_Any_data中指向堆的残留地址,这样就可以让一个堆地址进入reg,而我们的字符串就是在堆上,通过偏移计算修改地址指向“/bin/sh”字符串,xor多余reg数据然后syscall即可完成利用
exp.py如下
#!/usr/bin/env python3 |
效果如下
~/WHUCTF2026/vmpp python3 exp.py P |
MISC
跑路
过程
将题目描述和提示加上配置文件和对应网页内容发给ai
注册登录后尝试各种命令
发现
/sendcmdtoserver server1 op <你的名字> |
成功得到管理员权限,然后直接getflag
附件
ai对话如下
我先把题面里能落地的点串起来:这是个 BungeeCord 反代 + Spigot 后端 的 MC 服,配置基本默认,且明确点名 CommandBridge、MQEasy,再给了 commandbridge.bukkit.send = TRUE。这已经很像“跨服指令桥默认配错,能被普通玩家借道打到后端控制命令”的链子了。已经定位到插件源头了:CommandBridge 的官方说明就是“把 Spigot 里的命令发到 BungeeCord,或者 Bungee 发到 Spigot,甚至 Spigot 发到 Spigot”。题目那句“有没有可利用的插件”基本就是在点它。已思考 1m 35s这题的核心不是“服务器炸了”,而是: |









