XCTF-notsequence
查壳
32位ELF文件且无壳,直接拖入ida找到主函数,F5看伪代码。
ida静态分析
可以看出有两个关键函数sub_80486CD和sub_8048783依次进入查看逻辑。
sub_80486CD
第一个函数大体是遍历数组,将数组数据分成很多行,每行有v5+1个元素,并且每行元素的加和等于2^(v5),看到这里相信有的师傅也能猜到是杨辉三角了,为了完整理解算法接下来看另一个函数。
sub_8048783
第二个函数则判断每个元素都不为0,并且左斜线数据的和等于最后一行在他右下的数据,根据猜测,我们拿杨辉三角来分析。
这样基本能确定是杨辉三角了,再根据v5等于20可知道是前20行的数据,自己写或在网上找个杨辉三角的算法即可。
#include<iostream>
using namespace std;
int main(void)
{
int n;
cin >> n;
int(*arr)[34] = new int[n][34];
for (int i = 0; i < n; i++)
{
arr[i][0] = 1;
arr[i][i] = 1;
}
for (int i = 2; i < n; i++)
{
for (int j = 1; j < i; j++)
{
arr[i][j] = arr[i - 1][j - 1] + arr[i - 1][j];
}
}
for (int i = 0; i < n; i++)
{
for (int j = 0; j <= i; j++)
{
cout << arr[i][j];
}
}
delete[] arr;
return 0;
}
输出前20行数据,之后cmd5网站加密或python脚本按照flag的格式加密即可。
用z3解释器打出的非预期解
其实上面我们知道了v5其实他在第一个函数和第二个函数循环次数我们能够确定,所以可以通过c/c++将ida中的c代码拿出去跑,得到下标关系,之后列z3方程,用z3来解
这题思路类似一次校赛,用上次校赛的非预期wp来呈现一下。
from z3 import *
import hashlib
#for i in range(55):
# print('a'+str(i)+'='+'Int(\''+'a'+str(i)+'\')')
#for i in range(55)://多少元素 校赛上次是10行
# print('s.add(a'+str(i)+'!=0)')
a0=Int('a0')
a1=Int('a1')
a2=Int('a2')
a3=Int('a3')
a4=Int('a4')
a5=Int('a5')
a6=Int('a6')
a7=Int('a7')
a8=Int('a8')
a9=Int('a9')
a10=Int('a10')
a11=Int('a11')
a12=Int('a12')
a13=Int('a13')
a14=Int('a14')
a15=Int('a15')
a16=Int('a16')
a17=Int('a17')
a18=Int('a18')
a19=Int('a19')
a20=Int('a20')
a21=Int('a21')
a22=Int('a22')
a23=Int('a23')
a24=Int('a24')
a25=Int('a25')
a26=Int('a26')
a27=Int('a27')
a28=Int('a28')
a29=Int('a29')
a30=Int('a30')
a31=Int('a31')
a32=Int('a32')
a33=Int('a33')
a34=Int('a34')
a35=Int('a35')
a36=Int('a36')
a37=Int('a37')
a38=Int('a38')
a39=Int('a39')
a40=Int('a40')
a41=Int('a41')
a42=Int('a42')
a43=Int('a43')
a44=Int('a44')
a45=Int('a45')
a46=Int('a46')
a47=Int('a47')
a48=Int('a48')
a49=Int('a49')
a50=Int('a50')
a51=Int('a51')
a52=Int('a52')
a53=Int('a53')
a54=Int('a54')
s=Solver() #创建解容器
s.add(a1!=0) #add增加约束条件
s.add(a2!=0)
s.add(a3!=0)
s.add(a4!=0)
s.add(a5!=0)
s.add(a6!=0)
s.add(a7!=0)
s.add(a8!=0)
s.add(a9!=0)
s.add(a0==1)
s.add(a1+a2==2)
s.add(a3+a4+a5==4)
s.add(a6+a7+a8+a9==8)
s.add(a10+a11+a12+a13+a14==16)
s.add(a15+a16+a17+a18+a19+a20==32)
s.add(a21+a22+a23+a24+a25+a26+a27==64)
s.add(a28+a29+a30+a31+a32+a33+a34+a35==128)
s.add(a36+a37+a38+a39+a40+a41+a42+a43+a44==256)
s.add(a45+a46+a47+a48+a49+a50+a51+a52+a53+a54==512)
#第二层
s.add(a0+a1+a3+a6+a10+a15+a21+a28+a36-a46==0)
s.add(a2+a4+a7+a11+a16+a22+a29+a37-a47==0)
s.add(a5+a8+a12+a17+a23+a30+a38-a48==0)
s.add(a9+a13+a18+a24+a31+a39-a49==0)
s.add(a14+a19+a25+a32+a40-a50==0)
s.add(a20+a26+a33+a41-a51==0)
s.add(a27+a34+a42-a52==0)
s.add(a35+a43-a53==0)
s.add(a44-a54==0)
s.check()
print(s.model())
str="""
1
1 1
1 2 1
1 3 3 1
1 4 6 4 1
1 5 10 10 5 1
1 6 15 20 15 6 1
1 7 21 35 35 21 7 1
1 8 28 56 70 56 28 8 1
1 9 36 84 126 126 84 36 9 1"""
s=str.replace(' ','')
s=s.replace('\n','')
a=hashlib.md5()
a.update(s.encode())
print(('CUMTCTF{'+a.hexdigest()+'}'))
#思路错了 没想到杨辉三角 想起了z3 呜呜呜!
**可能是题目过滤比较少,出题人没有考虑到这个解法,有兴趣的师傅可以去了解下z3,挺好用的。**其实打出来z3的方程 看着也挺像杨辉三角的,麻了。
完结线:re弟弟的做题笔记,有时可能会带点稀奇古怪的思路,如有问题还望师傅们指正,专栏内容会随着比赛记录而不断更新哦。爬~