首页
论坛
课程
招聘
[原创]看雪.京东 2018CTF 第十三题 NeuralCrackme Writeup
2018-7-12 00:46 2108

[原创]看雪.京东 2018CTF 第十三题 NeuralCrackme Writeup

2018-7-12 00:46
2108

首先声明,本人对神经网络一窍不通,如有表述错误请见谅。
本题构造了一个四层人工神经网络模型,原始输入变换后形成的两个浮点数为输入进入网络计算,网络输出为一个浮点数,通过输入之和与输出之间的逼近精度、输出值的范围、原始输入的格式等方式进行检验,确定唯一解。

 

下面是基本按着做题过程叙述的。

代码分析

程序是MinGW64编译。试运行情况如下:
run

 

搜索字符串并未发现打印信息,原来所有字串全被异或编码了,脚本解码后情况如下:
string

 

正式开始分析程序。

主流程分析

开始进行一些数值的初始化后,要求输入key。
main1

 

接着检查输入key的长度为10,并进行unhex,要求输入为数字+A-F,否则转换结果不为5字节长度,报错退出。
main2

 

再接着将输入变换得到的5字节的前两字节赋值给一个64位浮点数的高位,后三字节赋值给另一个浮点数的高位,构造出两个浮点数,代入函数4015E0进行计算,然后检查计算结果。
main3
main4

 

照主流程来看,关键的计算函数4015E0应该就是题名说的神经网络了。
对于我这种既没有数学基础又不懂AI相关知道的人来说,太难为人了。
无法,滚去粗略学习了大约一晚上的神经网络。

计算函数分析

计算函数代码似乎比较简单,如下:
compute

 

按我一晚上的学习经验来看,这是个前馈神经网络FFNN(错了误怪),4层结构。
在第2层,18个神经元,两个输入加权求和后有一个sigmoid激活函数;第3层只是加权求和,后面还有个线性计算,我也把这归进来了。

 

具体计算过程代码中已经标出。

 

计算最后部分还有一个校验,网络输入的一个浮点数在(1,10)之间,否则计算的输出值为10.0,就不能通过主流程的check。

check分析

这神经网络似乎是理清了些(也不管对不对),但是怎么求解呢,不知道。先详细分析下check规则吧。

 

计算出来后,其结果以%lf格式覆盖原始输入。并检查第二字节为.,即计算结果s

0 < s < 10

 

计算结果的前三个数字的平方和不小于241,如果记s1,s2,s3为前三个数字,本来式子是:

sqrt(s1**2+s2**2+s3**2) > 15.5
因为s1,s2,s3都为整数,所以即
s1**2+s2**2+s3**2 > 240.25 >= 241
而 
240 /3 = 80
9*9 = 81
8*8 = 64
所以前三个数字必都为9

这是要逼近10啊。

 

此外还有一个校验,翻译一下,就是原始输入的第6字节为0。

 

下一个校验是:(记网络输入的两个浮点数为num1,num2)

abs(num1+num2-s) < 0.003

 

这是输出逼近输入和的意思啊,结合上面输入逼近10和网络输入值的范围,那几乎可以先假定题意设定网络输入为10或无限接近10。

 

整理下格式要求、主流程及计算流程的校验:

1. 输入长度为10,且字符范围是数字+A-F
2. 1<num1<10; 1<num2<10
3. num1+num2 == 10 (假定)
4. num1+num2-s < 0.003
5. input[5] == '0'

求解

这么多的条件限制,看来并不能从网络计算方法中得出结果的唯一性。开始还想从网络计算得出唯一结论,现在不管能不能就此得出,但是已经没有这个必要了。

 

因为,从上面的校验分析看出,实际上网络的计算过程已经不重要了,网络计算是死的,唯一变的是输入与输出,两个网络输入的浮点关系也是定的,如果定其中一个为变量,那么则可以将网络计算看来一个黑盒函数。

 

于是我就以第一个浮点数为变量,在输入范围内画出了墨盒函数。
figure1
下图为两段包含符合输出值要求的图:
figure2

 

纵轴0处为10,其上数值为相对10的偏移。
如果放大点范围,第一个浮点数的范围为:

1 < num1 < 1.125
8 < num1 < 8.2

本题还有个隐藏条件,是关于浮点数的。第一个浮点数实际上只用了输入的两个字节,第二个浮点数只用了输入的三个字节,其余字节为0。这两个数不是随便的浮点数,存储值是要符合字节格式要求的。据测试,num1其值应该是0.0625的倍数。在脚本求解的过程中,为防止错过解,将步长又进一步放小。

 

求解代码如下,求解范围作了调整:

import numpy as np
import struct
import os
import matplotlib.pyplot as plt

step = 0.00005


a = [ -1.0245,    0.0848024,
      -0.530959,  0.703843,
      -0.120586,  -0.313185,
      -0.765289,  0.339469,
      0.40869,    0.346429,
      -0.672084,  0.703138,
      0.479381,   0.145042,
      -0.758163,  -1.19117,
      -0.716324,  -0.185696,
      -0.388104,  -0.441494,
      0.749153,   -0.293723,
      -0.280767,  -0.660177,
      -1.13947,   -0.373301,
      -0.371646,  -0.320964,
      0.227951,   0.286258,
      -0.64833,   0.34251,
      0.101866,   -0.0669482,
      -0.799297,  0.277074]
a_1 = np.array([-1.0245, -0.530959, -0.120586, -0.765289, 0.40869, -0.672084, 
                0.479381, -0.758163, -0.716324, -0.388104, 0.749153, -0.280767,
                 -1.13947, -0.371646, 0.227951, -0.64833, 0.101866, -0.799297])
a_2 = np.array([0.0848024, 0.703843, -0.313185, 0.339469, 0.346429, 0.703138,
                0.145042, -1.19117, -0.185696, -0.441494, -0.293723, -0.660177, 
                -0.373301, -0.320964, 0.286258, 0.34251, -0.0669482, 0.277074])
w = [-0.119411,0.364227,-0.335042,-0.616251,1.03833,0.193202,
      1.00183,0.443425,-0.571216,-1.36825,0.158766,-1.15323,
      0.253585,-0.988879,0.611415,0.149166,0.518852,0.298557]


  #1.0625   8.9375
  ##flag:F13FE02140
def crack():
  i1 = 1
  while True:
    i1 = i1+step 
  #  i1 = 1.0625
    i2 = 10-i1
    x = (i1-0.01+1)/(9.99-0.01+1)
    y = (i2-0.03+1)/(9.99-0.03+1)
    l = []

    for i in range(18):
      t1 = x*a[2*i]
      t2 = y*a[2*i+1]
      l.append(1.0/(np.exp(-1*(t1+t2))+1))
    s = 0  
    ss = 0
    for i in range(18):
      s += l[i]*w[i]
    ss = s*(19.32-0.26+1)+0.26-1 

    if ss<10 and ss>9.997 :
      d1 = struct.pack('>d',round(i1,6))
      d2 = struct.pack('>d',round(i2,6))       
      if d1[2:] == '\x00'*6 and d2[3:] == '\x00'*5:
        print i1,d1.encode('hex').upper()
        print i2,d2.encode('hex').upper()
        print ss      
    if i1 >1.2:
      return


def dataplot(r1,r2,step):
  a1 = a_1.reshape(18,1)
  a2 = a_2.reshape(18,1)
  wi = np.array(w)
  X=np.arange(r1,r2,step)
  Y = 10-X
  x = (X-0.01+1)/(9.99-0.01+1)
  y = (Y-0.03+1)/(9.99-0.03+1)
  t1 = x*a1
  t2 = y*a2
  l = 1.0/(np.exp(-1*(t1+t2))+1)
  s = np.dot(l.T,wi)
  ss = s*(19.32-0.26+1)+0.26-1  
  plt.plot(X,ss)  


plt.figure(1)  
plt.subplot(111)
plt.grid()
dataplot(1,9,0.0005)
plt.figure(2) 
plt.subplot(211)
plt.grid() 
dataplot(1,1.2,0.0005)
plt.subplot(212)
plt.grid() 
dataplot(8,8.6,0.005)
plt.show()
crack()

最后flag:F13FE02140,两个浮点数为1.0625,8.9375。


【公告】看雪招聘大学实习生!看雪20年安全圈的口碑,助你快速成长!

最后于 2018-7-12 11:55 被poyoten编辑 ,原因: 修改笔误
收藏
点赞0
打赏
分享
最新回复 (4)
雪    币: 5694
活跃值: 活跃值 (694)
能力值: ( LV15,RANK:1426 )
在线值:
发帖
回帖
粉丝
lelfei 活跃值 23 2018-7-12 18:21
2
0
这个牛,基本分析出神经网络的结构了,赞一个
雪    币: 13422
活跃值: 活跃值 (1230)
能力值: ( LV15,RANK:2588 )
在线值:
发帖
回帖
粉丝
poyoten 活跃值 22 2018-7-12 19:28
3
0
lelfei 这个牛,基本分析出神经网络的结构了,赞一个
还不是猜错结构了
雪    币: 5694
活跃值: 活跃值 (694)
能力值: ( LV15,RANK:1426 )
在线值:
发帖
回帖
粉丝
lelfei 活跃值 23 2018-7-12 21:14
4
0
poyoten 还不是猜错结构了[em_5]
你的解法是最接近神经网络计算过程的,其他人都太暴力了
雪    币: 13422
活跃值: 活跃值 (1230)
能力值: ( LV15,RANK:2588 )
在线值:
发帖
回帖
粉丝
poyoten 活跃值 22 2018-7-12 21:28
5
0
lelfei 你的解法是最接近神经网络计算过程的,其他人都太暴力了[em_2]
太血腥了
游客
登录 | 注册 方可回帖
返回