题目链接: https://buuoj.cn/challenges#[MRCTF2020]EasyCpp
题目思路
首先不废话,直接丢 detect it easy 里面看看是什么玩意
可以看到这个东西是一个 Linux 可执行程序,没有加壳
那么我们直接丢入 IDA 开始干(大人,时代变了,最好用 IDA 7.5 版本的吧,7.0 貌似有些程序的某些函数是无法识别的)
这么恶心,一看就是一个 C++ 程序(部分函数和变量的名字已经被我替换掉了)
之后就是开始分析了,基本上逆向比的就是耐心
我们可以看到,程序一开始会让你输入 9 个数字,并把这 9 个数字存入 vector
然后我们可以看到这里有一个 lambda 表达式(相当于又些语言中的匿名函数)
这个 lambda 表达式对 vector 中的每个数据 ^ 1
之后就是一个循环,然后这个循环中,用一个 vector 迭代器迭代那个 vector 容器(不懂得自己去了解 STL 容器中的 vector 的用法哦)
其中一个比较关键的函数就是 depart 这个函数。这个函数的的等价代码
void depart(int data)
{
int current_result = data;
for (int i = 2; i <= std::sqrt(data); i++)
{
if (!(data % i))
{
current_result = i;
depart(data / i);
break;
}
}
cout << current_result << endl;
}
其实就是一个分解质因数的函数
然后这个题目中这个函数会把每个分解出来的质因数存入一个字符串,并且每个数字的前面用空格隔开(包括第一个数字,比如说 4 分解就是 2 * 2,那么最后会得到一个 2 2这样的字符串
之后有一个 lambda 表达式(我已经注释了)会对这个字符串进行替换操作,比如说 2 会被换成字母 z,空格会换成 =
这个就是那个转换表,下面就是数字,上面就是对应的转换后的字母。
v25 = 'O';
v26 = '0';
v27 = 'l';
v28 = '1';
v29 = 'z';
v30 = '2';
v31 = 'E';
v32 = '3';
v33 = 'A';
v34 = '4';
v35 = 's';
v36 = '5';
v37 = 'G';
v38 = '6';
v39 = 'T';
v40 = '7';
v41 = 'B';
v42 = '8';
v43 = 'q';
v44 = '9';
v45 = '=';
v46[0] = ' ';
后面的逻辑就是将转换后的字符串和程序中的目标字符串进行对比(标红的 lambda 表达式就是干这个的)
这个时候我们只要查看字符串,就可以看到我们所需要的转换后的字符串了
这样我们只要手动转化一下,然后 ^ 1,就可以算出那 9 个数字是什么了,这里就自己算吧。