前言

做的时候就觉得题目阴间得一匹,没想到官方wp也这么阴间,原理呢?分析呢?不管怎么说看着就是不明不白脑洞也贼多,复现起来也怪怪的

yusa_yyds

回过头仔细看时才注意到Xbox360提示,当时其实队友有注意到可能是xbox,我们还看了官方文档,但想多了,注意力全放在提取出来的usbdata上,最后也没看懂

图片

图片

xbox传入的信息在流量包的DEVICE DESCRIPTOR部分,以下截一个包分析

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
DEVICE DESCRIPTOR
    bLength: 18
    bDescriptorType: 0x01 (DEVICE)
//设备描述符长度为18个字节
    bcdUSB: 0x0200
//控制器使用USB2.0
    bDeviceClass: Vendor Specific (0xff)
    bDeviceSubClass: 255
    bDeviceProtocol: 255
//设备的USB设备类别被设定为0xFF,子类设定为255,设备协议设定为255
    bMaxPacketSize0: 8
//端点0(设备控制端点)的最大数据包大小为8字节
    idVendor: Microsoft Corp. (0x045e)
    idProduct: Xbox360 Controller (0x028e)
//供应商VID和PID信息信息
    bcdDevice: 0x0114
//供应商定义的版本号,被编码为二进制编码的十进制,使用8421编码可转为1.1.4版本
    iManufacturer: 1
    iProduct: 2
    iSerialNumber: 3
    bNumConfigurations: 1
//描述制造商,产品,序列号的字符串在索引1,2,3,该设备只有1种配置

通过time可以发现,中间断电缺失了一段时间的数据

图片

图片

然后wp里说的

图片

图片

恕我直言没看懂,希望能有师傅教教我

下面是之前常规做法时提取的usbdata

提取usb流量

1
tshark -r game.pcapng -T fields -e usb.capdata > usbdata.txt

读取出来的usb流量,不是常规的键盘和鼠标敲击码
键盘一般是八位一组,第一二位都是00,第三位开始记录击键信息.

鼠标一般是四位一组,第一位代表按键,取00时没有按键,取01时按左键,取02时按右键;第二位可以看成是一个signed byte类型,最高位为符号位,当这个值为正时代表鼠标水平右移多少像素,为负时代表水平左移多少像素.第三位与第二位类似,代表垂直上下移动的偏移.

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
00:08:00:ff:00:00:00:00
00:08:00:00:00:00:00:00
00:08:00:ff:00:00:00:00
00:08:00:00:00:00:00:00
00:08:00:ff:00:00:00:00
00:08:00:00:00:00:00:00
00:08:00:ff:00:00:00:00
00:08:00:00:00:00:00:00
01:00:00:00:65:00:00:00:00:00:00:53:00:00:00:00:00:00:00:00:00:00:05:04:00:00:00:00:00:00:00:45:00:00:05:00:00:00:04:00:02:0b:b8:05:00:00:00:04:00:02:0b:b9:02:00:00:00:04:00:00:00:01:06:00:00:00:08:00:00:00:05:25:03:78:ce:05:00:00:00:04:00:02:0b:b9:02:00:00:00:04:00:00:00:02:01:00:00:00:04:00:00:00:01
00:08:00:ff:00:00:00:00
00:08:00:00:00:00:00:00
00:08:00:ff:00:00:00:00
00:08:00:00:00:00:00:00
00:08:00:ff:00:00:00:00
00:08:00:00:00:00:00:00
00:08:00:ff:00:00:00:00
00:08:00:00:00:00:00:00
00:08:00:ff:00:00:00:00
00:08:00:00:00:00:00:00
00:08:00:ff:00:00:00:00
00:08:00:00:00:00:00:00
00:08:00:ff:00:00:00:00
00:08:00:00:00:00:00:00
00:08:00:ff:00:00:00:00
00:08:00:00:00:00:00:00
01:00:00:00:65:00:00:00:00:00:00:53:00:00:00:00:00:00:00:00:00:00:05:04:00:00:00:00:00:00:00:45:00:00:05:00:00:00:04:00:02:0b:b8:05:00:00:00:04:00:02:0b:b9:02:00:00:00:04:00:00:00:01:06:00:00:00:08:00:00:00:05:25:90:30:ce:05:00:00:00:04:00:02:0b:b9:02:00:00:00:04:00:00:00:02:01:00:00:00:04:00:00:00:02
00:08:00:ff:00:00:00:00
00:08:00:00:00:00:00:00
00:08:00:ff:00:00:00:00
00:08:00:00:00:00:00:00
00:08:00:ff:00:00:00:00
00:08:00:00:00:00:00:00
00:08:00:ff:00:00:00:00
00:08:00:00:00:00:00:00

yusapapa

在网页注释里有提示

1
2
3
Maybe these texts are really helpful for you
Biometric list is OK!
endow gremlin indulge bison flatfoot fallout goldfish bison hockey fracture fracture bison goggles jawbone bison flatfoot gremlin glucose glucose fracture flatfoot indoors gazelle gremlin goldfish bison guidance indulge keyboard keyboard glucose fracture hockey bison gazelle goldfish bison cement frighten gazelle goldfish indoors buzzard highchair fallout highchair bison fallout goldfish flytrap bison fallout goldfish gremlin indoors frighten fracture highchair bison cement fracture goldfish flatfoot gremlin flytrap fracture buzzard guidance goldfish freedom buzzard allow crowfoot jawbone bison indoors frighten fracture bison involve fallout jawbone Burbank indoors frighten fracture bison guidance gazelle flatfoot indoors indulge highchair fracture bison hockey frighten gremlin indulge flytrap bison flagpole fracture bison indulge hockey fracture flytrap bison allow blockade endow indulge hockey fallout blockade bison gazelle hockey bison inverse fracture highchair jawbone bison gazelle goggles guidance gremlin highchair indoors fallout goldfish indoors bison gazelle goldfish bison indoors frighten gazelle hockey bison flatfoot frighten fallout glucose glucose fracture goldfish freedom fracture blackjack blackjack

去重整理列表

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
endow
gremlin
indulge
bison
flatfoot
fallout
goldfish
hockey
fracture
goggles
jawbone
glucose
indoors
gazelle
guidance
keyboard
cement
frighten
buzzard
highchair
flytrap
freedom
allow
crowfoot
involve
Burbank
flagpole
blockade
inverse
blackjack

根据PGP词汇表对应写个脚本

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
# -*- coding: UTF-8 -*-
from __future__ import print_function
a = "endow gremlin indulge bison flatfoot fallout goldfish bison hockey fracture fracture bison goggles jawbone bison flatfoot gremlin glucose glucose fracture flatfoot indoors gazelle gremlin goldfish bison guidance indulge keyboard keyboard glucose fracture hockey bison gazelle goldfish bison cement frighten gazelle goldfish indoors buzzard highchair fallout highchair bison fallout goldfish flytrap bison fallout goldfish gremlin indoors frighten fracture highchair bison cement fracture goldfish flatfoot gremlin flytrap fracture buzzard guidance goldfish freedom buzzard allow crowfoot jawbone bison indoors frighten fracture bison involve fallout jawbone Burbank indoors frighten fracture bison guidance gazelle flatfoot indoors indulge highchair fracture bison hockey frighten gremlin indulge flytrap bison flagpole fracture bison indulge hockey fracture flytrap bison allow blockade endow indulge hockey fallout blockade bison gazelle hockey bison inverse fracture highchair jawbone bison gazelle goggles guidance gremlin highchair indoors fallout goldfish indoors bison gazelle goldfish bison indoors frighten gazelle hockey bison flatfoot frighten fallout glucose glucose fracture goldfish freedom fracture blackjack blackjack"
s = a.split(" ")
dict = {'endow': '59',
'gremlin': '6F',
'indulge': '75',
'bison':'20',
'flatfoot':'63',
'fallout':'61',
'goldfish': '6E',
'hockey': '73',
'fracture': '65',
'goggles':'6D',
'jawbone': '79',
'glucose': '6C',
'indoors': '74',
'gazelle': '69',
'guidance': '70',
'keyboard': '7A',
'cement': '2F',
'frighten': '68',
'buzzard': '2E',
'highchair': '72',
'flytrap': '64',
'freedom': '67',
'allow': '0A',
'crowfoot': '42',
'involve': '77',
'Burbank': '2C',
'flagpole': '62',
'blockade': '22',
'inverse': '76',
'blackjack': '21'
};
for item in s:
print (dict[item],end='')
596F752063616E20736565206D7920636F6C6C656374696F6E2070757A7A6C657320696E202F68696E742E72617220616E6420616E6F74686572202F656E636F64652E706E672E0A427920746865207761792C74686520706963747572652073686F75642062652075736564200A225975736122206973207665727920696D706F7274616E7420696E2074686973206368616C6C656E67652121

解hex

1
2
3
You can see my collection puzzles in /hint.rar and another /encode.png.
By the way,the picture shoud be used
"Yusa" is very important in this challenge!!

也可以在在线网站解密
同时发现页面的图片是.webp格式,存在webp隐写

stegpy工具安装

1
2
3
4
python3 -m pip install stegpy
git clone https://github.com/dhsdshdhk/stegpy.git
cd stegpy
python3 setup.py install

使用命令行解密

1
2
3
stegpy encode.webp
得到密码
the_key_is:Yus@_yydsstegpy!!

下载hint.rar后,注释里提示

1
利用一种较为古老和不常见的工具。USE your google and Baidu

使用刚才用stegpy解出来的密码解压缩,得到一张图片

图片

图片

根据比赛放出的提示搜到 invisible Secrets 工具,我下的是pro 3.0 版本

使用工具解密文件,密码是Yusa,得到encode.py

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
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
import os,random
from PIL import Image,ImageDraw
p=Image.open('flag.png').convert('L')
flag = []
a,b = p.size
for x in range(a):
    for y in range(b):
        if p.getpixel((x,y)) == 255:
            flag.append(0)
        else:
            flag.append(1)
key1stream = []
for _ in range(len(flag)):
    key1stream.append(random.randint(0,1))
random.seed(os.urandom(8))
key2stream = []
for _ in range(len(flag)):
    key2stream.append(random.randint(0,1))
enc = []
for i in range(len(flag)):
    enc.append(flag[i]^key1stream[i]^key2stream[i])
hide=Image.open('source.png').convert('RGB')
R=[]
G=[]
B=[]
a,b = hide.size
for x in range(a):
    for y in range(b):
        R.append(bin(hide.getpixel((x,y))[0]).replace('0b','').zfill(8))
        G.append(bin(hide.getpixel((x, y))[1]).replace('0b','').zfill(8))
        B.append(bin(hide.getpixel((x, y))[2]).replace('0b','').zfill(8))
R1=[]
G1=[]
B1=[]
for i in range(len(key1stream)):
    if key1stream[i] == 1:
        R1.append(R[i][:7]+'1')
    else:
        R1.append(R[i][:7]+'0')
for i in range(len(key2stream)):
    if key2stream[i] == 1:
        G1.append(G[i][:7]+'1')
    else:
        G1.append(G[i][:7]+'0')
for i in range(len(enc)):
    if enc[i] == 1:
        B1.append(B[i][:7]+'1')
    else:
        B1.append(B[i][:7]+'0')
for r in range(len(R)):
    R[r] = int(R1[r],2)
for g in range(len(G)):
    G[g] = int(G1[g],2)
for b in range(len(B)):
    B[b] = int(B1[b],2)
a,b = hide.size
en_p = Image.new('RGB',(a,b),(255,255,255))
for x in range(a):
    for y in range(b):
        en_p.putpixel((x,y),(R[y+x*b],G[y+x*b],B[y+x*b]))
en_p.save('encode.png')

根据加密脚本写解密脚本,这里直接贴官方wp的

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
from PIL import Image,ImageDraw
p = Image.open('encode.png').convert('RGB')
a,b = p.size
R=[]
G=[]
B=[]
for x in range(a):
    for y in range(b):
        R.append(bin(p.getpixel((x,y))[0]).replace('0b','').zfill(8))
        G.append(bin(p.getpixel((x, y))[1]).replace('0b''').zfill(8))
        B.append(bin(p.getpixel((x, y))[2]).replace('0b''').zfill(8))
R1=[]
G1=[]
B1=[]
flag=[]
for i in range(len(R)):
    R1.append(int(R[i][-1:]))
    G1.append(int(G[i][-1:]))
    B1.append(int(B[i][-1:]))
print(R1[100:150])
print(G1[100:150])
print(B1[100:150])
for i in range(len(R1)):
    flag.append(B1[i]^G1[i]^R1[i])
print(flag[100:150])
de_p = Image.new('L',(a,b),255)
c=0
for x in range(a):
    for y in range(b):
        if flag[c] == 1:
            de_p.putpixel((x,y),0)
        else:
            de_p.putpixel((x, y), 255)
        c=c+1
de_p.save('out.png')

好家伙,差点把我电脑跑死机

图片

图片

flag{fa0a8cb83f26dead82e1a45f8af2f44b}

指鹿为马

show source code

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
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
import numpy as np
from PIL import Image
import math
import operator
import os
import time
import base64
import random
def load_horse():
data = []
p = Image.open('./horse.png').convert('L')
p = np.array(p).reshape(-1)
p = np.append(p,0)
data.append(p)
return np.array(data)
def load_deer():
data = []
p = Image.open('./deer.png').convert('L')
p = np.array(p).reshape(-1)
p = np.append(p,1)
data.append(p)
return np.array(data)
def load_test(pic):
data = []
p = Image.open(pic).convert('L')
p = np.array(p).reshape(-1)
p = np.append(p,1)
data.append(p)
return np.array(data)
def euclideanDistance(instance1, instance2, length):
distance = 0
for x in range(length):
distance += pow((instance1[x] - instance2[x]), 2)
return math.sqrt(distance)
def getNeighbors(trainingSet, testInstance, k):
distances = []
length = len(testInstance) - 1
for x in range(len(trainingSet)):
dist = euclideanDistance(testInstance, trainingSet[x], length)
distances.append((trainingSet[x], dist))
distances.sort(key=operator.itemgetter(1))
neighbors = []
for x in range(k):
neighbors.append(distances[x][0])
return neighbors
def getResponse(neighbors):
classVotes = {}
for x in range(len(neighbors)):
response = neighbors[x][-1]
if response in classVotes:
classVotes[response] += 1
else:
classVotes[response] = 1
sortedVotes = sorted(classVotes.items(), key=operator.itemgetter(1), reverse=True)
return sortedVotes[0][0]
def getAccuracy(testSet, predictions):
correct = 0
for x in range(len(testSet)):
if testSet[x][-1] == predictions[x]:
correct += 1
return (correct / float(len(testSet))) * 100.0
def check(pic):
source_p = Image.open('deer.png')
try:
c_p = Image.open(pic)
except:
print("Please upload right picture.")
exit()
diff_pixel = 0
a, b = source_p.size
if c_p.size[0] != a and c_p.size[1] != b:
print("Please upload right picture size("+str(a)+','+str(b)+')')
exit()
for y in range(b):
for x in range(a):
diff_pixel += abs(source_p.getpixel((x, y)) - c_p.getpixel((x, y)))
return diff_pixel
def main():
while 1:
print('-' * 134)
print('''      ____       __            _          _   _                _                              _   _            _
|  __ \     / _|          | |        | | | |              | |                            | | | |          | |
| |__) |___| |_ ___ _ __  | |_ ___   | |_| |__   ___    __| | ___  ___ _ __    __ _ ___  | |_| |__   ___  | |__   ___  _ __ ___  ___
|  _  // _ \  _/ _ \ '__| | __/ _ \  | __| '_ \ / _ \  / _` |/ _ \/ _ \ '__|  / _` / __| | __| '_ \ / _ \ | '_ \ / _ \| '__/ __|/ _ \\
| | \ \  __/ ||  __/ |    | || (_) | | |_| | | |  __/ | (_| |  __/  __/ |    | (_| \__ \ | |_| | | |  __/ | | | | (_) | |  \__ \  __/
|_|  \_\___|_| \___|_|     \__\___/   \__|_| |_|\___|  \__,_|\___|\___|_|     \__,_|___/  \__|_| |_|\___| |_| |_|\___/|_|  |___/\___|
''')
print('-'*134)
print('\t1.show source code')
print('\t2.give me the source pictures')
print('\t3.upload picture')
print('\t4.exit')
choose = input('>')
if choose == '1':
w = open('run.py','r')
print(w.read())
continue
elif choose == '2':
print('this is horse`s picture:')
h = base64.b64encode(open('horse.png','rb').read())
print(h.decode())
print('-'*134)
print('this is deer`s picture:')
d = base64.b64encode(open('deer.png', 'rb').read())
print(d.decode())
continue
elif choose == '4':
break
elif choose == '3':
print('Please input your deer picture`s base64(Preferably in png format)')
pic = input('>')
try:
pic = base64.b64decode(pic)
except:
exit()
if b"<?php" in pic or b'eval' in pic:
print("Hacker!!This is not WEB,It`s Just a misc!!!")
exit()
salt = str(random.getrandbits(15))
pic_name = 'tmp_'+salt+'.png'
tmp_pic = open(pic_name,'wb')
tmp_pic.write(pic)
tmp_pic.close()
if check(pic_name)>=100000:
print('Don`t give me the horse source picture!!!')
os.remove(pic_name)
break
ma = load_horse()
lu = load_deer()
k = 1
trainingSet = np.append(ma, lu).reshape(2, 5185)
testSet = load_test(pic_name)
neighbors = getNeighbors(trainingSet, testSet[0], k)
result = getResponse(neighbors)
if repr(result) == '0':
os.system('clear')
print('Yes,I want this horse like deer,here is your flag encoded by base64')
flag = base64.b64encode(open('flag','rb').read())
print(flag.decode())
os.remove(pic_name)
break
else:
print('I want horse but not deer!!!')
os.remove(pic_name)
break
else:
print('wrong choose!!!')
break
exit()
if __name__=='__main__':
main()

give me the source pictures

1
2
3
4
5
this is horse`s picture:
iVBORw0KGgoAAAANSUhEUgAAAEgAAABICAAAAABwhuybAAAFeElEQVR4nO2Xy28TVxTGvzN2ZpLYIY5dkgImIU4I2DFqQqiaqGpL2gXqv8AC2lUX/BFl032lSpWqblqpGyQ2LQhERQhUDSqk4ZnEtHnxCATn4TjP8fOeLmZszzPEUpeclefeM7/z3e/OfRh4G/9n+Dtk907v7jnKh42vc6690u5BTe/u1FsFyEPVgGoaqkAbw+pR5+m5689dq+5QxApSWjuO/DhbGoRgU6dcv7E7UH1472EUw2fuFDVS8e+UKblmX3JXoHBfiEKAOJjSClPOOpTOp2k3kCG19aN3IADA08habGyZk7nxRN2bFTWc8AuEWiWADtG8AIAF1ZLNrZ77SwynqIAa19cpHpMZgLddmcsTCpmwBACFZLGcFQ69TKoaivPragVKxl/9Z/YI/WlxRiVtoKC1qyoAtJzyAgAx66+LrWdPNu2KGL2n/el6vaFZntogzUBS8wCALXUPA2CQXl0KBPbdXtFfN5gdPxt68M210lNTNFj6mSxooJdWX5ibB3w20JEv9vLMqyeFUlJDtEX7pb4kSZIInFi3rTZuOWIdWuTLfUJiVNxjpUuZFwA8xwVAUzNYvTvgs03ZoYRqAsW+CgnAh3rDWL3t8tMCULMfAD0H8CxzbH+NQQ4A9jeYQF3fHR1LE/fXdHkMNaWD8kyGwAAKaQBIpkJBWRsf1YeCEgOSvmtqrW3fnxTp+2kiYov21alNAkDL1zLWQdW2xQMMcX1eKwoA9edPFjnQG2AWVg+CsSAA8LSNg8w/N1cq7ksA8P7nAuBAT4CJyDwz3HC0BcCLaRsHwModtZztBYC4XwDgpt6RJY/gBo+JVNslL6/N+f12Tl59PRczgXQsN937SRY43StM+d5ION9nx5DILSeWyqvQCwDjmz4GQBt/LQIYOqqYX5FqXTaPgz3p5flSEgDcveohgDyXRwFgctK2NbNzCA50HJYNoO2vL2xJ0uYv51UAyA5btyH3YBz4WPtEdXt8J7p5fGxbe1DO9QmXFx0i98NdA8gcvecUp2bnkB59m4XLSTsxUcUpye0H4AbKVeES2Bd2BWGyGklSozuoKknat+hSuSpJtAMod8NdkvPtxq1w4pFbD684XtuMZ78n3Fx+u7hWdKxMuZnNQFuNvcMI6vqk8h1yIzuBqHB58XgKDiTDAChSKyrheMJT4cpvOULqWX4nRZKX4Walzslf/bVAABw0WW9sBX222OFKTdlLV3Sj7SQLSEoOaQtfdMet0yalLo6UzmE7yaZoQ99BVItJxE8uJgCQv0ySjSm7u/kTide3bq0DQEenftmZHTvVZCC5ghjQ55S5sD1//552UwsNKAwAtPBHMnk2UCG5gho8QPbWGoGLanpxKau1Kv26iumRNYzCQLKCvB5NudzvFdL4BctqoN4IA6Dio9EMYCJZpka0HNNaYt0C6rB1VUXeAwBSR25rJ/joz6ul784AKqYBeD/o8QCQB+sgjScsnOCAAkBKDz0snYujQ6U+o6KHrwio6WsuCbppEaQMBBmgV9dmy84o7WScFz3SQwuE4sMlQD5ZB2li0syhnggDmP7d8D8i1i2gzllBSA0tiNGxAhCNOzjU3gOQeHBjzaBxsA7SZAKwzlrqRsu/RUAerBM2QcEBhUkdfVw0tEVjAupw1g7CygrgLEjpDzHSf84Zl4U8WCekSa2g0wfpKKgzwsgMvzC1RbvLghz3bEeH/B5QbtVaECVBTiD507KDO0c0LpC5mXUFxQyCDWG7XmqCJvQnu0dGBw2RXWPaNO1R0bhAplzQDup2FpSYZYhtW8GSIDtIcRaErBUdMwmyexSLOQqyhdkhh//9n/kEOQiyRfwYpKyhoA00PgU8frMg5C8JWp94c97bqMR/qKdMxhtIpukAAAAASUVORK5CYII=
--------------------------------------------------------------------------------------------------------------------------------------
this is deer`s picture:
iVBORw0KGgoAAAANSUhEUgAAAEgAAABICAAAAABwhuybAAAEXUlEQVR4nO2XS2xbRRSG/5l7b/xSb2wnDqbBSdU0FcQUmsRZVCAkorZJumkrFWEkWLJgyZINC5bsQQKEVAkhNRKJRKWqjUiFEAgUkYRQtYQ+ZCc4jzbk4dgkaWzfOSwSP+7D9r3Jtmc198ycz/+ZmTMzBp6Zc2N959wAXGdjDEDTxY6DggJfXT8FoOv7L/wArox/xG2FmUcpHsUNwKO4FYB3QNABQaCKyGi39pc9kKzT8p/Yb3pdfkhNSvTtpvu/2eLoQBfPfjkNAGh7+bTqlYIfs8aGha9XHYOkUyd7pgFAes/L8iIHldIzo4/scSpB2mPRpWYAwLtwK1EAINZW8jY5utQmzr8Uv5YB+MKnf9uNtwTdGbt8uWtW8tG4c44OVPiWBqJRiELSOUcHQvbqw4FjDR4qHBbU/mane0MJy+e2Z7VDgFj3W01ZhZFGL4bGx2wvVzG63IzF/TMjZwYYh0Dh1k2HpHKtxeIqJZcfaqRpRPLgkGI3cM9KqcXiKjHCfoWSPIiamviQd3KuspyL4FhcJcALLyuRampiJ4Y+OFMxL0VFvXGVAOpTTkg2NQktcGm5YsNxAGCxd/wAQIH+SElu3XkSgV6jotbXsptySNKfafXnCWGpvN1kANB+JzraLxnH1SVJFZMkA0BWcvlebTAfqSQPSjef1tJkAG0pA17F6mgm+XxoLCUseqxB9AveCO5lxhViABVjifd13vlzYctUepVZASiVCGsMKQAg2j8JCrDtmaelgYzl0umcEcQiR4jf/ax8TuzvI0qn9xrJxCsaoC3Pl9MjOdRiToUI5A8vlL6NJbP73bYQgrfplpCE2Qig1vejVUH46Z4EUIvfzrVIR989WRW0el0AcEdscADRfEmtBsKNJQ6g1WvrphYdxTIxgx7c5gCpYVuSwHtc1UDaaIYBUti4UayNwoFqIExMcQCyTZBbrQrKjhYA8cRWYQCSUhWEHxKySM7ZU1SqDdmiK/XNlfUnebsgVAfRyPNHWJljyJFZ/4IVCKnp/nK0K6iP3NmwDxK3OyNFkgi+rp/H3amUVYz123dlZL3UwbjevLE2+yDcu5ood+lTI48lyTI1ALPLvd3HJQBM7EqGsuOntUVTQI1FDn8YIIAt/2xYNmrpyUvB4pf2+d2aigAUCADY6o/GA7vVxRtEs8Fp74+G3hjn+X/WioDQwUEAWG5+bW9W+IXYYUBguflFAgBqjEftgaosB9u6NskAgPzHgZqTvR9Q5VnKVh4tsT4C9t9m9RSxjV+tSSKhZYcny3LrKGLp4T+sO9YXgcwwSk+kOorYxJTZ6eMAJXcAbN7IFDXVS23H7JLaGNjW3p2+W8r7AMvf/BwBqU2D9wCgdheQSxrvT+cgXwRgj1eMbuegVpUgEqY94RgkHeNg60smv2NQcwuB5syL6RjU7gLbmjP7nYJ8EQCpjLmjVokwTtxY+y80guUTpBtTD7Q95iF23+icBnb+1Y95UEPMM6uw/wEb7IPCRqC/gwAAAABJRU5ErkJggg==

horse

图片](./6.jpg)deer![图片

图片](./6.jpg)deer![图片

根据官方说的知识点 KNN图像识别漏洞 单文件网页文件格式识别

审计代码得知需要进行图像操作使上传一个不能是马的图,但是需要识别成马,所以我们使用脚本对其进行修改,对鹿图进行弱化处理,再附加上马图,但是两图的距离(详情请看knn的图像识别原理)马图需要比鹿图增加得慢,这样才可以识别成鹿图。

knn原理带例子分析反正我是没看懂

大概就是要传一个72*72的图,欧氏距离和horse更近一点

解密exp如下,源自官方

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
#!/usr/bin/env python
# coding: utf-8
from PIL import Image
h = Image.open('horse.png')
d = Image.open('deer.png')
a,b = h.size
h_pixels = []
d_pixels = []
for y in range(b):
    for x in range(a):
        h_pixels.append(h.getpixel((x,y))//50)
        d_pixels.append(d.getpixel((x,y)))  
plt.imshow(np.array(h_pixels).reshape(72,72))
plt.show()
plt.imshow(np.array(d_pixels).reshape(72,72))
plt.show()
res1_png = Image.new('L',(a,b))
for y in range(b):
    for x in range(a):
        if d_pixels[x+a*y] != 0:
            res1_png.putpixel((x,y),d_pixels[x+a*y]-100)
        else:
            res1_png.putpixel((x,y),0)
for y in range(b):
    for x in range(a):
        res1_png.putpixel((x,y),res1_png.getpixel((x,y))+h_pixels[x+a*y]*33)
res1_png.save('deer1.png')
plt.imshow(res1_png)
plt.show()

从deer开始随手改了几个像素点为horse同位置的数值,然后保存为deer1.png,base64提交一下

图片

图片

收到一大串base64,扔进cyberchef解一下里面又有个base64,转图片得到flag。

Barbar

首先发现电脑端CQR和手机端扫描结果不一样,怀疑有隐藏信息

图片

图片

foremost分离文件

图片

图片

在线网站零宽字节隐写,扫描出隐藏密码

图片

图片

用该密码YcfVgMBUraXftwO6Cp92YBGAbyRyWNOO解压缩包得到

图片

图片

docx里暂无别的信息,选择先修二维码

图片

图片

队友修完后扫描结果为

图片

图片

修了个寂寞,于是倒回去继续看docx解码,在document.xml里发现base64图片

图片

图片

是个Aztec code,中国编码app扫出来

1
di`f{e1c64e14db14c6bb8faabab5bd7be1dc}

再进行npiet解密
在线网站

图片

图片

flag{f2d76g36fd16cbb6abaaf8db57cbd1ed}