资格赛进阶版题解
本帖最后由 echo579 于 2018-4-27 12:50 编辑第一次发帖,搞不动格式,贴上word吧
--------------------------------------------------
0x00 概述
程序接受了用户输入的用户名和注册码,要求用户名长度为39,格式为xxxx#xxxx#xxxx#xxxx#xxxx#xxxx#xxxx#xxxx,注册码则为变形AES加密后再用变形base64编码后的数据,要求解密后长度为32,最后一个DWORD为0,倒数第二个DWORD为0x32303138。
0x01 校验
将格式化的用户名按照计算规则生成5个64位数据,计算过程用python表示如下:
用户名计算
def process(a): # total 8*5 = 40 char
if a!='#' or a!='#' or a!='#' or a!='#' or a!='#' or a!='#' or a!='#':
print 'Format error'
exit(0)
a = ['']*8
a = serial
a = serial
a = serial
a = serial
a = serial
a = serial
a = serial
a = serial
for i in a:
for j in i:
if j not in '0123456789ABCDEF':
print 'Format error'
exit(0)
target = *5
target = ord(a)*ord(a)<<16
target += ord(a)^ord(a)
target += ord(a)%(ord(a)+1)+1
target += ord(a)/(ord(a)+1)
target = (ord(a)^ord(a))<<16
target += ord(a)%(ord(a)+3)
target += ord(a)/(ord(a)+1)+5
target += ord(a)+ord(a)
target = (ord(a)/(ord(a)+3)) << 16
target ^= ord(a)%ord(a)
target += ord(a)+12+ord(a)
target += ord(a)+ord(a)
target = ord(a)^ord(a)
target *= ord(a)+ord(a)
target &= ord(a)&ord(a)
target *= ord(a)
target += target
target *= ord(a)
target *= target
tmp = target
tmp -= target
tmp %= 2*target
target -= tmp
target = (ord(a)^ord(a)) << 16
target *= ord(a)%(ord(a)+2)
target += ord(a)%(ord(a)+5) + 7
target += ord(a)*ord(a)
return target
将得到的5个64位数据与base64解密后的前三个DWORD进行比较,比较公式如下:
将上式求解得到如下公式:
求解公式
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的密钥扩展方式变了,不过无妨,可以从运行中的程序中直接提取,得到
但在AES运行到2-9次密钥加时还会对2-9轮的轮密钥进行逆列混淆运算,同样,可提前计算出结果备用。计算函数如下(由于其轮密钥使用顺序以及列混淆的缘故,此处所有标为inv的函数或数据均为加密时使用,未标注的为解密时使用)
轮密钥变换
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
计算结果如下
密钥加在执行过程中也发生了改变,原本应对位相加的方式在第3第4字节出发生了交换。变换后的密钥加函数如下:
密钥加
def Key_xor(res,a2):
result = list(res)
for i in xrange(4):
result = chr(ord(result)^ord(a2))
result = chr(ord(result)^ord(a2))
result = chr(ord(result)^ord(a2))
result = chr(ord(result)^ord(a2))
return ''.join(result)
在进行字节代换时,代换表也发生了变化,代换表如下:
可运算得到逆代换表如下
在进行行变换时由原本的行变换变成了列变换。代码如下:
行变换
def Inv_RowShift(res):
result = list(res)
result,result,result,result = result,result,result,result
result,result,result,result = result,result,result,result
result,result,result,result = result,result,result,result
return ''.join(result)
其列混淆则为列混淆的逆变换,直接使用即可,此处不给出。 根据分析结果对应的写出逆变换得到解密函数即可。
0x03 结果
任给一组用户名:0000#A222#2222#2222#44F4#55D5#C666#7AB7
求得注册码:Ou979Wh4Udz8ky9Y9ga#QSAssV&pf2rBBSv@5ou7BS+=
结果:
历害历害,祝楼主取得好成绩! 看到轮密钥就头疼。。 过来学习进步 加油,祝楼主技术越来越高超 楼主 题目中的代码是什么语言 wh314 发表于 2018-5-8 20:08
楼主 题目中的代码是什么语言
做的PC版,C写的 我来学习一下{:301_1001:} 看着密密麻麻的字符就头疼了 祝楼主取得好成绩!