本文记录一下BugkuCTF上Misc部分的第四十一及之后题目。其他BugkuCTF的题目参见文末的链接。
$[timeformat('2019-09-14T11:55:44+08:00')]
#CTF#Misc

好多压缩包

123.zip

解压后里面有68个带密码的压缩包,爆破半天不行。之后注意到文件大小都只有4字节,想到使用CRC碰撞。抄一下大佬的脚本:

import zipfile
import string
import binascii
def CrackCrc(crc):
    for i in dic:
        for j in dic:
            for p in dic:
                for q in dic:
                    s = i + j + p + q
                    s = s.encode('utf-8')
                    if crc == (binascii.crc32(s) & 0xffffffff):
                        #print s
                        f.write(s)
                        return
def CrackZip():
    for I in range(68):
        file = '/Users/joe/Desktop/123/out' + str(I) + '.zip'
        print(file)
        z = zipfile.ZipFile(file, 'r')
        GetCrc = z.getinfo('data.txt')
        crc = GetCrc.CRC
        #以上3行为获取压缩包CRC32值的步骤
        #print(hex(crc))
        CrackCrc(crc)
dic = string.ascii_letters + string.digits + '+/='
with open('out.txt', 'wb')as f:
    CrackZip()

打开输出的文件看到一段base64:

z5BzAAANAAAAAAAAAKo+egCAIwBJAAAAVAAAAAKGNKv+a2MdSR0zAwABAAAAQ01UCRUUy91BT5UkSNPoj5hFEVFBRvefHSBCfG0ruGnKnygsMyj8SBaZHxsYHY84LEZ24cXtZ01y3k1K1YJ0vpK9HwqUzb6u9z8igEr3dCCQLQAdAAAAHQAAAAJi0efVT2MdSR0wCAAgAAAAZmxhZy50eHQAsDRpZmZpeCB0aGUgZmlsZSBhbmQgZ2V0IHRoZSBmbGFnxD17AEAHAA==

解码之后看到:

1

样子很像一个压缩文件,经查阅资料得知是个rar,但需要补上rar头52 61 72 21 1A 07 00。但一开始拷贝乱码老出现问题,写个脚本直接写成文件:

import base64
with open('out.txt', 'rb')as f:
    r = f.read()
    r = base64.b64decode(r)
    with open('out1.data', 'wb')as ff:
        f.write(r)

然后用010editor打开,补上rar头:

2

打开压缩包在注释里看到flag:

3

一个普通的压缩包

zip.rar

打开rar提示secret.png被损坏,解压rar得到flag.txt,但没有任何信息。拿到010editor里观察png头,看到headtype错误,将其修改为文件类型:

4

修改完成解压得到secret.png,16进制查看可知其为gif:

5

使用frame browser保存为两张图片,两张图的red plane0里各有半个二维码

7

将两张图合并文件再补上定位符可得flag:

6

2B

打开之后是宅男女神2B,010editor打开后发现文件里还包含一个zip,使用foremost分离后解压发现有密码。查看16进制知道是伪加密,修改标识为可修复:

8

解压后得到B2.png和2B.png,看起来没什么区别,使用stegsolve对比也没发现什么线索,尝试使用盲水印。

网上有两种盲水印脚本,其中一个脚本的作者还开发了python3版本,算起来一共有3个盲水印脚本。但经尝试,只有一个脚本能正确解出flag,不知道是不是我环境的问题。

import cv2
import numpy as np
import random
import os
from argparse import ArgumentParser
ALPHA = 5
def build_parser():
    parser = ArgumentParser()
    parser.add_argument('--original', dest='ori', required=True)
    parser.add_argument('--image', dest='img', required=True)
    parser.add_argument('--result', dest='res', required=True)
    parser.add_argument('--alpha', dest='alpha', default=ALPHA)
    return parser
def main():
    parser = build_parser()
    options = parser.parse_args()
    ori = options.ori
    img = options.img
    res = options.res
    alpha = float(options.alpha)
    if not os.path.isfile(ori):
        parser.error("original image %s does not exist." % ori)
    if not os.path.isfile(img):
        parser.error("image %s does not exist." % img)
    decode(ori, img, res, alpha)
def decode(ori_path, img_path, res_path, alpha):
    ori = cv2.imread(ori_path)
    img = cv2.imread(img_path)
    ori_f = np.fft.fft2(ori)
    img_f = np.fft.fft2(img)
    height, width = ori.shape[0], ori.shape[1]
    watermark = (ori_f - img_f) / alpha
    watermark = np.real(watermark)
    res = np.zeros(watermark.shape)
    random.seed(height + width)
    x = range(height / 2)
    y = range(width)
    random.shuffle(x)
    random.shuffle(y)
    for i in range(height / 2):
        for j in range(width):
            res[x[i]][y[j]] = watermark[i][j]
    cv2.imwrite(res_path, res, [int(cv2.IMWRITE_JPEG_QUALITY), 100])
if __name__ == '__main__':
    main()
python2 decode.py --original B2.png --image 2B.png --result 1.png

9

NUST{I_10v3_2B_F0r3v3r}

QAQ

cipher.txt

QAQ

查看16进制猜想QAQ可能是个pyc,使用反编译工具:

uncompyle6 QAQ.pyc > 1.py

得到加密算法:

def encryt(key, plain):
    cipher = ''
    for i in range(len(plain)):
        cipher += chr(ord(key[(i % len(key))]) ^ ord(plain[i]))
    return cipher
def getPlainText():
    plain = ''
    with open('plain.txt') as (f):
        while True:
            line = f.readline()
            if line:
                plain += line
            else:
                break
    return plain
def main():
    key = 'LordCasser'
    plain = getPlainText()
    cipher = encryt(key, plain)
    with open('cipher.txt', 'w') as (f):
        f.write(cipher.encode('base_64'))
if __name__ == '__main__':
    main()

根据加密脚本写个解密脚本

import base64
cipher = '''
FSAnRAIzNlMjPQMjNyBJNTs6NlIFPFIqDDVTJy0zGE8rKxZBJDIrJkYoPUQML1M3MDYJZTElFyI7
UzE6DTtSNxckNDw2Mxk9Jzc=
'''
key = 'LordCasser'
plain = ''
c1 = base64.b64decode(cipher)
c1 = c1.decode('utf-8')
for i in range(len(c1)):
    plain += chr(ord(c1[i]) ^ ord(key[(i % len(key))]))
print(plain)

得到:

YOU ARE FOOLED
THIS IS NOT THAT YOU WANT
GO ON DUDE
CATCH THAT STEGOSAURUS

百度了一番,查看一个用于在python字节码中隐藏信息的工具:

https://github.com/AngelKitty/stegosaurus

用法:

#从负载中分离载荷
python3 stegosaurus.py -x encode.py
#报告最大载荷存储量
python3 stegosaurus.py encode.py -r
#嵌入载荷到负载中
python3 stegosaurus.py encode.py -s --payload "xxx"

得到flag:

10

apple

Apple在2017年WWDC上发布了全新的APFS ,带有一系列新功能。 Bugku很好奇,马上试了一下。 而且,他给你留下了一些惊喜:)

N1CTF_APFS_ver2.dmg

尝试打开发现有密码,使用010editor看到最后有个字符串:

11

使用N1CTF_APFS成功打开并挂载。打开挂载盘看到531个0字节的txt,思路中断...查看writeup得知可以通过以下命令查看快照:

#查看快照
tmutil listlocalsnapshots /Volumes/N1CTF_APFS
#挂载快照
mkdir temp
mount_apfs -s ctf /Volumes/N1CTF_APFS ./temp/

使用以下命令取得文件的修改时间(精确到10^9级):

gstat -c "%n %y" * > ./1.txt
gstat -c "%n %y" * > ./2.txt

使用脚本分别取两个镜像所有文件修改时间的最后一位秒数,并做异或,然后作为8进制数转2进制,再转Ascii码写入文件。

import re
path1 = './1.txt'
path2 = './2.txt'
l1 = []
l2 = []
req = ''
with open(path1, 'r')as f1:
    lines = f1.readlines()
    for line in lines:   
        req = re.findall(r'[0-9]{4}.txt 2018-02-23 07:33:33.[0-9]{8}([0-9])', line)[0]
        l1.append(req)
with open(path2, 'r')as f2:
    lines = f2.readlines()
    for line in lines:   
        req = re.findall(r'[0-9]{4}.txt 2018-02-23 07:33:33.[0-9]{8}([0-9])', line)[0]
        l2.append(req)
b = ''
for i in range(len(l1)):
    f = int(l1[i]) ^ int(l2[i])
    b += bin(int('0o'+str(f),8)).replace("0b", "").zfill(3)
with open('./result.data', 'wb')as f:
    for i in range(0, len(b), 8):
        f.write(chr(int(b[i:i+8], 2)).encode('utf-8'))

写入之后用010editor打开发现是个zip,使用之间得解压密码N1CTF_APFS可得flag。

12

妹子的陌陌

想要妹子陌陌号吗?做题来拿吧。下载这个图片做题

momo.jpg

使用foremost可从图片中分离出一个rar,解压密码竟然是图片中的“喜欢我吗.”...解压得到:

13

先解码摩斯电码得到一个网址:

14

打开网址是个在线编码解码网站。把网址后面的base64作为密文粘进去,填上key,可解出明文:

15

将解出的明文和网址前半部分“http://c.bugku.com/”合起来,得到一个图片链接,下载后发现是个反色的二维码:

16

使用stegsolve取反可扫出flag:

17

就五层你能解开吗

链接: http://pan.baidu.com/s/1i4TQoz7 密码: w65m

提示:第一层:CRC32 碰撞

第二层:维吉尼亚密码

第三层:sha1 碰撞

第四层:md5 相同文件不同

第五层:RSA

先从Github上找了个CRC32碰撞脚本:

https://github.com/theonlypwner/crc32

依次逆向三个CRC:

18

19

20

从结果上猜测最有可能的组合是:

_CRC32_i5_n0t_s4f3

使用这个密码成功解压7z,再解压里面的7z,看到一个keys.txt,里面有10000个密钥,一个ciphertext.txt,里面有一段密文。还有个tips.txt:

21

写个python批量解密维吉尼亚密码:

from pycipher import Vigenere
keys = []
cipher = 'rla xymijgpf ppsoto wq u nncwel ff tfqlgnxwzz sgnlwduzmy vcyg ib bhfbe u tnaxua ff satzmpibf vszqen eyvlatq cnzhk dk hfy mnciuzj ou s yygusfp bl dq e okcvpa hmsz vi wdimyfqqjqubzc hmpmbgxifbgi qs lciyaktb jf clntkspy drywuz wucfm'
with open('./keys.txt', 'r')as f:
    keys = f.readlines()
plain = ''
with open('./plain.txt', 'w')as f:
    for i in keys:
        i=i.replace('\n','')
        plain = Vigenere(i).decipher(cipher)
        f.write(plain+'\n')

从得到的10000个明文中,搜索“Vigenere”,找到唯一一条有意义的明文:

THEVIGENERECIPHERISAMETHODOFENCRYPTINGALPHABETICTEXTBYUSINGASERIESOFDIFFERENTCAESARCIPHERSBASEDONTHELETTERSOFAKEYWORDITISASIMPLEFORMOFPOLYALPHABETICSUBSTITUTIONSOPASSWORDISVIGENERECIPHERFUNNY

从最后可以得到下一个压缩包的密码是“vigenere cipher funny”,需要全部改为小写。

解压得到一个加密7z和一个txt:

22

写个python跑一下:

import string
import hashlib
printable = string.printable
for k1 in printable:
    for k2 in printable:
        for k3 in printable:
            for k4 in printable:
                key = k1 + '7' + k2 + '5-' + k3 + '4' + k4 + '3?'
                sha1 = hashlib.sha1(key.encode('utf-8'))
                flag = sha1.hexdigest()
                if '619c20c'and'a4de755'and'9be9a8b'and'b7cbfa5'and'e8b4365' in flag:
                    print(key)

挨个试跑出来的结果:

8725-{4}3?
f7B5-]43?
k7T5-)4l3?
p7.5-"4'3?
F7M5-i4@3?
I7~5-s4F3?
*705-q4w3?

最后发现“I7~5-s4F3?”是真正的密码。解压后看到一个txt:

23

从网上找了这样两个软件:

24

输出分别是:

Hello World ;-)
Goodbye World :-(

经尝试,“Goodbye World :-(”是正确的密码。

解压之后得到一个pem密钥文件,和一个enc密文文件。大学学的RSA基本已还给老师了,弄明白原理之前先上工具解出答案再说。

https://github.com/Ganapati/RsaCtfTool

先装好以下依赖库:

  • GMPY2
  • SymPy
  • PyCrypto
  • Requests
  • SageMath - optional but advisable

运行以下命令:

python RsaCtfTool.py --publickey './rsa_public_key.pem' --uncipherfile './flag.enc'

25

一个NB的工具是多么重要...

杂项部分总结:

除了两个做不出来也没搜到writeup的题之外,Bugku杂项部分都齐了,有会以下两题的大佬请带带小弟orz...

BugkuCTF-Misc-2/#不简单的压缩包

BugkuCTF-Misc-2/#一枝独秀

所有BugkuCTF的题目:

BugkuCTF-Misc-1

BugkuCTF-Misc-2

BugkuCTF-Misc-3

BugkuCTF-Web-1

BugkuCTF-Web-2

BugkuCTF-Web-3


评论