中石油CTF-斐波那契算法优化

拿到题目运行一下
中石油CTF-斐波那契算法优化_第1张图片
可以看到大致意思是找出一个数字要等于上方的这一串数据,放入IDA中看算法。
找到关键位置

unsigned __int64 __fastcall loadQuestion(unsigned int a1)
{
  int v1; // eax
  signed int v3; // [rsp+14h] [rbp-1Ch]
  signed int i; // [rsp+18h] [rbp-18h]
  signed int j; // [rsp+1Ch] [rbp-14h]
  __int64 v6; // [rsp+20h] [rbp-10h]
  unsigned __int64 v7; // [rsp+28h] [rbp-8h]

  v7 = __readfsqword(0x28u);
  printf("This is time %d, load questions...\n", a1);
  v6 = question(a1);
  v3 = 0;
  for ( i = 0; i <= 3; ++i )
  {
    for ( j = 0; j <= 99; ++j )
    {
      printf("testing number %d\n", (unsigned int)j);
      if ( func1(j) == v6 || func2(j) == v6 || func3(j) == v6 || func4(j) == v6 )
      {
        printf("\n=============>  Found number, is %d\n", (unsigned int)j);
        v3 = 1;
        v1 = key++;
        S[v1] = j;
        break;
      }
    }
    if ( v3 )
      break;
    printf("func%d is bad\n", (unsigned int)i);
  }
  if ( !v3 )
  {
    puts("system error, Exit!");
    exit(0);
  }
  return __readfsqword(0x28u) ^ v7;

程序逻辑大致为找8个数字,要求这8个数字在4个函数中只要一个满足能够等于这8个数字,8个数字如下
0x15F958A7E94CA61D, 0x18B3C1D91E77DECD, 0x20AC81D87D7EE6A3, 0x339FDF470F9FFFE0, 0x33DB76A7C594BFC3, 0x5226BC958D01E7E3, 0x6A241FC4441BADF3, 0x846597CABA82E6AC]
,这八个数次找到了flag依次就是这8个数字。。。。下图为强制修改跳转所得

中石油CTF-斐波那契算法优化_第2张图片
分别看一下这4个函数。。。

unsigned __int64 __fastcall func1(unsigned __int64 a1)
{
  unsigned __int64 v2; // rbx

  if ( a1 > 0x63 )
  {
    puts("Boom!");
    exit(0);
  }
  if ( a1 <= 2 )
    return a1;
  v2 = func1(a1 - 1);
  return v2 + func1(a1 - 2);
}
unsigned __int64 __fastcall func2(unsigned __int64 a1)
{
  unsigned __int64 v2; // rbx
  unsigned __int64 v3; // rbx

  if ( a1 > 0x63 )
  {
    puts("Boom!");
    exit(0);
  }
  if ( a1 <= 3 )
    return a1;
  v2 = func2(a1 - 1);
  v3 = func2(a1 - 2) + v2;
  return v3 + func2(a1 - 3);
}
unsigned __int64 __fastcall func3(unsigned __int64 a1)
{
  unsigned __int64 v2; // rbx
  unsigned __int64 v3; // rbx
  unsigned __int64 v4; // rbx

  if ( a1 > 0x63 )
  {
    puts("Boom!");
    exit(0);
  }
  if ( a1 <= 4 )
    return a1;
  v2 = func3(a1 - 1);
  v3 = func3(a1 - 2) + v2;
  v4 = func3(a1 - 3) + v3;
  return v4 + func3(a1 - 4);
}
]unsigned __int64 __fastcall func4(unsigned __int64 a1)
{
  unsigned __int64 v2; // rbx
  unsigned __int64 v3; // rbx
  unsigned __int64 v4; // rbx
  unsigned __int64 v5; // rbx

  if ( a1 > 0x63 )
  {
    puts("Boom!");
    exit(0);
  }
  if ( a1 <= 5 )
    return a1;
  v2 = func4(a1 - 1);
  v3 = func4(a1 - 2) + v2;
  v4 = func4(a1 - 3) + v3;
  v5 = func4(a1 - 4) + v4;
  return v5 + func4(a1 - 5);
}

是一个类似于斐波那契数列的算法。。。由于采用了递归导致计算速度过于缓慢,导致难以计算出结果,将其算法优化一下。
同时我们需要注意等于的数据为__ int64,而返回的数据为unsigned __int64 因此最好这题的代码用c将数据类型定义好。进行计算
四份计算代码如下

#include
#include
unsigned __int64  f(int n) {
	// write code here  
	unsigned __int64 f0 = 1;
	unsigned __int64 f1 = 2;
	unsigned __int64 f2 = 0;

	for (int i = 2; i < n; i++){
		f2 = f0 + f1;
		f0 = f1;
		f1 = f2;
	}
	return f2;
}

int main()
{
	__int64 a[8] = { 0x15F958A7E94CA61D, 0x18B3C1D91E77DECD, 0x20AC81D87D7EE6A3, 0x339FDF470F9FFFE0, 0x33DB76A7C594BFC3, 0x5226BC958D01E7E3, 0x6A241FC4441BADF3, 0x846597CABA82E6AC };
	for (int x = 0; x <= 7; x++)
	{
		for (int i = 10; i <= 0x63; i++)
		{


			if (f(i) == a[x])
			{
				printf("%d=====>%llx\n", i, a[x]);

			}

		}
	}
	system("pause");
}
#include
#include
unsigned __int64 fib1(int n) {
	// write code here  
	unsigned __int64 f0 = 1;
	unsigned __int64 f1 = 2;
	unsigned __int64 f2 = 4;
	unsigned __int64 f3=0;
	for (int i = 6; i < n; i++){
		f3 = f0 + f1+f2;
		f0 = f1;
		f1 = f2;
		f2 = f3;
	}
	return f3;
}
unsigned __int64 fib2(int n) {
	// write code here  
	unsigned __int64 f0 = 1;
	unsigned __int64 f1 = 2;
	unsigned __int64 f2 = 3;
	unsigned __int64 f3=0;
	for (int i = 6; i < n; i++){
		f3 = f0 + f1 + f2;
		f0 = f1;
		f1 = f2;
		f2 = f3;
	}
	return f3;
}
unsigned __int64 fib3(int n) {
	// write code here  
	unsigned __int64 f0 = 1;
	unsigned __int64 f1 = 1;
	unsigned __int64 f2 = 2;
	unsigned __int64 f3=0;
	for (int i = 6; i < n; i++){
		f3 = f0 + f1 + f2;
		f0 = f1;
		f1 = f2;
		f2 = f3;
	}
	return f3;
}
int main()
{
	__int64 a[8] = { 0x15F958A7E94CA61D, 0x18B3C1D91E77DECD, 0x20AC81D87D7EE6A3, 0x339FDF470F9FFFE0, 0x33DB76A7C594BFC3, 0x5226BC958D01E7E3, 0x6A241FC4441BADF3, 0x846597CABA82E6AC };
	for (int x = 0; x <= 7; x++)
	{
		for (int i = 10; i <= 0x63; i++)
		{
				if (fib1(i) * 3 + 2 * fib2(i) + fib3(i) == a[x])

				{
					printf("%d=====>%llx\n", i,a[x]);
				}
		}
	}
	system("pause");
}
#include
#include
unsigned __int64 fib1(int n) {
	// write code here  
	unsigned __int64 f0 = 1;
	unsigned __int64 f1 = 2;
	unsigned __int64 f2 = 4;
	unsigned __int64 f3=8;
	unsigned __int64 f4;
	for (int i = 8; i < n; i++){
		f4 = f0 + f1 + f2+f3;
		f0 = f1;
		f1 = f2;
		f2 = f3;
		f3 = f4;
	}
	return f3;
}
unsigned __int64 fib2(int n) {
	// write code here  
	unsigned __int64 f0 = 1;
	unsigned __int64 f1 = 2;
	unsigned __int64 f2 = 4;
	unsigned __int64 f3=7;
	unsigned __int64 f4;

	for (int i = 8; i < n; i++){
		f4 = f0 + f1 + f2+f3;
		f0 = f1;
		f1 = f2;
		f2 = f3;
		f3 = f4;
	}
	return f3;
}
unsigned __int64 fib3(int n) {
	// write code here  
	unsigned __int64 f0 = 1;
	unsigned __int64 f1 = 2;
	unsigned __int64 f2 = 3;
	unsigned __int64 f3=6;
	unsigned __int64 f4;
	for (int i = 8; i < n; i++){
		f4 = f0 + f1 + f2+f3;
		f0 = f1;
		f1 = f2;
		f2 = f3;
		f3 = f4;
	}
	return f3;
}
unsigned __int64 fib4(int n) {
	// write code here  
	unsigned __int64 f0 = 1;
	unsigned __int64 f1 = 1;
	unsigned __int64 f2 = 2;
	unsigned __int64 f3 = 4;
	unsigned __int64 f4;
	for (int i = 8; i < n; i++){
		f4 = f0 + f1 + f2 + f3;
		f0 = f1;
		f1 = f2;
		f2 = f3;
		f3 = f4;
	}
	return f3;
}
int main()
{
	__int64 a[8] = { 0x15F958A7E94CA61D, 0x18B3C1D91E77DECD, 0x20AC81D87D7EE6A3, 0x339FDF470F9FFFE0, 0x33DB76A7C594BFC3, 0x5226BC958D01E7E3, 0x6A241FC4441BADF3, 0x846597CABA82E6AC };
	for (int x = 0; x <= 7; x++)
	{

		for (int i = 10; i <= 0x63; i++)
		{


			if (fib1(i) * 4 + 3 * fib2(i) + 2 * fib3(i) + fib4(i) == a[x])

			{
				printf("%d======>%llx\n", i,a[x]);

			}

		}
	}
	system("pause");
}
#include
#include
unsigned __int64 fib1(int n) {
	// write code here  
	unsigned __int64 f0 = 1;
	unsigned __int64 f1 = 2;
	unsigned __int64 f2 = 4;
	unsigned __int64 f3 = 8;
	unsigned __int64 f4=16;
	unsigned __int64 f5;
	for (int i = 10; i < n; i++){
		f5 = f0 + f1 + f2 + f3+f4;
		f0 = f1;
		f1 = f2;
		f2 = f3;
		f3 = f4;
		f4 = f5;
	}
	return f4;
}
unsigned __int64 fib2(int n) {
	// write code here  
	unsigned __int64 f0 = 1;
	unsigned __int64 f1 = 2;
	unsigned __int64 f2 = 4;
	unsigned __int64 f3 = 8;
	unsigned __int64 f4 = 15;
	unsigned __int64 f5;
	for (int i = 10; i < n; i++){
		f5 = f0 + f1 + f2 + f3 + f4;
		f0 = f1;
		f1 = f2;
		f2 = f3;
		f3 = f4;
		f4 = f5;
	}
	return f4;
}
unsigned __int64 fib3(int n) {
	// write code here  
	unsigned __int64 f0 = 1;
	unsigned __int64 f1 = 2;
	unsigned __int64 f2 = 4;
	unsigned __int64 f3 = 7;
	unsigned __int64 f4 = 14;
	unsigned __int64 f5;
	for (int i = 10; i < n; i++){
		f5 = f0 + f1 + f2 + f3 + f4;
		f0 = f1;
		f1 = f2;
		f2 = f3;
		f3 = f4;
		f4 = f5;
	}
	return f4;
}
unsigned __int64 fib4(int n) {
	// write code here  
	unsigned __int64 f0 = 1;
	unsigned __int64 f1 = 2;
	unsigned __int64 f2 = 3;
	unsigned __int64 f3 = 6;
	unsigned __int64 f4 = 12;
	unsigned __int64 f5;
	for (int i = 10; i < n; i++){
		f5 = f0 + f1 + f2 + f3 + f4;
		f0 = f1;
		f1 = f2;
		f2 = f3;
		f3 = f4;
		f4 = f5;
	}
	return f4;
}
unsigned __int64 fib5(int n) {
	// write code here  
	unsigned __int64 f0 = 1;
	unsigned __int64 f1 = 1;
	unsigned __int64 f2 = 2;
	unsigned __int64 f3 = 4;
	unsigned __int64 f4 = 8;
	unsigned __int64 f5;
	for (int i = 10; i < n; i++){
		f5 = f0 + f1 + f2 + f3 + f4;
		f0 = f1;
		f1 = f2;
		f2 = f3;
		f3 = f4;
		f4 = f5;
	}
	return f4;
}

int main()
{
	__int64 a[8] = { 0x15F958A7E94CA61D, 0x18B3C1D91E77DECD, 0x20AC81D87D7EE6A3, 0x339FDF470F9FFFE0, 0x33DB76A7C594BFC3, 0x5226BC958D01E7E3, 0x6A241FC4441BADF3, 0x846597CABA82E6AC };
	for (int x = 0; x <= 7;x++)
	{
		for (int i = 11; i <= 0x63; i++)
		{
			if (fib1(i) * 5 + 4 * fib2(i) + 3 * fib3(i) + 2 * fib4(i) + fib5(i) == a[x])

			{
				printf("%d=====>%llx\n", i, a[x]);
			}

		}
	}
	system("pause");
}

最后计算出的结果为
99=====>6a241fc4441badf3
88=====>846597caba82e6ac

88=====>18b3c1d91e77decd
99=====>33db76a7c594bfc3

77=====>15f958a7e94ca61d
66=====>5226bc958d01e7e3

66======>20ac81d87d7ee6a3
77======>339fdf470f9fffe0
将其整理为flag为。。
flag{77_88_66_77_99_66_99_88}

你可能感兴趣的:(CTF-RE)