0%

腾讯游戏安全2019

2019决赛是线下赛,网上也下载不到题目,就不给题解了。总的来说,还是2018年题目更有意思一些。

PC客户端安全-第一题

EasyJob-分析文档

进入main函数,如图:

EasyJob_p1

如图所示,获取到我们输入的responseCode以后,进行check1操作,对我们的responseCode进行格式解析

EasyJob_p2

输入的responseCode4个为一组,共4组,每组中的字符为0-9,且不能一组全为0,每组之间要以破折号-隔开。

在check2中

EasyJob_p3

sub_FBF960中对我们输入的4组responsecode进行了一系列计算,得到了4个QWORD类型的值,同时在上图中对去除破折号-后的字符串进行了减48累加的操作,得到第五个值。得到的这五个值,将被十进制化,然后作为十进制字符串连接在去除掉破折号的responsecode之后。

EasyJob_p4

最后以最终得到的字符串(去除掉破折号的输入以及5个值,将之作为字符串相连)作为message,输入的第一组responsecode作为key,进行sha256的hash计算,最后比较,相同,则注册成功。

我们在注册机中输入一组值得到注册码。如图:

EasyJob_register

输入程序,验证成功!

EasyJob_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
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
152
153
154
155
156
157
158
159
#!/usr/bin/env python2
#-*- coding:utf-8 -*-

import hashlib
import hmac
import base64


def toHex(str):
lst = []
for ch in str:
hv = hex(ord(ch)).replace('0x', '')
if len(hv) == 1:
hv = '0' + hv
lst.append(hv)
return reduce(lambda x, y: x + y, lst)

responseCode = raw_input("Please input your responseCode:")
inputString = responseCode
message = ""
Sum = 0
array1 = inputString.split("-")
for i in range(4):
for ch in array1[i]:
message += ch
Sum += ord(ch) - 48


secret = array1[0]
s1 = array1[0]
s2 = array1[1]
s3 = array1[2]
s4 = array1[3]

value1 = (ord(s1[0]) ^ ord(s4[0])) << 8
value1 += (ord(s1[1]) * ord(s4[1]))
value1 += (ord(s1[2]) / ord(s4[2]))
value1 += (ord(s1[2]) % ord(s4[2]))

#print hex(value1)

value2 = (ord(s2[0])*ord(s3[0])) << 8
value2 += (ord(s2[1])^ord(s3[1]))
value2 += ((ord(s2[2])%ord(s3[2])) + 32)
value2 += (ord(s1[2])/ord(s3[2]))

#print hex(value2)

value3 = (ord(s1[1])%ord(s1[3])) << 8
value3 += (ord(s2[1])/ord(s2[3]))
value3 += (ord(s3[1])*ord(s3[3])) + 8
value3 += (ord(s4[1])^ord(s4[3]))

#print hex(value3)

value4 = (ord(s1[0])^ord(s4[3])) << 8
value4 += (ord(s2[1])/ord(s3[2]))
value4 += (ord(s3[2])*ord(s2[1]))
value4 += (ord(s4[3])%ord(s1[0]))

#print hex(value4)


v39 = value4
v40 = value4 >> 29
v42 = 9*value4 >> 32
value4 *= 9
v43 = (value4 | ((v40+v42)<<32))
v41 = ((v43 >> 29) << 32) | (20 * (value1 + 2 * value3))

tmp2 = 30 * value2
tmp = (20*(value1 + 2*value3) >> 32)
tmp2 += (8 * value4) | (tmp << 32)
tmp2 += v41

tmp3 = 23 * value1 + 32 * value2 + 42 * value3 + 54 * v39

v41_low = 25 * value2 + 38 * value3 + 67 * v39
v43_high = (value1 >> 29) + (9*value1>>32)
v43_low = 9*value1
v41_high = v43 >> 31

v41 = (v41_high << 32) | v41_low
v43 = (v43_high << 32) | v43_low

tmp = (25 * value2 + 38 * value3 + 67 * v39) >> 32
v44 = ((18 * value1) | (tmp << 32)) + v41
tmp4 = v44

v43_high = (value1 >> 31) + (3 * value1 >> 32)
v43_low = 3 * value1
v43 = (v43_high << 32) | v43_low

tmp = ((v43 >> 30) << 32) | 12 * value1
v41_low = tmp + 45 * value2 + 33 * v39 + (value3 << 6)
v41_low = v41_low >> 32

v45 = (tmp2 >> 32)
v46 = (v45 >> 32) ^ (tmp2 & 0xffffffff)
if v46 < (v45 >> 32):
v42 = 1
else:
v42 = 0
tmp2_low = v46 - (v45 >> 32)
tmp2_high = ((v45 >> 32) ^ v45) - (v42 + (v45 >> 32))
tmp2 = (tmp2_high << 32) | tmp2_low
v47 = tmp3 & 0xffffffff

tmp3_high = tmp3 >> 32

v1 = (tmp3_high >> 31) ^ (tmp3_high)
v2 = (tmp3_high >> 31) ^ v47

v3 = ((tmp3_high >> 31) << 32) | (tmp3_high >> 31)
tmp3 = ((v1 << 32) | v2) - v3

tmp4_high = tmp4 >> 32
v1 = (tmp4_high >> 31) ^ (tmp4_high)
v2 = (tmp4_high >> 31) ^ (tmp4 & 0xffffffff)
v3 = ((tmp4_high >> 31) << 32) | (tmp4_high >> 31)
tmp4 = ((v1 << 32) | v2) - v3
tmp4 = tmp4 % 20

v1 = (v41_low >> 31) ^ v41_low
v2 = (v41_low >> 31) ^ ((12 * value1 + 45 * value2 + 33 * v39 + (value3 << 6)) & 0xffffffff)
v3 = ((v41_low >> 31) << 32) | (v41_low >> 31)
tmp5 = ((v1 << 32) | v2) - v3
tmp5 = tmp5 % 20

tmp5_high = tmp5 >> 32
tmp5_low = tmp5 & 0xffffffff
tmp4_low = tmp4 & 0xffffffff

#print hex(tmp2),hex(tmp3),hex(tmp4),hex(tmp5)


if (tmp4_high >= tmp5_high):
if((tmp4_high > tmp5_high) or (tmp4_low > tmp5_low)):
temp1 = tmp4_low
temp2 = tmp4_high
tmp4_low = tmp5_low
tmp4_high = tmp5_high
tmp5_low = temp1
tmp5_high = temp2

tmp4 = (tmp4_high << 32) | tmp4_low
tmp5 = (tmp5_high << 32) | tmp5_low
#print hex(tmp2),hex(tmp3),hex(tmp4),hex(tmp5)


message += str(tmp2)
message += str(tmp3)
message += str(tmp4)
message += str(tmp5)
message += str(Sum)
#print message

print "Here is the verification code:"
print toHex(hmac.new(secret,message,digestmod=hashlib.sha256).digest())

Rotate分析报告

Main函数:

Rotate_w1

在checkResponseCode里对输入的Requestcode进行的格式的验证,最终的验证结果和第一题EasyJob一致。输入的responseCode4个为一组,共4组,每组中的字符为0-9,且不能一组全为0,每组之间要以破折号-隔开。

分析checkVerificationCode函数:

Rotate_w2

在cal函数里实现了和EasyJob中差不多的算法,计算结果和EasyJob一致。此题和上一题在计算上的唯一不同在于,除了把requestcode和cal函数中计算出的5个值的十进制字符串连接到一起外,还加上了将图片灰度化以后返回的hash,将这些同样进行hmacSha256,密钥就是灰度图的hash,明文就是以上所有字符串的连接。

程序将flag图片旋转,灰度化,resize为8 * 8像素的图片,然后dct变换,最后进行hash。

主要操作在这两个函数中:

Rotate_w3

最后以最终得到的字符串,进行sha256的hash计算,最后比较,相同,则注册成功。

我们在注册机中输入一组值得到注册码。如图:

Rotate_p1

输入程序,验证成功!

Rotate_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
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
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
#!/usr/bin/env python2
#-*- coding:utf-8 -*-

import hashlib
import hmac
import base64
import numpy as np
import cv2

def getHash(image):
avreage = np.mean(image)
hash = []
for i in range(image.shape[0]):
for j in range(image.shape[1]):
if image[i,j] > avreage:
hash.append(1)
else:
hash.append(0)
return hash


def toHex(str):
lst = []
for ch in str:
hv = hex(ord(ch)).replace('0x', '')
if len(hv) == 1:
hv = '0' + hv
lst.append(hv)
return reduce(lambda x, y: x + y, lst)

responseCode = raw_input("Please input your responseCode:")
inputString = responseCode
message = ""
Sum = 0
array1 = inputString.split("-")
for i in range(4):
for ch in array1[i]:
message += ch
Sum += ord(ch) - 48


s1 = array1[0]
s2 = array1[1]
s3 = array1[2]
s4 = array1[3]

value1 = (ord(s1[0]) ^ ord(s4[0])) << 8
value1 += (ord(s1[1]) * ord(s4[1]))
value1 += (ord(s1[2]) / ord(s4[2]))
value1 += (ord(s1[2]) % ord(s4[2]))

#print hex(value1)

value2 = (ord(s2[0])*ord(s3[0])) << 8
value2 += (ord(s2[1])^ord(s3[1]))
value2 += ((ord(s2[2])%ord(s3[2])) + 32)
value2 += (ord(s1[2])/ord(s3[2]))

#print hex(value2)

value3 = (ord(s1[1])%ord(s1[3])) << 8
value3 += (ord(s2[1])/ord(s2[3]))
value3 += (ord(s3[1])*ord(s3[3])) + 8
value3 += (ord(s4[1])^ord(s4[3]))

#print hex(value3)

value4 = (ord(s1[0])^ord(s4[3])) << 8
value4 += (ord(s2[1])/ord(s3[2]))
value4 += (ord(s3[2])*ord(s2[1]))
value4 += (ord(s4[3])%ord(s1[0]))

#print hex(value4)


v39 = value4
v40 = value4 >> 29
v42 = 9*value4 >> 32
value4 *= 9
v43 = (value4 | ((v40+v42)<<32))
v41 = ((v43 >> 29) << 32) | (20 * (value1 + 2 * value3))

tmp2 = 30 * value2
tmp = (20*(value1 + 2*value3) >> 32)
tmp2 += (8 * value4) | (tmp << 32)
tmp2 += v41

tmp3 = 23 * value1 + 32 * value2 + 42 * value3 + 54 * v39

v41_low = 25 * value2 + 38 * value3 + 67 * v39
v43_high = (value1 >> 29) + (9*value1>>32)
v43_low = 9*value1
v41_high = v43 >> 31

v41 = (v41_high << 32) | v41_low
v43 = (v43_high << 32) | v43_low

tmp = (25 * value2 + 38 * value3 + 67 * v39) >> 32
v44 = ((18 * value1) | (tmp << 32)) + v41
tmp4 = v44

v43_high = (value1 >> 31) + (3 * value1 >> 32)
v43_low = 3 * value1
v43 = (v43_high << 32) | v43_low

tmp = ((v43 >> 30) << 32) | 12 * value1
v41_low = tmp + 45 * value2 + 33 * v39 + (value3 << 6)
v41_low = v41_low >> 32

v45 = (tmp2 >> 32)
v46 = (v45 >> 32) ^ (tmp2 & 0xffffffff)
if v46 < (v45 >> 32):
v42 = 1
else:
v42 = 0
tmp2_low = v46 - (v45 >> 32)
tmp2_high = ((v45 >> 32) ^ v45) - (v42 + (v45 >> 32))
tmp2 = (tmp2_high << 32) | tmp2_low
v47 = tmp3 & 0xffffffff

tmp3_high = tmp3 >> 32

v1 = (tmp3_high >> 31) ^ (tmp3_high)
v2 = (tmp3_high >> 31) ^ v47

v3 = ((tmp3_high >> 31) << 32) | (tmp3_high >> 31)
tmp3 = ((v1 << 32) | v2) - v3

tmp4_high = tmp4 >> 32
v1 = (tmp4_high >> 31) ^ (tmp4_high)
v2 = (tmp4_high >> 31) ^ (tmp4 & 0xffffffff)
v3 = ((tmp4_high >> 31) << 32) | (tmp4_high >> 31)
tmp4 = ((v1 << 32) | v2) - v3
tmp4 = tmp4 % 20

v1 = (v41_low >> 31) ^ v41_low
v2 = (v41_low >> 31) ^ ((12 * value1 + 45 * value2 + 33 * v39 + (value3 << 6)) & 0xffffffff)
v3 = ((v41_low >> 31) << 32) | (v41_low >> 31)
tmp5 = ((v1 << 32) | v2) - v3
tmp5 = tmp5 % 20

tmp5_high = tmp5 >> 32
tmp5_low = tmp5 & 0xffffffff
tmp4_low = tmp4 & 0xffffffff

#print hex(tmp2),hex(tmp3),hex(tmp4),hex(tmp5)


if (tmp4_high >= tmp5_high):
if((tmp4_high > tmp5_high) or (tmp4_low > tmp5_low)):
temp1 = tmp4_low
temp2 = tmp4_high
tmp4_low = tmp5_low
tmp4_high = tmp5_high
tmp5_low = temp1
tmp5_high = temp2

tmp4 = (tmp4_high << 32) | tmp4_low
tmp5 = (tmp5_high << 32) | tmp5_low
#print hex(tmp2),hex(tmp3),hex(tmp4),hex(tmp5)


message += str(tmp2)
message += str(tmp3)
message += str(tmp4)
message += str(tmp5)
message += str(Sum)
#print message

angle = Sum

# opencv deal with picture
img = cv2.imread("./flag.jpg")
#print rows,cols
#M = cv2.getRotationMatrix2D(center=(img.shape[1]/2, img.shape[0]/2), angle=96, scale=1.0)
M = cv2.getRotationMatrix2D((img.shape[1]/2, img.shape[0]/2), angle, 1.0)
#M = cv2.getRotationMatrix2D((img.shape[1]/2, img.shape[0]/2),90,1)
img = cv2.warpAffine(img,M,(img.shape[1], img.shape[0]))

img = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
img = cv2.resize(img,(8,8))
print img
img = img.astype(np.float32)
img_dct = cv2.dct(img)
print img_dct
hash1 = getHash(img_dct)
ans = ""
for ch in hash1:
ans += str(ch)

message += ans
secret = ans
#print message
#print secret

print "Here is the verification code:"
print toHex(hmac.new(secret,message,digestmod=hashlib.sha256).digest())

Invisiable-分析报告

题目分为3个Check,每一次输入一个number,如果最后通过校验,则会输出提示信息。动态调试需要patch掉反调试位置。3个Check主要思路如下:

  1. 第一处Check输入正确的值以后,把后缀为mp3的文件解密为了decode.py,把flag解密为了nice.png,同时获取了main.dll,在导出函数main_1的代码段写入了C2,0C,00,在输出flag的时候会导致程序崩溃,到时候需要手动patch掉。输入的值通过python的subprocess模块暴力求解。
  2. 第二处Check可以输入20192,20194,20196,20198四个值,主要是写入1.txt的内容,程序根据1.txt中的破折号-,对字符串进行分割,破折号之前的是需要异或的密文,破折号之后的是密钥,根据说明文档中提到的最后的flag为flag{xxxx},密钥又是4字节,所以可以倒推出写入1.txt的明文应该是flag{Sec,密钥为2019。
  3. 第三处Check对我们的输入进行了一个算法校验,通过写脚本得到该值,输入即可通过。脚本跑第三次算法计算时,没有出结果,使用前两次的输出结果,输入程序验证得到744110。

Invisiable_p1

程序最后进入main.dll的导出函数main_1输出我们的flag。如下图:

Invisiable_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
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
#!/usr/bin/env python2
#-*- coding:utf-8 -*-

from subprocess import *
import base64

print "First Check:"
p = Popen("Invisiable.exe",shell=True,stdin=PIPE,stdout=PIPE)
print p.stdout.readline()
for num in range(2019002,2020000):
str1 = str(num) + "\r\n"
p.stdin.write(str1)
Infor = p.stdout.readline()
if "Ok" in Infor:
print num,Infor
break
#2019153

#20192
print "third Check:"
for num in range(100000,1000000):
tmp1 = num/0x64%0xA + 10 * (num/0x3E8%0xA)
tmp1 *= (-2)
tmp2 = num/0x2710%0xA + 10 * (num/0x186A0%0xA)
tmp2 *= 1
tmp3 = num + 10 * (num/0xA%0xA - num/0xA)
tmp3 *= 1
if (tmp1 + tmp2 + tmp3) == 2:
tmp1 = num/0x64%0xA + 10 * (num/0x3E8%0xA)
tmp1 *= 2
tmp2 = num/0x2710%0xA + 10 * (num/0x186A0%0xA)
tmp2 *= 0
tmp3 = num + 10 * (num/0xA%0xA - num/0xA)
tmp3 *= (-8)
if (tmp1 + tmp2 + tmp3) == 2:
print num
tmp1 = num/0x64%0xA + 10 * (num/0x3E8%0xA)
tmp1 *= 5
tmp2 = num/0x2710%0xA + 10 * (num/0x186A0%0xA)
tmp2 *= (-4)
tmp3 = num + 10 * (num/0xA%0xA - num/0xA)
tmp3 *= 0
if (tmp1 + tmp2 + tmp3) == (-1):
print num
#744110
# calculate the key and get the plaintext
str1 = "VFxQXkljVFo="
str1 = base64.b64decode(str1)
key = ""
str2 = "flag{"
for i in range(4):
tmp = ord(str2[i]) ^ ord(str1[i])
key += chr(tmp)
print key

ans = ""
for i in range(len(str1)):
tmp = ord(str1[i]) ^ ord(key[i%4])
ans += chr(tmp)
print ans
#flag{Sec