paluctf wp

记录一些不会的或者比赛会用到的

Misc

FM 145.8

参考这篇博客

SSTV
慢扫描电视(Slow-scan television 简称 SSTV)是业余无线电爱好者的一种主要图片传输方法,慢扫描电视通过无线电传输和接收单色或彩色静态图片。

表示这玩意真的出烂了,傻瓜式操作

使用工具:MMSSTV,e2eSoft
文件类型:wav
工具上就完了

e2esoft (VSC)是一个虚拟声卡工具,理解一下简单说就是选择一下输入输出设备让他转换一下

首先将声音输出到虚拟声卡

然后在电脑的音频输出的地方选择

然后直接 MMSSTV 播放就可以出 flag 了

公式化做题

为什么我的新猫猫吃不饱

打开有一张图片 (png),一张 gif
首先这里用 010 看 gif

看见一个很像 flag 的内容,注意不要把 HHT5 带进去了,flag 不包含这部分,然后随波逐流一把梭

flag{my_ca1_
然后来看另外一张图片 png 左边有一条竖的线,要么是 lsb,要么是盲水印
这里我把 gif 切割为一帧一帧(puzzlesolver 工具或者 conver 1. gif 1. png 都可以)
发现第 22 张图片很像
puzzlesolver


(不知道为什么复现变成这样了,之前和官方出题人那个很像)
flag{my_ca1_1s_Fu11}

350x350

比较简单,但是比较套,前面就不停的 binwalk 分析,binwalk -e 切割(或者 foremost 切割),多试一试几条命令,换几个平台,因为总有 bug
讲讲最后拿到只剩下两张图片

这里也可以看到我试了很多次
最后的最后,会用到下面这个项目

https://github.com/guofei9987/blind_watermark?tab=readme-ov-file
这个项目中水印可以是三种东西,文字、图片和二进制数据(其实你想,可以变成很多种东西)

这里的 3. png 是原图,33. png 是带水印的图

1
2
3
4
5
from blind_watermark import WaterMark

bwm1 = WaterMark(password_wm=1, password_img=1)
# notice that wm_shape is necessary
bwm1.extract(filename='33.png', wm_shape=(350, 350), out_wm_name='extracted33.png', )

会导出一张二维码,扫描二维码得到数据

flag{b3bd61023d129f9e39b4a26b98c0f366}

ez_misc

binwalk 切割出一个图片,010 打开最后有一个很明显的编码要么是零宽隐写要么是snow

snow 隐写内容

这里只需要将提取内容拿出来然后保存为 1. txt,然后直接用工具解出就行

1
snow -C 1.txt


Carefree and carefree
应该是压缩包密码
但是我这里还有伪加密

压缩源文件数据区+压缩源文件目录区+压缩源文件目录结束标志
压缩源文件数据区
50 4B 03 04:这是头文件标记(0x04034b50)
14 00:解压文件所需 pkware 版本
00 00:全局方式位标记(有无加密)
08 00:压缩方式
5A 7E:最后修改文件时间
F7 46:最后修改文件日期
16 B5 80 14:CRC-32校验(1480B516)
19 00 00 00:压缩后尺寸(25)
17 00 00 00:未压缩尺寸(23)
07 00:文件名长度
00 00:扩展记录长度

压缩源文件目录区
50 4B 01 02:目录中文件文件头标记(0x02014b50)
3F 00:压缩使用的 pkware 版本
14 00:解压文件所需 pkware 版本
00 00:全局方式位标记(有无加密,这个更改这里进行伪加密,改为09 00打开就会提示有密码了)
08 00:压缩方式
5A 7E:最后修改文件时间
F7 46:最后修改文件日期
16 B5 80 14:CRC-32校验(1480B516)
19 00 00 00:压缩后尺寸(25)
17 00 00 00:未压缩尺寸(23)
07 00:文件名长度
24 00:扩展字段长度
00 00:文件注释长度
00 00:磁盘开始号
00 00:内部文件属性
20 00 00 00:外部文件属性
00 00 00 00:局部头部偏移量

压缩源文件目录结束标志
50 4B 05 06:目录结束标记
00 00:当前磁盘编号
00 00:目录区开始磁盘编号
01 00:本磁盘上纪录总数
01 00:目录区中纪录总数
59 00 00 00:目录区尺寸大小
3E 00 00 00:目录区对第一张磁盘的偏移量
00 00:ZIP 文件注释长度

简单来说就是一个压缩包肯定会有上面的内容,伪加密就是本来这个 zip 没有压缩,但是我修改了标志位,然后计算机就以为它压缩了,我们只需要把这些标志位修改为 00 00

这道题目这里是压缩源文件目录区(可以根据文件头标志匹配)

这里的全局方式位标记为 09 00,修改为 00 00 即可
解压之后使用上面的密码即可拿到flag

flag{b220116fc6ca827ecf3cb6c6c06dac26}

Re

Pylu

pyinstxtractor 解包
pycdc 反编译出来
然后发现竟然是个密码题

尝试用 z3 爆破
但是觉得可能性不大,所以只爆了 1min 就结束了
赛后看 wp,就是用 z3 爆破的,可恶

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
import z3
from Crypto.Util.number import *

def enc(key):
    R = bytes_to_long(b"Welcome To PaluCTF!")
    MOD = 2**418
    R = R ^ (R - 60) >> 24
    R = R ^ (R - 60) << 88

    R ^= key
    R = (-R * R * 2024) % MOD  
    R = (R * key) % MOD
    return R

cor = 0x2E441F765514CCA89173554726494D37E9FBE774B6F807BC5F6E71117530CE3D7DB5F70554C03CD9055F4E42969600904DF1F4DB8
s = z3.Solver()
key = z3.BitVec("key", 418)
s.add(enc(key)==cor)
s.check()
m = s.model()
flag = long_to_bytes(m[key].as_long())
print(flag)

判断是 chacha2.0

然后简单看看 enc 和 key

1
2
3
4
enc = "f568c48912eed6dc520c7164f44b6378e1d0d3e248914fa8847b405a131f"
key = "SGludDogSW1wcm92ZSBvZiBTYWxzYTIw"

"Is_This_TEA?"

动调过程中发现去掉了最后四字节
借鉴脚本

1
2
3
4
5
6
7
8
9
10
11
from Crypto.Cipher import ChaCha20

enc_data = bytes.fromhex("f568c48912eed6dc520c7164f44b6378e1d0d3e248914fa8847b405a131f")


key = b"SGludDogSW1wcm92ZSBvZiBTYWxzYTIw"
nonce = b"Is_This_"

cc = ChaCha20.new(key=key, nonce=nonce)

print(cc.decrypt(enc_data))

flag{But_I_Like_ChaCha20_More}

O2


查壳

直接用 ida 打开错误
用 010 打开跑一下模板


这个地方是用来判断 elf 的位数的,ctf 常考点,尝试修改
1是32位,2是64位
现在改为 02 然后导出副本,发现是可以的

用 ida 打开

定位到关键函数 enc
对三个参数进行分析,发现第三个参数是 key(PaluCTF)
那么第一个参数就是 output,加密后的 flag

!注意!:这里的变量需要动态调试的时候才会加载进去

这里差不多,加密逻辑清晰,ouput 最后要与 obj 比较,也就是说

已知:
加密逻辑,输出密文,key 那么我们就可以求出 flag 了
这里还是爆破比较好,因为加密比较难看

借鉴的 wp

1
2
3
4
5
6
7
8
9
10
11
12
from string import printable

enc = bytearray.fromhex("364d4d5c3e387e00421c597a0a7302144d5b70087e064619567336297d151f56770a7935424f2a780643")

key = "PaluCTF"

for i in range(len(enc)):
for c in printable:
if (ord(c) + ord(key[i % len(key)])) % 128 == enc[i]:
print(c, end="")
break

flag{d80a0d76-23af-486e-a0bc-43a463eac552}
另外一篇博客 z3 求解的时候会用 z3 求一遍

参考:
帕鲁杯 Writeup