-
-
[原创]CTF2018第十三题分析(qwertyaa)
-
发表于: 2018-7-10 22:26 2901
-
首先看一遍main
函数,如下:
里面的所有字符串都简单加密了一下,动态调试即可得他们分别是key len error.
、key char error
、%lf
、Ohhh.Try again
、Come on, go on
、Congratulation
。
程序里的fabs
和浮点取负似乎不一定能够识别出来,在了解到COERCE_UNSIGNED_INT64
用于将参数强制转换为unsigned __int64
(等价于*(unsigned __int64*)(&x)
)以及double
的最高位是符号位后很容易手工识别出来。
而程序中的exp
函数可以通过函数中的一些魔数识别,sqrt
可以通过异常处理时用的字符串识别,将这两个函数重新命名后按F5可以识别出不少东西来。
而开头的initVals
、sub_401C50
似乎是在初始化一些东西,或许是在训练网络,里面的GetTickCount
似乎用于反调试,这一点和 lelfei 以前的CM很像。
输入后是判断输入的key是否长度为10,并将其进行“hex2bin
”,然后将结果放到两个double
高2/3byte上去。
接下来将其传入一个函数记作nnRun
,通过传递地址返回一个double
,接下来进行一些检查:
而阅读nnRun
可知,但传入double
不在(1,10)的范围内时返回的double
必为10.0,而这显然不满足条件1,而double
最高位是符号位,接下来是阶码,后面才是尾数,而改变key改变的是这两个double
的高位内容,所以所剩的key的可能数不多了(总共仅几百万种可能)。
但是由于前面两个用于初始化的函数执行的很慢,所以我们要直接Dump初始化结果,并自已实现一遍nnRun
才能较快穷举。
仔细看几遍,就可写出nnRun
的代码如下:
其中的wei*
是被前面所述的两个函数初始化的内容。
这似乎是一个两层的神经网络,第一层有sigmoid
函数,第二层直接乘权重,最后求和,这里似乎是在用神经网络模拟加法。(然而我并不懂神经网络,这些都是瞎猜的。(懂了似乎对这道题解题也没太大帮助。))
毕竟即使懂,由于神经网络很难被人类直接看懂,暴力是个不错的选择。
由第一段可知,所剩下的可能数已经不多,枚举可知double
的最高两bit必须在3ff1h-4023h
的范围内。
暴力的程序如下("defs.h"
是IDA的plugins文件夹下的头文件):
这个程序最后还会把枚举出来的正确密钥用NNCrackme.exe来验证一遍,当然这个其实是不必要的(因为我一开始省略了一些条件判断让NNCrackme.exe来直接判断)。
最后得到的key为F13FE02140
。
[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课