腾讯游戏安全技术移动平台资格题writeup
题目描述
题目要求输入key和code,匹配则会显示“success!”,否则显示“fail!”。
有standard和advance两个版本,advance比standard多一个函数,这里时间原因只做到了standard版本,最近每周都有ctf。
key相关
key只能是数字,字母a(A)~f(F),如果是小写,会被转为大写。
将keystr以”#”间隔,拆分,放入vector
sub_4864将keystr 拆分为8块,校验每块长度不为0
最后会对每块取值运算,要求每块4字节,所以结构是****#****#****#****#****#****#****#****
sub_496C函数传入keystr,生成5个int64,用于后面校验。
生成规则脚本里有,不作详解。大概就是每次运算取vector中两个项中各一字节,参与指定运算。前两个还算有规律,后面就没什么规律了。关于这里的代码,似乎是经过混淆,循环被平坦化了。
脚本是python的,所以对数据的类型处理不是很好,可能存在bug。好尴尬。
code相关
输入长度需要是偶数
长度需要是44(由生成数据的长度决定)
最后12字符确定()(由生产数据的最后9字节决定)
最后以”=”结束
sub_7114函数传入codestr,生成一个vector,用于后面校验。
每4字节生成3字节数据,根据字节在已知字符串"ZO6Kq79L&CPWvNopzQfghDRSG@di*kAB8rsFewxlm+/u5a^2YtTJUVEn0$HI34y#="
中的位置来确定数。
block[0]
block[1]->result[0]block[2]->result[1]
block[1]
block[2]~block[3]->result[2]
最后生成44/4*3=33字节数据
v11[3] != 0x32303138
决定生成的数据最后8字节,值为(int64)0x0000000032303138
由生成规则爆破(爆破代码在脚本注释中)得到“pKqE”、“NeZZ”、“ZZZ”。
所以code最后12字节为“pKqENeZZZZZ=”
验证函数
sub_5658传入key生成的5个int64数和code生成的前24字节数据。
参数作为8个int64参与运算。
1 | if ( ((a6 * a1 + a2) * a6 + a3) ^ a7 ) // ((S[0]*v18+v17)*S[0]+v16)==S[1] |
将code生成的数据当作未知数,整理数据:
1 | a=(4*CH18*CH18) |
可整理为一个二元一次方程。且delta=0,所以有唯一解。
注册机编写思路
要求由输入key来计算code,key可以生成5个int64,通过还原程序的计算过程,将5个数计算出来。此时验证函数中,把code的数据当作未知数,已有系数,由整理得到的方程解出S[0],再计算得出S[1],S[2]。
S[0],S[1],S[2]分别数code生成的前24字节组成的3个int64
得到code生成的数据后,反推code输入,已经知道了code的生成规则,和之前得到code的最后12个字节一样,爆破处理,每4字节生成3字节数据,那么就3字节3字节处理。
每3字节得到4字节输入,24/3*4=32,加上已知的12字节,32+12=44,正好输入44字节。
注册机使用
脚本测试环境:Python 2.7.14
MYKEY设置成key,注意格式。
运行脚本即可,最后输出的结果即是code.
几组跑出来的结果:
1 | ab1D#2BCE#A41B#EA2A#B3CD#8A0A#AB31#0FF0 |
截图: