[BugkuCTF]杂项部分(3)

本文记录一下BugkuCTF上杂项部分的第四十一及之后题目。其他BugkuCTF的题目参见文末的链接。

好多压缩包

123.zip

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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:

1
z5BzAAANAAAAAAAAAKo+egCAIwBJAAAAVAAAAAKGNKv+a2MdSR0zAwABAAAAQ01UCRUUy91BT5UkSNPoj5hFEVFBRvefHSBCfG0ruGnKnygsMyj8SBaZHxsYHY84LEZ24cXtZ01y3k1K1YJ0vpK9HwqUzb6u9z8igEr3dCCQLQAdAAAAHQAAAAJi0efVT2MdSR0wCAAgAAAAZmxhZy50eHQAsDRpZmZpeCB0aGUgZmlsZSBhbmQgZ2V0IHRoZSBmbGFnxD17AEAHAA==

解码之后看到:

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

1
2
3
4
5
6
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头:

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

一个普通的压缩包

zip.rar

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

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

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

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

2B

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

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

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
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()
1
python2 decode.py --original B2.png --image 2B.png --result 1.png

NUST{I_10v3_2B_F0r3v3r}

QAQ

cipher.txt

QAQ

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

1
uncompyle6 QAQ.pyc > 1.py

得到加密算法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
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()

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

1
2
3
4
5
6
7
8
9
10
11
12
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)

得到:

1
2
3
4
YOU ARE FOOLED
THIS IS NOT THAT YOU WANT
GO ON DUDE
CATCH THAT STEGOSAURUS

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

https://github.com/AngelKitty/stegosaurus

用法:

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

得到flag:

apple

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

N1CTF_APFS_ver2.dmg

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

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

1
2
3
4
5
#查看快照
tmutil listlocalsnapshots /Volumes/N1CTF_APFS
#挂载快照
mkdir temp
mount_apfs -s ctf /Volumes/N1CTF_APFS ./temp/

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

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

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
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。

妹子的陌陌

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

momo.jpg

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

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

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

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

使用stegsolve取反可扫出flag:

就五层你能解开吗

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

提示:第一层:CRC32 碰撞

第二层:维吉尼亚密码

第三层:sha1 碰撞

第四层:md5 相同文件不同

第五层:RSA

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

https://github.com/theonlypwner/crc32

依次逆向三个CRC:

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

1
_CRC32_i5_n0t_s4f3

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

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

1
2
3
4
5
6
7
8
9
10
11
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”,找到唯一一条有意义的明文:

1
THEVIGENERECIPHERISAMETHODOFENCRYPTINGALPHABETICTEXTBYUSINGASERIESOFDIFFERENTCAESARCIPHERSBASEDONTHELETTERSOFAKEYWORDITISASIMPLEFORMOFPOLYALPHABETICSUBSTITUTIONSOPASSWORDISVIGENERECIPHERFUNNY

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

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

写个python跑一下:

1
2
3
4
5
6
7
8
9
10
11
12
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)

挨个试跑出来的结果:

1
2
3
4
5
6
7
8725-{4}3?
f7B5-]43?
k7T5-)4l3?
p7.5-"4'3?
[email protected]?
I7~5-s4F3?
*705-q4w3?

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

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

输出分别是:

1
2
Hello World ;-)
Goodbye World :-(

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

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

https://github.com/Ganapati/RsaCtfTool

先装好以下依赖库:

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

运行以下命令:

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

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

杂项部分总结:

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

[BugkuCTF]杂项部分(2)/#不简单的压缩包

[BugkuCTF]杂项部分(2)/#一枝独秀

所有BugkuCTF的题目:

[BugkuCTF]Web部分(1)

[BugkuCTF]Web部分(2)

[BugkuCTF]Web部分(3)

[BugkuCTF]杂项部分(1)

[BugkuCTF]杂项部分(2)

[BugkuCTF]杂项部分(3)

但愿我的博文能对您有所帮助~