[资格赛题] 2018腾讯游戏安全竞赛第一轮PC进阶版分析

本文转载自:

https://www.52pojie.cn/thread-731852-1-1.html

0x00 概述

    程序接受了用户输入的用户名和***,要求用户名长度为39,格式为xxxx#xxxx#xxxx#xxxx#xxxx#xxxx#xxxx#xxxx,***则为变形AES加密后再用变形base64编码后的数据,要求解密后长度为32,最后一个DWORD为0,倒数第二个DWORD为0x32303138。
0x01 校验
    将格式化的用户名按照计算规则生成5个64位数据,计算过程用python表示如下:
用户名计算
[Python] 纯文本查看 复制代码
01
02
03
04
05
06
07
08
09
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
def process(a):        # total 8*5 = 40 char
        if a[4]!='#' or a[9]!='#' or a[14]!='#' or a[19]!='#' or a[24]!='#' or a[29]!='#' or a[34]!='#':
                print 'Format error'
                exit(0)
        a = ['']*8
        a[0] = serial[0:4]
        a[1] = serial[5:9]
        a[2] = serial[10:14]
        a[3] = serial[15:19]
        a[4] = serial[20:24]
        a[5] = serial[25:29]
        a[6] = serial[30:34]
        a[7] = serial[35:39]
 
        for i in a:
                for j in i:
                        if j not in '0123456789ABCDEF':
                                print 'Format error'
                                exit(0)
 
        target = [0]*5
 
        target[0] = ord(a[0][0])*ord(a[1][0])<<16
        target[0] += ord(a[0][1])^ord(a[2][1])
        target[0] += ord(a[0][2])%(ord(a[3][2])+1)+1
        target[0] += ord(a[0][3])/(ord(a[4][3])+1)
 
        target[1] = (ord(a[1][0])^ord(a[5][0]))<<16
        target[1] += ord(a[1][1])%(ord(a[6][1])+3)
        target[1] += ord(a[1][2])/(ord(a[7][2])+1)+5
        target[1] += ord(a[1][3])+ord(a[0][3])
 
        target[2] = (ord(a[2][0])/(ord(a[1][0])+3)) << 16
        target[2] ^= ord(a[2][1])%ord(a[3][1])
        target[2] += ord(a[2][2])+12+ord(a[5][2])
        target[2] += ord(a[2][3])+ord(a[7][3])
 
        target[3] = ord(a[2][3])^ord(a[0][1])
        target[3] *= ord(a[1][3])+ord(a[3][1])
        target[3] &= ord(a[4][2])&ord(a[5][2])
        target[3] *= ord(a[7][3])
        target[3] += target[1]
        target[3] *= ord(a[6][0])
        target[3] *= target[0]
 
        tmp = target[3]
        tmp -= target[1]
        tmp %= 2*target[0]
        target[3] -= tmp
 
 
        target[4] = (ord(a[3][0])^ord(a[4][0])) << 16
        target[4] *= ord(a[3][1])%(ord(a[4][1])+2)
        target[4] += ord(a[3][2])%(ord(a[4][2])+5) + 7
        target[4] += ord(a[3][3])*ord(a[4][3])
 
        return target
    将得到的5个64位数据与base64解密后的前三个DWORD进行比较,比较公式如下:
    [资格赛题] 2018腾讯游戏安全竞赛第一轮PC进阶版分析 
    将上式求解得到如下公式:
求解公式
[Python] 纯文本查看 复制代码
1
2
3
x = (d-b)/(2*a)
y = (d**2+4*a*c-b**2)/(4*a)
z = a*e**2+(b-d)*e+c
0x02 变形AES分析       
    首先AES的**扩展方式变了,不过无妨,可以从运行中的程序中直接提取,得到
    [资格赛题] 2018腾讯游戏安全竞赛第一轮PC进阶版分析 
      但在AES运行到2-9次**加时还会对2-9轮的轮**进行逆列混淆运算,同样,可提前计算出结果备用。计算函数如下(由于其轮**使用顺序以及列混淆的缘故,此处所有标为inv的函数或数据均为加密时使用,未标注的为解密时使用)
轮**变换
[Python] 纯文本查看 复制代码
01
02
03
04
05
06
07
08
09
10
def RoundKey_mix():
        key = key_expansion('clewgemobals8102')
        real = key[:16]
        for i in range(9):
                encdata = key_trans(key[(i+1)*16:(i+2)*16])
                encdata = Inv_ColumMix(encdata)
                encdata = inv_key_trans(encdata)
                real += encdata
        real += key[-16:]
        return real
    计算结果如下
    [资格赛题] 2018腾讯游戏安全竞赛第一轮PC进阶版分析 
       **加在执行过程中也发生了改变,原本应对位相加的方式在第3第4字节出发生了交换。变换后的**加函数如下:
**加
[Python] 纯文本查看 复制代码
1
2
3
4
5
6
7
8
def Key_xor(res,a2):
        result = list(res)
        for i in xrange(4):
                result[i] = chr(ord(result[i])^ord(a2[4*i]))
                result[4+i] = chr(ord(result[4+i])^ord(a2[4*i+1]))
                result[8+i] = chr(ord(result[8+i])^ord(a2[4*i+3]))
                result[12+i] = chr(ord(result[12+i])^ord(a2[4*i+2]))
        return ''.join(result)
       在进行字节代换时,代换表也发生了变化,代换表如下:
    [资格赛题] 2018腾讯游戏安全竞赛第一轮PC进阶版分析 
    可运算得到逆代换表如下
    [资格赛题] 2018腾讯游戏安全竞赛第一轮PC进阶版分析 
      在进行行变换时由原本的行变换变成了列变换。代码如下:
行变换
[Python] 纯文本查看 复制代码
1
2
3
4
5
6
def Inv_RowShift(res):
        result = list(res)
        result[1],result[5],result[9],result[13] = result[13],result[1],result[5],result[9]
        result[2],result[6],result[10],result[14] = result[10],result[14],result[2],result[6]
        result[3],result[7],result[11],result[15] = result[7],result[11],result[15],result[3]
        return ''.join(result)
       其列混淆则为列混淆的逆变换,直接使用即可,此处不给出。       根据分析结果对应的写出逆变换得到解密函数即可。
0x03 结果
     任给一组用户名:0000#A222#2222#2222#44F4#55D5#C666#7AB7
    求得***:Ou979Wh4Udz8ky9Y9ga#QSAssV&[email protected]+=
    [资格赛题] 2018腾讯游戏安全竞赛第一轮PC进阶版分析 
    结果:
    [资格赛题] 2018腾讯游戏安全竞赛第一轮PC进阶版分析