下载附件easyCpp,先查看文件信息:
是Linux下的64位ELF文件,运行程序:
是一个输入字符串然后判断是否正确的程序,错误就输入“You failed!” 之后用IDA64打开:
main函数源代码及注释:
int __cdecl main(int argc, const char **argv, const char **envp)
{
char v3;
__int64 v4;
__int64 v5;
__int64 v6;
__int64 v7;
__int64 v8;
__int64 v9;
__int64 v10;
char v11;
unsigned int *v12;
int i;
int j;
char v16[32];
char v17[32];
char v18[32];
char v19[32];
char v20[32];
__int64 a4[4];
__int64 a1[4];
char v23[72];
unsigned __int64 v24;
v24 = __readfsqword(0x28u);
std::vector<int>::vector((__int64)v16);
std::vector<int>::vector((__int64)v17);
std::vector<int>::vector((__int64)v18);
std::vector<int>::vector((__int64)v19);
std::vector<int>::vector((__int64)v20);
for ( i = 0; i <= 15; ++i )
{
scanf("%d", &v23[4 * i]);
std::vector<int>::push_back(v17, &v23[4 * i]);
}
for ( j = 0; j <= 15; ++j )
{
LODWORD(a1[0]) = fib(j);
std::vector<int>::push_back(v16, a1);
}
std::vector<int>::push_back(v18, v23);
v4 = std::back_inserter<std::vector<int>>(v18);
v5 = std::vector<int>::end(v17);
a1[0] = std::vector<int>::begin(v17);
v6 = __gnu_cxx::__normal_iterator<int *,std::vector<int>>::operator+(a1, 1LL);
std::transform<__gnu_cxx::__normal_iterator<int *,std::vector<int>>,std::back_insert_iterator<std::vector<int>>,main::{lambda(int)#1}>(
v6,
v5,
v4,
(__int64)v23);
std::vector<int>::vector((__int64)a4);
v7 = std::vector<int>::end(v18);
v8 = std::vector<int>::begin(v18);
std::accumulate<__gnu_cxx::__normal_iterator<int *,std::vector<int>>,std::vector<int>,main::{lambda(std::vector<int>,int)#2}>(
(__int64)a1,
v8,
v7,
(__int64)a4,
v9,
v10,
v3);
std::vector<int>::operator=(v19, a1);
std::vector<int>::~vector(a1);
std::vector<int>::~vector(a4);
if ( (unsigned __int8)std::operator!=<int,std::allocator<int>>(v19, v16) )
{
puts("You failed!");
exit(0);
}
std::back_inserter<std::vector<int>>(v20);
std::vector<int>::end(v17);
v11 = std::vector<int>::begin(v17);
std::copy_if<__gnu_cxx::__normal_iterator<int *,std::vector<int>>,std::back_insert_iterator<std::vector<int>>,main::{lambda(int)#3}>(v11);
puts("You win!");
printf("Your flag is:flag{");
a4[0] = std::vector<int>::begin(v20);
a1[0] = std::vector<int>::end(v20);
while ( (unsigned __int8)__gnu_cxx::operator!=<int *,std::vector<int>>(a4, a1) )
{
v12 = (unsigned int *)__gnu_cxx::__normal_iterator<int *,std::vector<int>>::operator*(a4);
std::ostream::operator<<(&std::cout, *v12);
__gnu_cxx::__normal_iterator<int *,std::vector<int>>::operator++(a4);
}
putchar(125);
std::vector<int>::~vector(v20);
std::vector<int>::~vector(v19);
std::vector<int>::~vector(v18);
std::vector<int>::~vector(v17);
std::vector<int>::~vector(v16);
return 0;
}
push_back()函数:将一个新的元素加到vector的最后面,位置为当前最后一个元素的下一个元素。 程序的逻辑就是首先保存输入的字符串到v17,然后计算斐波那契数列前16个数保存在v16,之后将v17经过主要的变换过程就是transform函数和accumulate函数,之后得到的结果和v16比较,通过就输出“You win!”,失败就输出“You failed!”。
首先查看transform函数:
transform函数源代码及注释:
__int64 __fastcall std::transform<__gnu_cxx::__normal_iterator<int *,std::vector<int>>,std::back_insert_iterator<std::vector<int>>,main::{lambda(int)#1}>(__int64 a1, __int64 a2, __int64 a3, __int64 a4)
{
unsigned int *v4;
__int64 v5;
__int64 v7;
__int64 v8;
__int64 v9;
__int64 v10;
int v11;
unsigned __int64 v12;
v10 = a1;
v9 = a2;
v8 = a3;
v7 = a4;
v12 = __readfsqword(0x28u);
while ( (unsigned __int8)__gnu_cxx::operator!=<int *,std::vector<int>>(&v10, &v9) )
{
v4 = (unsigned int *)__gnu_cxx::__normal_iterator<int *,std::vector<int>>::operator*(&v10);
v11 = main::{lambda(int)#1}::operator()(&v7, *v4);
v5 = std::back_insert_iterator<std::vector<int>>::operator*(&v8);
std::back_insert_iterator<std::vector<int>>::operator=(v5, &v11);
__gnu_cxx::__normal_iterator<int *,std::vector<int>>::operator++(&v10);
std::back_insert_iterator<std::vector<int>>::operator++(&v8);
}
return v8;
}
std::transform<__gnu_cxx::__normal_iterator<int *,std::vector<int>>,std::back_insert_iterator<std::vector<int>>,main::{lambda(int)#1}>(v6,v5,v4,(__int64)v23);
transform函数函数的作用就是把输入的字符串从第二个值开始v6逐个加上第一个值v23,直到最后一个值结束v5,结果保存在新的中间地址v4。 之后是accumulate函数:
accumulate函数源代码及注释
__int64 __fastcall std::accumulate<__gnu_cxx::__normal_iterator<int *,std::vector<int>>,std::vector<int>,main::{lambda(std::vector<int>,int)#2}>(__int64 a1, __int64 a2, __int64 a3, __int64 a4, __int64 a5, __int64 a6, char a7)
{
unsigned int v7;
__int64 v10;
__int64 v11;
__int64 v12;
char v13[32];
char v14[24];
unsigned __int64 v15;
v12 = a1;
v11 = a2;
v10 = a3;
v15 = __readfsqword(0x28u);
while ( (unsigned __int8)__gnu_cxx::operator!=<int *,std::vector<int>>(&v11, &v10) )
{
v7 = *(_DWORD *)__gnu_cxx::__normal_iterator<int *,std::vector<int>>::operator*((__int64)&v11);
std::vector<int>::vector(v13, a4);
main::{lambda(std::vector<int>,int)#2}::operator()(v14, &a7, v13, v7);
std::vector<int>::operator=(a4, v14);
std::vector<int>::~vector(v14);
std::vector<int>::~vector(v13);
__gnu_cxx::__normal_iterator<int *,std::vector<int>>::operator++(&v11);
}
std::vector<int>::vector(v12, a4);
return v12;
}
std::accumulate<__gnu_cxx::__normal_iterator<int *,std::vector<int>>,std::vector<int>,main::{lambda(std::vector<int>,int)#2}>((__int64)a1,v8,v7,(__int64)a4,v9,v10,v3); accumulate函数函数的作用就是前面transform函数计算得到的中间字符串v18,从起始地址v8到结束地址v7,转换顺序逆序排列,将结果再保存到输入字符串的地址a1中。 最后比较结果字符串v19和斐波那契数列前16个数v16是否逐个数相等。 程序的计算流程就是:
1、接收16个数字输入; 2、计算斐波那契数列前16项; 3、计算把输入的16个数字,从第二个数字开始,都加上第一个值; 4、将步骤3的计算的结果顺序,逆向排序 5、将步骤4计算的结果和步骤2的结果比较,完全相同则输出“You win!”
所以我们的逆向算法的过程就是:
1、计算斐波那契数列前16项; 2、将斐波那契数列前16项顺序,逆向排序 ; 3、把步骤2中得到的结果,从第二个数字开始,都减去第一个值,得到的数组就是正确的输入。
python代码:
def fib(num):
if not num or num == 1:
return 1
j = fib(num - 1)
return j + fib(num - 2)
flag = []
for i in range(16):
flag.append(fib(i))
print(flag)
flag = flag[::-1]
print(flag)
for i in range(1,len(flag)):
flag[i] = flag[i] - flag[0]
print(flag)
for i in range(16):
print(flag[i],end=" ")
运行结果: 将结果987 -377 -610 -754 -843 -898 -932 -953 -966 -974 -979 -982 -984 -985 -986 -986输入程序: 得到flag:flag{987-377-843-953-979-985}
|