5

CTF | 2021 春秋杯 Baby_steg WriteUp

 3 years ago
source link: https://miaotony.xyz/2021/05/31/CTF_2021chunqiu_Baby_steg/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client
image-20210530191538770.png

2021年 春秋杯 网络安全联赛春季赛

比赛时间:2021年5月29日 10:00-18:00

https://www.ichunqiu.com/chunqiucup

和上一篇一样,这周末比赛巨多。

于是春秋杯的话也是随意看了题,然而发现题目挺难的 Orz。

这个比赛的时候就摸鱼做了 Misc Baby_steg 题目的一半,剩下一半还是比赛后复现的。其他题目就没怎么看吧。

这题结合了几个之前没见过的玩法,这里顺手记录一下。

Baby_steg

小A想学MISC,她请教了某大佬,大佬为了考验她的能力,给了她一个文件,让她找到其中隐藏的秘密,可是小A拿到文件后一脸懵逼,所以来找你求救,你能帮助她吗?

附件下载 提取码(GAME)备用下载

hint:先获取password.7z里面的内容,大佬好像跟小A说是6-8位的数字

下载下来个压缩包。

image-20210529182500254.png

根据提示需要先解密那个 7z。

搜了一下发现 cRARk for 7-Zip 用来爆破还挺不错,支持自定义各种格式的密码,还能调用 GPU 加速运算。

https://www.crark.net/crark-7zip.html 这里下载。

参考 https://www.crark.net/cRARk-7z.htmlpassword.def 定义文件。

由于全是数字,直接就写成这样。

##
$1 *

然后指定最小和最大的长度去解密。

crark-7z.exe -l6 -g8 password.7z
image-20210529175232631.png

得到 7z 的密码 321456

解压出来个 password.txt

7324623c

flag1.txt 这是什么玩意……

image-20210529182615012.png

后来看了别人 wp 才发现是 uuencode。来复现一下。

拿 python 写个脚本解码一下。

python
import uu
s = uu.decode('flag1.txt')

它会自动输出文件。

加密的话就是

uu.encode(input_file, output_file)

用上面解密得到的 7324623c 作为密码解压。

得到一张图 challenge.png

challenge
challenge

以及 encode.py

python
import numpy as np
import cv2
import sys
import random

def encode(image):
    i = random.randint(520,540)
    np.random.seed(i)
    # image = 1298 * 695
    to_hide = cv2.imread(image)
    to_hide_array = np.asarray(to_hide)

    for i in range(to_hide_array.shape[0]):
        np.random.shuffle(to_hide_array[i])
    
    gray = cv2.cvtColor(to_hide_array, cv2.COLOR_BGR2GRAY)
    cv2.imwrite('challenge.png', gray)
    print("encode!")

def main():
    if len(sys.argv) != 2:
        print('error!')
        exit(1)
    encode(sys.argv[1])

if __name__ == '__main__':
    main()

随机数种子在 520-540 之前取值,np.random.shuffle 函数把 to_hide_array 第1个维度上的数字进行位置上的随机打乱。

于是可以试试爆破这个随机数种子,记录下打乱前后下标的映射关系,再反过来恢复出原始图像,其中一个就是打乱之前的图像了。

另外注意 random.randint(520,540) 在 520 和 540 上都能取到值,即左右区间都闭合。

代码写的有点乱,能用就行了。(逃走

python
import numpy as np
import cv2
import sys
import random


def decode(image):
    # image = 1298 * 695
    to_hide = cv2.imread(image)
    to_hide_array = np.asarray(to_hide)
    shape = to_hide_array.shape

    for i in range(520, 541):
        print('====>', i)
        np.random.seed(i)
        l1 = []
        for j in range(shape[0]):
            l2 = list(range(shape[1]))
            new_array = []
            np.random.shuffle(l2)
            for x in range(len(l2)):
                new_array.append(to_hide_array[j][l2.index(x)])
            l1.append(new_array)
        l1_array = np.asarray(l1)
        # gray = cv2.cvtColor(l1_array, cv2.COLOR_BGR2GRAY)
        cv2.imwrite(f'decode{i}.png', l1_array)


def main():
    decode('challenge.png')


if __name__ == '__main__':
    main()

最后跑出来是随机种子为 540 时候的情况,得出 flag。

decode540
decode540

Baby_steg 这题还是堆了几个没玩过的知识点的,正好还把 7z 压缩包爆破的工具也找了一波,cRARk for 7-Zip 还是挺香的!

顺便还发现了 python 里的 uu 就能直接进行 uuencode 编解码,好耶。

就这样吧,摸🐟大法好!

BTW,XCTF final 的题目太顶了,喵喵好菜玩不来,喵呜呜呜。

(看啥时候有机会再摸鱼来复现吧,喵喵🐱

(溜了溜了喵


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK