XCTF 进阶 RE notsequence
直接进入正题,下载文件,无壳,直接使用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}