首页
社区
课程
招聘
[原创] KCTF2020 秋季赛 第五题 紧急救援
发表于: 2020-12-15 00:18 6853

[原创] KCTF2020 秋季赛 第五题 紧急救援

2020-12-15 00:18
6853

顺着start开始看逻辑。

主要是设置了一大堆东西,然后进入了函数401000。点进去一看是个VM。

回头看看start,顺着逻辑新建俩结构体。有些东西我也不知道是干啥的。大概是前面四个段链起来,后面又链了一个输入。

然后开始看VM内容。前面都是加减乘除,压栈啥的。但有俩操作比较迷,开始没看懂要是啥。就是memcpy,memset这两个。

然后开始写个脚本解析一下看看这段opcode讲了啥。对着opcode写完生成一遍发现。。。还是个VM。。。这不是套娃吗。

但比较良心的是,只是opcode的标号变了,其他的没变。所以脚本改改还能用。就是这俩memset,memcpy有了一点变化。这个参数看起来有点迷,先不管了。

想着再搞一层就出了,结果,发现又是套娃的一层VM。。。这次的memset和memcpy有点不一样了,之前的套娃方法有点问题,直接套出来更看不懂了。不如把这俩功能叫特殊功能,直接call个地址。这样子修完的好处在于,函数调用的参数就比较清楚了,并且不会因为memcpy参数为0而让F5自动忽略。。

就像这样子

而且这层VM出现了多个函数,鉴于下一层可能还是套娃,就先不细看多出来的函数了。

题目中CRC32的多项式和广泛流传的CRC32的多项式不太一样。

继续看下一层套娃。跟这层差不多,函数少了不少,这里就不抄了。

到了下下层套娃,终于是最终的了,没有VM了,抄上来看看。

可以看出,大概流程有调用特殊功能,验证,更改前面虚拟机的Code。

至此,逆向差不多就结束了,功能 MEMORY[0x10000] 调用了两次,翻看前面VM逻辑也可以看到,前面是通过函数参数来判断走哪个逻辑分支。

整理一下,大概是这个样子

剩下就是开始爆破,最后这个矩阵不太好爆破,规模有点大。特点就是改变一个点状态相邻点状态都会改变,感觉应该不是作者自己造出来的规则,像是个游戏。搜搜这个特点相关的,找到了生命游戏,黑白棋,点灯游戏。。。然后也就能网上搜到脚本和现成的解了。

 
 
struct seg{
    int pri;
    struct seg* next_seg; // 下一个段的信息
    char* addr_code; // 当前段代码指向
    int len;
    int zero;
    int idx;
    int dummy0;
    int dummy1;
};
 
struct inp{
    char * input;
    int *len; // 后面回头看,其实这是个大buf,里面存了长度,像是个大堆块
    struct seg* next_seg; // 指回第一个seg
};
struct seg{
    int pri;
    struct seg* next_seg; // 下一个段的信息
    char* addr_code; // 当前段代码指向
    int len;
    int zero;
    int idx;
    int dummy0;
    int dummy1;
};
 
struct inp{
    char * input;
    int *len; // 后面回头看,其实这是个大buf,里面存了长度,像是个大堆块
    struct seg* next_seg; // 指回第一个seg
};
                  if ( opcode != 40 )
                    break;
                  v26 = *(ssp + 2);
                  LOBYTE(eax_vm) = ssp[4];
                  BYTE1(eax_vm) = ssp[4];
                  v27 = *ssp;
                  v28 = eax_vm << 16;
                  LOWORD(v28) = eax_vm;
                  eax_vm = *(ssp + 2);
                  v29 = *ssp >> 2;
                  memset32(v26, v28, v29);
                  memset(&v26[4 * v29], v28, v27 & 3);
                  ebp_ = zzzz;
                }
                if ( opcode != 42 )
                  break;
                eax_vm = *(ssp + 2);
                qmemcpy(*(ssp + 2), *(ssp + 1), *ssp);
                ebp_ = zzzz;
              }
              ...
}
                  if ( opcode != 40 )
                    break;
                  v26 = *(ssp + 2);
                  LOBYTE(eax_vm) = ssp[4];
                  BYTE1(eax_vm) = ssp[4];
                  v27 = *ssp;
                  v28 = eax_vm << 16;
                  LOWORD(v28) = eax_vm;
                  eax_vm = *(ssp + 2);
                  v29 = *ssp >> 2;
                  memset32(v26, v28, v29);
                  memset(&v26[4 * v29], v28, v27 & 3);
                  ebp_ = zzzz;
                }
                if ( opcode != 42 )
                  break;
                eax_vm = *(ssp + 2);
                qmemcpy(*(ssp + 2), *(ssp + 1), *ssp);
                ebp_ = zzzz;
              }
              ...
}
 
    if ( opcode != 11 )
      break;
    v11 = esp_[1];
    v12 = v11 == 0x33333333;      // [esp + 1] == 0x33333333
    if ( v11 == 0x33333333 )
      v12 = *esp_ == 100;         // [esp] == 100
    if ( v12 )
      v12 = idx == 1;             // idx == 1
    if ( v12 )
    {
      v26 = a3;
      last_seg = a1;
      while ( v26 != 3 )          // 只有最后一块的parser.pri == 3
      {
        v26 = last_seg->pri;
        last_seg = last_seg->next_seg;
      }
      v24 = last_seg->pri;
      v23 = last_seg->next_seg;
      v13 = esp_[2];
      v5 = *esp_;
      v14 = esp_[2];
      v15 = *esp_ >> 2;
      memset32(esp_[2], esp_[2], v15);
      memset((v13 + 4 * v15), v14, v5 & 3);
      eax_vm = v14;
    }
    else
    {
      v16 = esp_[2];
      v17 = esp_[1];
      v5 = *esp_;
      v18 = esp_[2];
      v19 = *esp_ >> 2;
      memset32(esp_[2], esp_[2], v19);
      memset((v16 + 4 * v19), v18, v5 & 3);
      eax_vm = v18;
    }
  }
  if ( opcode != 15 )
    break;
  v20 = esp_[2];
  qmemcpy(esp_[2], esp_[1], 4 * (*esp_ >> 2));
  eax_vm = v20;
}
    if ( opcode != 11 )
      break;
    v11 = esp_[1];
    v12 = v11 == 0x33333333;      // [esp + 1] == 0x33333333
    if ( v11 == 0x33333333 )
      v12 = *esp_ == 100;         // [esp] == 100
    if ( v12 )
      v12 = idx == 1;             // idx == 1
    if ( v12 )
    {
      v26 = a3;
      last_seg = a1;
      while ( v26 != 3 )          // 只有最后一块的parser.pri == 3
      {
        v26 = last_seg->pri;
        last_seg = last_seg->next_seg;
      }
      v24 = last_seg->pri;
      v23 = last_seg->next_seg;
      v13 = esp_[2];
      v5 = *esp_;
      v14 = esp_[2];
      v15 = *esp_ >> 2;
      memset32(esp_[2], esp_[2], v15);
      memset((v13 + 4 * v15), v14, v5 & 3);
      eax_vm = v14;
    }
    else
    {
      v16 = esp_[2];
      v17 = esp_[1];
      v5 = *esp_;
      v18 = esp_[2];
      v19 = *esp_ >> 2;
      memset32(esp_[2], esp_[2], v19);
      memset((v16 + 4 * v19), v18, v5 & 3);
      eax_vm = v18;
    }
  }
  if ( opcode != 15 )
    break;
  v20 = esp_[2];
  qmemcpy(esp_[2], esp_[1], 4 * (*esp_ >> 2));
  eax_vm = v20;
}
 
MEMORY[0x10000](*arg, arg[1], arg[2]);
MEMORY[0x10000](*arg, arg[1], arg[2]);
    if ( code != 40 )
      break;
    v8 = arg[1];
    v9 = v8 == 1;
    if ( v8 == 1 )
      v9 = *arg == 100;
    if ( v9 )
      v9 = v27 == 2;
    if ( v9 )
    {
      v25 = a3;
      v24 = a2;
      while ( v25 != &loc_0 + 3 )
      {
        v25 = v24->input;
        v24 = v24->len;
      }
      input = v24->input;
      buf = v24->len;
      v10 = (buf + 16);
      *v10 = sub_895(input);      // 0xD540
      v11 = (buf + 8);
      *v11 = sub_A29((input + 4), buf + 256);// 0x4A752000
      v32 = MEMORY[0x10000](*arg, 0, arg[2]);
    }
    else
    {
      v12 = arg[1];
      v13 = v12 == 1;
      if ( v12 == 1 )
        v13 = *arg == 1600;
      if ( v13 )
        v13 = v27 == 2;
      if ( v13 )
      {
        v25 = a3;
        v24 = a2;
        while ( v25 != &loc_0 + 3 )
        {
          v25 = v24->input;
          v24 = v24->len;
        }
        input = v24->input;
        buf = v24->len;
        v14 = (buf + 8);
        *v14 = sub_F25((input + 32), (buf + 256));
        if ( *(buf + 2) == 2 )
        {
          v32 = MEMORY[0x10000](*arg, 1, arg[2]);
          sub_1E33(buf + 256, buf + 4096);
        }
      }
      else
      {
        v32 = MEMORY[0x10000](*arg, arg[1], arg[2]);
      }
    }
  }
  if ( code != 36 )
    break;
  v15 = arg[1] == arg[2];
  if ( arg[1] == arg[2] )
    v15 = *arg == 0;
  if ( v15 )
  {
    v15 = v27 == 3;
    if ( v27 != 3 )
      v15 = v27 == 2;
  }
  if ( v15 )
  {
    v25 = a3;
    v24 = a2;
    while ( v25 != &loc_0 + 3 )
    {
      v25 = v24->input;
      v24 = v24->len;
    }
    input = v24->input;
    buf = v24->len;
    v16 = (buf + 8);
    *v16 = sub_114B(0xFFFFFFFF, buf + 8); //crc,多项式为0xEB31D82
    v17 = (buf + 8);
    *v17 = sub_114B(0xFFFFFFFF, buf + 8);
    v18 = (buf + 8);
    *v18 = sub_114B(0xFFFFFFFF, buf + 8);
    v19 = (buf + 8);
    *v19 = sub_114B(0xFFFFFFFF, buf + 8);
    v32 = MEMORY[0x20000](*arg, arg[1], arg[2]);
  }
  else
  {
    v32 = MEMORY[0x20000](*arg, arg[1], arg[2]);
  }
}
    if ( code != 40 )
      break;
    v8 = arg[1];
    v9 = v8 == 1;
    if ( v8 == 1 )
      v9 = *arg == 100;
    if ( v9 )
      v9 = v27 == 2;
    if ( v9 )
    {
      v25 = a3;
      v24 = a2;
      while ( v25 != &loc_0 + 3 )
      {
        v25 = v24->input;
        v24 = v24->len;
      }
      input = v24->input;
      buf = v24->len;
      v10 = (buf + 16);
      *v10 = sub_895(input);      // 0xD540
      v11 = (buf + 8);
      *v11 = sub_A29((input + 4), buf + 256);// 0x4A752000
      v32 = MEMORY[0x10000](*arg, 0, arg[2]);
    }
    else
    {
      v12 = arg[1];
      v13 = v12 == 1;
      if ( v12 == 1 )
        v13 = *arg == 1600;
      if ( v13 )
        v13 = v27 == 2;
      if ( v13 )
      {
        v25 = a3;
        v24 = a2;
        while ( v25 != &loc_0 + 3 )
        {
          v25 = v24->input;
          v24 = v24->len;
        }
        input = v24->input;
        buf = v24->len;
        v14 = (buf + 8);
        *v14 = sub_F25((input + 32), (buf + 256));
        if ( *(buf + 2) == 2 )
        {
          v32 = MEMORY[0x10000](*arg, 1, arg[2]);
          sub_1E33(buf + 256, buf + 4096);
        }
      }
      else
      {
        v32 = MEMORY[0x10000](*arg, arg[1], arg[2]);
      }
    }
  }
  if ( code != 36 )
    break;

[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)

收藏
免费 1
支持
分享
最新回复 (0)
游客
登录 | 注册 方可回帖
返回
//