说来惭愧,这题只能写写我的做法,好多我也没有分析出来,看得好心烦。
看图标就知道MFC写的窗体程序。拖入IDA,入口都不想去翻,直接查看字符串,好多。稍微翻下能看到KanXueCrackMe2017
字样和一串类似base64的字串,追到sub_406FC3
,像是验证算法。 再往上追,到sub_4071FD
,这时我比较确信这是主流程,而下层那个应该就是算法,看伪代码:
主流程根据算法流程的返回不同弹出三个不同的弹窗。
直接贴上算法流程的伪代码,菜鸡如我,只会f5。
先不说具体算法,先看流程。 似乎最后strcmp("Vm0wd2QyUXlVWGw==", &v11)
这比较成功,就行了。
但再看中间的__asm { int 2Dh; Windows NT - debugging services: eax = type }
这段。显示的调试坑啊。为了静态方便看正确的流程,我patch下代码,至于动态,网上说加了插件的OD直接过,我是把int 2D
改成int3
,再设置pass int3
过的,不然过不了,哎。
还是先看流程。校验一共有两处:一是v7
与v8
的48字节比较,不正确就返回0
;二是v11
长度是否为12
及sub_40680C(v11)
是否返回1
,若不是则返回2,是则返回1,即校验成功。
那v7
、v8
及v11
又是什么呢。下面开始理算法。
通过动静结合分析,v7
、v8
为sub_407307
初始化的48字节数组,其16进制表示为:
v8
后由sub_4084A3
函数两次(实际上内部是多次)修改。而v11
则是输入。
这里我们得到第一个比较明确的条件:
len(input) == 12
为了弄清楚v8
的最后值与输入的关系,得先弄清楚sub_407307
和sub_4084A3
这两个函数。
sub_407307
除了初始化了v7
,v8
,还通过v7
另外6个数组生成了6个48x48变换矩阵。这6组数组如下:
再看sub_4084A3
。
粗跟下,sub_40829C
似乎是一个转换,再将转换结果用作sub_4080DF
的矩阵计算。sub_4080DF
的变换是以v3/3
值为索引选择矩阵变换表,v3%3+1
则是转换次数,变换目标为前面说的v8
,变换实际上就是矩阵乘法。
那sub_40829C
的字符变换到底是一个什么过程呢。细跟了一次,没什么头绪,除了发现里面有点像是大数运算操作。
不断翻看代码。注意到矩阵运算前的v3
是由转换后的字符算术运算得到的,运算规则是:
若字符为数字 则v3 = v4-48 若字符为A-H 则v3 = v4-55
那转换后的字符范围是0-9 A-H
,v3范围是0-17
。而在sub_40829C
中也有类似的计算:
其中的v3
是取的输入字符,其范围是0-9 A-Z a-z
,v4
范围是0-61
。
似乎转换后的字符是18进制,其它的还是没有头绪。后经人提醒,加上验证,输入字符应该是62进制字串,转换过程就是62进制到18进制的转换,这就与上面的代码全对上了。这个可以从1个字节、2个字节输入慢慢测出来。
开始看到两个校验,且两个校验的输入是全输入,就想能不能通过一个校验就能得出答案。通常有两个校验的情况不外乎这么两种:一是两个校验均不能得到唯一解,只能相互补充条件得到唯一解;二是其中一个校验是冗余校验,且难于反解出答案。如果此题是第一种情况,可以尝试爆破,从校验一结果中找到唯一解;如果是另一种情况,那只能先看看校验一能不能解了,反正校验二看了更蒙。
刚才说了校验一处的v8
由sub_4084A3
分别以KanXueCrackMe2017
和输入改变了两次。改变过程就是多次的矩阵变换,实际上就是由参数控制实现两次互逆的变换。
看了很多矩阵的相关知识,没找到办法。后来仔细分析了变换矩阵,原来此中的绝技。以第一个变换矩阵来说,它是由第一个变换数组得到的:
看前8个元素,每变换一次,它们都是循环后移2个位置,m0[0:5]
后移,m0[6:7]
循环移动到前面,这样,每4次变换就是一个还原周期,其它位置的元素同样如此。
如:
对其它组变换矩阵进行了测试,同样如此。 也就是说
那就好办了。
运行记录第一次的变换操作
整理下,列表中的前面数值表示变换矩阵序号,后面数值表示变换次数:
看着这个就能直接写出逆变换操作:
计算出来的输入位数太多。细看操作列表,其中有好一些是可以合并操作的,进行合并,得新的操作列表:
出来结果校验直接通过,出乎意料,唯一结果。
校验二的代码现在是实在不想看,开始似乎看到了ecc,也是大数,如果有时间再补充吧。
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)