直接进入正题,下载文件,无壳,直接使用ida打开找到关键函数: 程序过程很简单,有两个检查,一个if判断 首先查看第一个检查函数: 要求我们return v5,不能return -1 为了让我们的逻辑更加清楚,粗略写了一下C语言的代码:
int sub_80486CD(int a1){ v5 = 0; for(int i = 0; i <= 1024 && a1[i]; i = v5 * (v5 + 1) / 2){ v3 = 0; for(int j = 0;j <= v5; ++j) v3 += a1[i+j] if(1 << v5 != v3) return -1; ++v5; } return v5; }a1就是我们的输入,分析一下这个函数: 首先i=0,1,3,6,10,15, v3表示从a1[i]开始加v5个的和: a1[0] a1[1] + a1[2] a1[3] + a1[4] + a1[5] a1[6] + a1[7] + a1[8] + a1[9]
v5左移一位等于v3即可!!! 可以列出几个例子: a1[0] = 1 a1[1] + a1[2] = 2 a1[3] + a1[4] + a1[5] = 4 a1[6] + a1[7] + a1[8] + a1[9] = 8
接下来进入第二个函数: 这里也粗略写了一下C语言的代码:
int sub_8048783(int a1 , int a2){ v6 = 0; for(int i = 1;i < a2; ++i ){ v4 = 0; v3 = i - 1; if( !a1[i] ) return 0; while(a2 - 1 > v3){ v4 += a1[v3 * (v3 + 1) / 2 + v6]; v3++; } if(a1[v3 * (v3 + 1) / 2 + i] != v4) return 0; ++v6; } return 1; }题目的要求是让我们返回1,也就是说要我们把这个函数执行完成,这里存在两个参数 第一个自然是我们的输入,第二个类似于上面举例子的层数 由于这里的a2没变,而且后面的if条件需要我们将这个类似的层数等于20 所以我们现在就可以认为a2=20,接下来继续分析这个函数 首先a1里面的每个数都不能为0,由于程序有点复杂 我们可以将下标打印出来看一下结果,编写python:
v6 = v3 = 1 # 因为v3未变化前 v6=v3 a2 = 20 # 表示层数 i = 1 while a2 - 1 > v3: print(int(v3 * (v3 + 1) / 2 + v6)) v3 += 1 print(v3 * (v3 + 1) / 2 + i)由于20太大了,所以我就调小了层数,一点点尝试,得到结果: a1[2] = a1[0] = 1 a1[4] = a1[0] + a1[1] = 2 a1[5] = a1[2] = 1 a1[7] = a1[0] + a1[1] + a1[3] = 3 a1[8] = a1[2] + a1[4] = 3 a1[11] = a1[0] + a1[1] + a1[3] + a1[6] = 4 a1[12] = a1[2] + a1[4] + a1[7] = 6 a1[13] = a1[5] + a1[8] = 4
再结合上一个函数得出的结论,可以推出前几层的数: 1 1 1 1 2 1 1 3 3 1 1 4 6 4 1 … … … …
这里就很显然了,学过C语言的应该都敲过,杨辉三角嘛~~ 所以这里应该是让我们输入一个20层的杨辉三角!! 然后根据最后答案的提示: 去掉空格和换行进行MD5值加密,裹上RCTF{}提交即可 接下来就是编写python脚本了,附上解题脚本:
a = [] for i in range(0,20): b = [] for j in range(0,i + 1): b.append(1) a.append(b) print(a) for i in range(1,20): for j in range(1,i): a[i][j] = a[i - 1][j] + a[i - 1][j - 1] print(a) flag = "" for i in range(0,len(a)): for j in range(0,len(a[i])): flag += str(a[i][j]) print(flag)运行结果: md5加密得到: 得到flag:RCTF{37894beff1c632010dd6d524aa9604db}