re | [NPUCTF2020]Baby Obfuscation

[NPUCTF2020]Baby Obfuscation

好久不写博客了,哦准确的说是好久都没有学习了。
最近听没有耐心的,看题也没有大段大段的时间仔仔细细的看,今天算是静下心来好好的砍了一个题,虽然只有9分233333.
学习还是需要有耐心的,恩。

64位的windowsRE,所有东西基本都在主函数,没什么反调试。

主程序:

int __cdecl main(int argc, const char **argv, const char **envp)
{
  int v3; // eax
  int v4; // ebx
  int v5; // esi
  int v6; // ebx
  int v7; // ebx
  int v8; // esi
  int v9; // edi
  int v10; // ebx
  int v11; // ebx
  int v12; // ebx
  int v13; // esi
  int v14; // eax
  int v15; // ebx
  int v16; // esi
  int v17; // ebx
  int v18; // eax
  bool v19; // bl
  int v20; // eax
  int v21; // esi
  int v22; // ebx
  int v23; // ebx
  int v24; // eax
  int v25; // eax
  int v26; // eax
  int v27; // eax
  int v28; // ebx
  int a[64]; // [rsp+20h] [rbp-60h]
  int v31; // [rsp+120h] [rbp+A0h]
  char input[1008]; // [rsp+130h] [rbp+B0h]
  int convert[1000]; // [rsp+520h] [rbp+4A0h]
  int v34; // [rsp+14C0h] [rbp+1440h]
  int v35; // [rsp+14D0h] [rbp+1450h]
  int v36; // [rsp+14D4h] [rbp+1454h]
  int v37; // [rsp+14D8h] [rbp+1458h]
  int v38; // [rsp+14DCh] [rbp+145Ch]
  int v39; // [rsp+14E0h] [rbp+1460h]
  int v40; // [rsp+14E4h] [rbp+1464h]
  int v41; // [rsp+14E8h] [rbp+1468h]
  int v42; // [rsp+14ECh] [rbp+146Ch]
  int len; // [rsp+14F0h] [rbp+1470h]
  int k; // [rsp+14F4h] [rbp+1474h]
  int j; // [rsp+14F8h] [rbp+1478h]
  int i; // [rsp+14FCh] [rbp+147Ch]

  _main();
  memset(convert, 0, sizeof(convert));
  v34 = 0;
  memset(a, 0, sizeof(a));
  v31 = 0;
  for ( i = 0; i <= 64; ++i )                   // 初始化一个65位的数组从0到64
    a[i] = i + 1;
  v39 = 2;                                      // 一些初始值 不知道干嘛的
                                                // 
  v40 = 3;
  v41 = 4;
  v42 = 5;
  v35 = 2;
  v36 = 3;
  v37 = 4;
  v38 = 5;
  puts("WHERE IS MY KEY!?");
  scanf("%32s", input);                         // 输入字符串32位
  len = strlen(input);                          // 获取长度
  v3 = F0X1(a[j], a[j]);                        // 递归求最大公约数
                                                // 
                                                // // FOX1 = gcd()
                                                // // FOX5 = pow()
                                                // // FOX4 = x-y
  for ( j = v3 / a[j]; j <= len; ++j )          // 遍历数组a
  {
    v4 = (a[j] + a[j + 1]) * (a[j] + a[j + 1]);
    if ( v4 >= F0X5(2, 2) * a[j] * a[j + 1] )
    {
      v5 = ~input[F0X4(j, 1)];
      v6 = F0X4(j, 1);
      convert[j] = ~(v5 + *(&v39 + v6 % F0X5(2, 2)));// F0X5( 2,2 )= 4
                                                // 
    }
    v7 = F0X1(a[j], a[j + 1]);
    if ( v7 > F0X1(a[j + 1], ~(~a[j + 1] + a[j])) )
    {
      v8 = convert[j];
      v9 = ~convert[j];
      v10 = F0X4(j, 1);
      convert[j] = ~(v9 + a[v10 % F0X5(2, 2)]) * v8;
    }
    v11 = a[j + 1];
    v12 = F0X5(2, 1) * v11;
    v13 = a[j];
    v14 = F0X5(2, 1);
    v15 = F0X1(v13 * v14, v12);
    v16 = F0X5(2, 1);
    if ( v15 == v16 * F0X1(a[j], a[j + 1]) )
    {
      v17 = F0X4(j, 1);
      convert[j] ^= *(&v39 + v17 % F0X5(2, 2));
    }
    v18 = F0X5(V0X3, a[j]);
    v19 = v18 < a[j] + 1;
    v20 = F0X5(2, 4);
    if ( F0X3(v20 >= j, v19) )
    {
      v21 = ~input[F0X4(j, 1)];
      v22 = F0X4(j, 1);
      convert[j] ^= ~(v21 + *(&v39 + v22 % F0X5(2, 2)));
    }
    v23 = F0X5(2, 3);
    v24 = F0X1(a[j], a[j]);
    convert[j] *= v23 + F0X5(2, v24 / a[j]);
  }
  v25 = F0X5(2, 4);                             // 16
  v26 = F0X4(v25, 1);                           // 15
  if ( v26 == len )                             // 输入长度为15
  {
    v27 = F0X1(a[k], a[k]);
    for ( k = v27 / a[k]; k <= len; ++k )
    {
      v28 = convert[k];
      if ( v28 == F0X4(A0X6[k], 1) / 10 )       // 这里是最后的判断
        ++V0X2;
    }
    if ( V0X2 == len )
      puts("\nPASS");
    else
      puts("\nDENIED");
  }
  else
  {
    puts("\nDENIED");
  }
  return 0;
}

分析一下不难发现每一位相对应的是有对应的值,当然其中的那些函数只不过是把程序复杂化的一种手段,很容易能看出来是啥作用,实在不行就动态调试一下就好了。
然后就是对于转化函数的爆破,这里本来想手动的,但是好像太多了,还是写了一下脚本,直接把程序贴出来改就好了。

exp:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int __cdecl F0X1(int a, int b)
{
  int result; // eax

  if ( b )
    result = F0X1(b, a % b);
  else
    result = a;
  return result;
}
int __cdecl F0X4(int a, int b)
{
  return ~(~a + b);
}

int __cdecl F0X5(int a, int b)
{
  int base; // [rsp+8h] [rbp-8h]
  signed int ans; // [rsp+Ch] [rbp-4h]
  int ba; // [rsp+28h] [rbp+18h]

  ba = b;
  ans = 1;
  base = a;
  while ( ba )
  {
    if ( ba & 1 )
      ans *= base;
    base *= base;
    ba >>= 1;
  }
  return ans;
}
bool __cdecl F0X2(bool a, bool b)
{
  return a == b && a != 1;
}

bool __cdecl F0X3(bool a, bool b)
{
  bool v2; // bl
  bool v3; // al
  bool aa; // [rsp+40h] [rbp-40h]

  aa = a;
  v2 = F0X2(b, b);
  v3 = F0X2(aa, aa);
  return F0X2(v3, v2);
}

int V0X2 =  0; 
int V0X3 = 3;
int A0X6[17] = {0, 0x1E79, 0x1E79, 0x2135,
0x170D, 0x1F41, 0x1901, 0x2CED,
0x11F9, 0x2649, 0x2581, 0x2DB5,
0x14B5, 0x25E5, 0x2A31, 0x30D5,
0};

int aim[15] = {0x30c,0x30c,0x352,0x24e,0x320,0x280,0x47e,0x1cc,0x3d4,0x3c0,0x492,0x212,0x3ca,0x438,0x4e2};


int main(int argc, const char **argv, const char **envp)
{
  int v3; // eax
  int v4; // ebx
  int v5; // esi
  int v6; // ebx
  int v7; // ebx
  int v8; // esi
  int v9; // edi
  int v10; // ebx
  int v11; // ebx
  int v12; // ebx
  int v13; // esi
  int v14; // eax
  int v15; // ebx
  int v16; // esi
  int v17; // ebx
  int v18; // eax
  bool v19; // bl
  int v20; // eax
  int v21; // esi
  int v22; // ebx
  int v23; // ebx
  int v24; // eax
  int v25; // eax
  int v26; // eax
  int v27; // eax
  int v28; // ebx
  int a[65]; // [rsp+20h] [rbp-60h]
  char input[1008]; // [rsp+130h] [rbp+B0h]
  int convert[1000]; // [rsp+520h] [rbp+4A0h]
  int v34; // [rsp+14C0h] [rbp+1440h]
  int v35; // [rsp+14D0h] [rbp+1450h]
  int v36; // [rsp+14D4h] [rbp+1454h]
  int v37; // [rsp+14D8h] [rbp+1458h]
  int v38; // [rsp+14DCh] [rbp+145Ch]
  int v39; // [rsp+14E0h] [rbp+1460h]
  int v40; // [rsp+14E4h] [rbp+1464h]
  int v41; // [rsp+14E8h] [rbp+1468h]
  int v42; // [rsp+14ECh] [rbp+146Ch]
  int len; // [rsp+14F0h] [rbp+1470h]
  int k; // [rsp+14F4h] [rbp+1474h]
  int j = 0; // [rsp+14F8h] [rbp+1478h]
  int i; // [rsp+14FCh] [rbp+147Ch]
  
  int vv39[4] = {2,3,4,5};

  memset(convert, 0, sizeof(convert));
  memset(a, 0, sizeof(a));
  for ( i = 0; i <= 64; ++i )                   // 初始化一个65位的数组从0到64
    a[i] = i + 1;
    
  v34 = 0;
  v35 = 2;
  v36 = 3;
  v37 = 4;
  v38 = 5;
  v39 = 2;                                      // 一些初始值 不知道干嘛的
  v40 = 3;
  v41 = 4;
  v42 = 5;
  j= 1;   // 这里要加初始值不然跑不起来 
  puts("WHERE IS MY KEY!?");
  scanf("%32s", input);                         // 输入字符串32位
  len = strlen(input);                          // 获取长度 长度应该为15 
  v3 = F0X1(a[j], a[j]);                        // 递归求最大公约数
                                                // 
                                                // // FOX1 = gcd()
                                                // // FOX5 = pow()
                                                // // FOX4 = x-y
  for ( j = v3 / a[j]; j <= len; ++j )          // 遍历数组a                
  {
  	for (char mmz = 33; mmz < 127; mmz ++){                    // 开始爆破!!!!! 
  		v4 = (a[j] + a[j + 1]) * (a[j] + a[j + 1]);
	    if ( v4 >= F0X5(2, 2) * a[j] * a[j + 1] )
	    {
	      v5 = ~mmz;    // 这里是输入点 
	      v6 = F0X4(j, 1);
	      convert[j] = ~(v5 + *(vv39 + v6 % F0X5(2, 2)));// F0X5( 2,2 )= 4
	                                                // 
	    }
	    v7 = F0X1(a[j], a[j + 1]);
	    if ( v7 > F0X1(a[j + 1], ~(~a[j + 1] + a[j])) )
	    {
	      v8 = convert[j];
	      v9 = ~convert[j];
	      v10 = F0X4(j, 1);
	      convert[j] = ~(v9 + a[v10 % F0X5(2, 2)]) * v8;
	    }
	    v11 = a[j + 1];
	    v12 = F0X5(2, 1) * v11;
	    v13 = a[j];
	    v14 = F0X5(2, 1);
	    v15 = F0X1(v13 * v14, v12);
	    v16 = F0X5(2, 1);
	    if ( v15 == v16 * F0X1(a[j], a[j + 1]) )
	    {
	      v17 = F0X4(j, 1);
	      convert[j] ^= *(vv39 + v17 % F0X5(2, 2));
	    }
	    v18 = F0X5(V0X3, a[j]);
	    v19 = v18 < a[j] + 1;
	    v20 = F0X5(2, 4);
	    if ( F0X3(v20 >= j, v19) )
	    {
	      v21 = ~mmz;
	      v22 = F0X4(j, 1);
	      convert[j] ^= ~(v21 + *(vv39 + v22 % F0X5(2, 2)));
	    }
	    v23 = F0X5(2, 3);
	    v24 = F0X1(a[j], a[j]);
	    convert[j] *= v23 + F0X5(2, v24 / a[j]);
	    
	    // 爆破条件判断
		if (convert[j] == aim[j-1]){
			printf("%c", mmz);
			break;
		} 
	}
	/* 
    v4 = (a[j] + a[j + 1]) * (a[j] + a[j + 1]);
    if ( v4 >= F0X5(2, 2) * a[j] * a[j + 1] )
    {
      v5 = ~input[F0X4(j, 1)];
      v6 = F0X4(j, 1);
      convert[j] = ~(v5 + *(vv39 + v6 % F0X5(2, 2)));// F0X5( 2,2 )= 4
                                                // 
    }
    v7 = F0X1(a[j], a[j + 1]);
    if ( v7 > F0X1(a[j + 1], ~(~a[j + 1] + a[j])) )
    {
      v8 = convert[j];
      v9 = ~convert[j];
      v10 = F0X4(j, 1);
      convert[j] = ~(v9 + a[v10 % F0X5(2, 2)]) * v8;
    }
    v11 = a[j + 1];
    v12 = F0X5(2, 1) * v11;
    v13 = a[j];
    v14 = F0X5(2, 1);
    v15 = F0X1(v13 * v14, v12);
    v16 = F0X5(2, 1);
    if ( v15 == v16 * F0X1(a[j], a[j + 1]) )
    {
      v17 = F0X4(j, 1);
      convert[j] ^= *(vv39 + v17 % F0X5(2, 2));
    }
    v18 = F0X5(V0X3, a[j]);
    v19 = v18 < a[j] + 1;
    v20 = F0X5(2, 4);
    if ( F0X3(v20 >= j, v19) )
    {
      v21 = ~input[F0X4(j, 1)];
      v22 = F0X4(j, 1);
      convert[j] ^= ~(v21 + *(vv39 + v22 % F0X5(2, 2)));
    }
    v23 = F0X5(2, 3);
    v24 = F0X1(a[j], a[j]);
    convert[j] *= v23 + F0X5(2, v24 / a[j]);*/
  }
  // 输出convert的结果来对比
  for (int mz = 1; mz <= len; mz ++){
  	printf("%x \n", convert[mz]);
  } 
  
  
  
  v25 = F0X5(2, 4);                             // 16
  v26 = F0X4(v25, 1);                           // 15
  if ( v26 == len )                             // 输入长度为15
  {
    v27 = F0X1(a[k], a[k]);
    for ( k = v27 / a[k]; k <= len; ++k )
    {
      v28 = convert[k];
      if ( v28 == F0X4(A0X6[k], 1) / 10 )       // 这里是最后的判断
        ++V0X2;
    }
    if ( V0X2 == len )
      puts("\nPASS");
    else
      puts("\nDENIED");
  }
  else
  {
    puts("\nDENIED");
  }
  return 0;
}

结果如下:

image

posted @ 2021-12-23 18:32  Mz1  阅读(71)  评论(0编辑  收藏  举报