WriteUp:巅峰极客 Misc

前言

巅峰极客的三道 Misc 题。

本体分别如下:

warmup
loli
flows

warmup

这道题比较奇怪,我看很多 WP 写的都是用 StegSolve 解决,但是我这里 StegSolve 一模一样的选项却什么都看不到,很蓝瘦。

所以我用的是 zsteg,效果还不错。

这里可以看到出现了 Ook 和 BrainFuck,分别提取出来后到这个网站在线解密可以得到三段 flag 拼接起来就是答案。

loli

打开一看是一张二维码,但是微信扫不出来,然后我就被坑了以为是少了定位标志….

后来经提醒直接用 CQ Research 扫码可以得到

这里有个提示 255,也就是 0xFF。

接着用 010 editor 打开图片发现文件末尾多了一块。

联想之前的提示(开脑洞)应该是异或,于是把最后一块提取出来异或得到新的 png 图片。

这里观察到图片大小为 100x100,并且所有的黑块被横向分为了十一列(全白的一列当做分界线),同时纵向上被分为了 50 行(全黑的一行当做分界线)。

接着注意到每一小段都是 8 个像素并且最左边的像素一定是白色,联想是 ASCII 码,所以写个脚本挨个翻译为 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 struct
from PIL import Image

# 这里是异或过程
with open('./end.bin', 'rb') as r:
with open('./end.png', 'wb+') as w:
for i in r.read():
w.write(struct.pack('B', i^0xFF))

img = Image.open('./end.png')

flag = ''

for i in range(0, 100, 2):
for j in range(11):
c = 0
for k in range(8):
p = img.getpixel((9*j + k + 1, i))
if p == (0, 0, 0):
c |= (1<<(7 - k))
flag += chr(c & 0Xff)

print(flag)

然后可以得到 flag。

flows

首先这里的解题方法参考了安全客的这篇文章

把 pcap 文件拖进 wireshark 后,按照包大小排序注意到三个比较关键的包。

图中高亮的包是一个 tips,同时最大的两个包分别是两个 pcap 文件。

其中 tips 内容如下

tips:

1、键盘的usb.capdata第一字节为0x02的代表按了shift键
2、鼠标的usb.capdata只用关心第一字节

两个 pcap 文件分别就是键盘和鼠标的流量包,分别用 tshark.exe -r 1.pcap -T fields -e usb.capdata > usbdata.txt 提取出我们需要的流量。

其中对于键盘的流量包根据提示我稍微对脚本进行了一些修改,加入了 shift 的提醒

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
mappings = { 0x04:"a",  0x05:"b",  0x06:"c", 0x07:"d", 
0x08:"e", 0x09:"f", 0x0A:"g", 0x0B:"h",
0x0C:"i", 0x0D:"j", 0x0E:"k", 0x0F:"l",
0x10:"m", 0x11:"n",0x12:"o", 0x13:"p",
0x14:"q", 0x15:"r", 0x16:"s", 0x17:"t",
0x18:"u",0x19:"v", 0x1A:"w", 0x1B:"x",
0x1C:"y", 0x1D:"z", 0x1E:"1", 0x1F:"2",
0x20:"3", 0x21:"4", 0x22:"5", 0x23:"6",
0x24:"7", 0x25:"8", 0x26:"9", 0x27:"0",
0x28:"n", 0x2a:"[DEL]", 0X2B:" ",
0x2C:" ", 0x2D:"-", 0x2E:"=", 0x2F:"[",
0x30:"]", 0x31:"\\", 0x32:"~", 0x33:";",
0x34:"'", 0x36:",", 0x37:"." }
nums = []
keys = open('usbdata2.txt')
f0 = ""
with open('usbdata2.txt') as keys:
f0 = ""
for line in keys:
if len(line) != 24:
continue
n = int(line[6:8],16)
if n == 0 :
continue
if n in mappings:
if int(line[0:2], 16) == 0x2:
print(f'{mappings[n]} with shift')
f0 += mappings[n]
else:
f0 += '[unknown]'
print(f0)

这样可以得到 flag 的前半段,后半段在鼠标流量里。

根据 tips 只用关心第一字节,所以猜测 0x1 代表 0 并且 0x2 代表 1 然后构成二进制串(反正错了就反过来再猜一次),写脚本得到 flag 后半段。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
with open('usbdata.txt') as mouse:
f1 = ""
f2 = ""
for line in mouse:
if line == '\n':
continue
c = int(line[0:2], 16)
if c == 1:
#f1 += '1'
f2 += '0'
elif c == 2:
#f1 += '0'
f2 += '1'
def str2bytes(b):
l = len(b)
d = int(b, 2)
r = ''
for i in range(l//8):
r += chr((d >> (8*i)) & 0xFF)
return r
# print(str2bytes(f1))
print(str2bytes(f2)[::-1])

最后拼接起来就是完整 flag。

后记

做 Misc 题,脑洞很重要。

参考资料

从CTF中学USB流量捕获与解析