首页
社区
课程
招聘
[原创]KCTF2020 第二题 异常信号 WriteUp
发表于: 2020-11-20 02:05 4398

[原创]KCTF2020 第二题 异常信号 WriteUp

2020-11-20 02:05
4398

肝了个一血出来哈哈哈

直接运行,然后x32dbg附加,注意开启sharpod的anti anti attach,然后ollydumpex,点search image,选择module、binary(virtual),dump下来,用ida打开,定位到sub_2F12B0函数

遇到30xxxx的地址,从x32dbg里查看到底是啥内容

解密脚本:

list中的值要满足的条件是:从[0,89]中选择12个互不相同的数,使它们任意两个数之差都不相同,这里我问了4位ACM金牌爷,2个多小时后有人把结果弄出来了

程序执行的思路就是,读入至多360个字符,只能0-9、A-F,把每4个输入组合成一个类似0x1234这样的short,如果与v31一样,则把下标加入v39队列,如果与v35一样,则继续,如果都不一样,则结束程序。如果v39的元素小于12则结束程序。之后会判断v39里面的数(也就是满足v31的输入的下标)是否两两之差唯一,是的话就输出Correct。

生成v31和v35的算法是可以本地写代码跑出来的,只要输入的满足“下标不在list里的输入等于v35,否则等于v31”的就是flag

补充金牌爷算法:

注意,这段代码能跑出多组解,但是其余解不满足程序的要求,会输出“穿越虫洞要讲究顺序”,因此上面那组解应该是唯一满足题目限制的解

 
int sub_2F12B0()
{
  int v0; // esi
  char v1; // al
  char *v2; // ecx
  unsigned __int8 *v3; // ecx
  unsigned __int8 v4; // al
  signed int v5; // eax
  signed int v6; // ecx
  signed int length; // ebx
  unsigned __int8 v8; // al
  char v9; // al
  signed int v10; // edx
  int v11; // esi
  char v12; // cl
  char v13; // al
  char v14; // cl
  signed int v15; // eax
  __int16 v16; // ax
  signed int half_len; // ebx
  int v18; // edi
  int v19; // ecx
  signed int v20; // esi
  signed int v21; // esi
  int v22; // eax
  int v23; // eax
  __int16 v24; // ax
  int v25; // esi
  int v26; // eax
  int v27; // ecx
  int v28; // edx
  int v29; // eax
  __int16 v31; // [esp+Ch] [ebp-514h]
  int v32; // [esp+10h] [ebp-510h]
  int v33; // [esp+14h] [ebp-50Ch]
  unsigned __int16 v34; // [esp+18h] [ebp-508h]
  __int16 v35; // [esp+18h] [ebp-508h]
  int v36; // [esp+1Ch] [ebp-504h]
  int v37; // [esp+20h] [ebp-500h]
  unsigned __int8 input; // [esp+23h] [ebp-4FDh]
  int v39[100]; // [esp+24h] [ebp-4FCh]
  char flag[400]; // [esp+1B4h] [ebp-36Ch]
  char table[256]; // [esp+344h] [ebp-1DCh]
  __int16 dest[50]; // [esp+444h] [ebp-DCh]
  char v43[100]; // [esp+4A8h] [ebp-78h]
  char v44; // [esp+50Ch] [ebp-14h]
  int v45; // [esp+50Dh] [ebp-13h]
  int v46; // [esp+511h] [ebp-Fh]
  int v47; // [esp+515h] [ebp-Bh]
  __int16 v48; // [esp+519h] [ebp-7h]
 
  v0 = *(_DWORD *)&unk_314474;
  memset(*(_DWORD *)&unk_314474, 0, 256);
  v1 = *(_BYTE *)&unk_3138B0;
  if ( *(_BYTE *)&unk_3138B0 )
  {
    v2 = (_BYTE *)&unk_3138B0;
    do
    {
      *(++v2 - 1) = v1 ^ 0xE4;
      v1 = *v2;
    }
    while ( *v2 );
  }
  sub_2F5D70(v0, 0x3138B0, strlen((const char *)&unk_3138B0) + 1);// Correct
  v45 = 0x9091948A;
  v46 = 0x9681B7C4;
  v3 = (unsigned __int8 *)&v44;
  v47 = 0xDE88858D;
  v4 = 0xADu;
  v48 = 0xEE;
  do
  {
    *(++v3 - 1) = v4 ^ 0xE4;
    v4 = *v3;
  }
  while ( *v3 );                                // Input Serial:\n
  v36 = **(_DWORD **)(*(_DWORD *)(*(_DWORD *)&unk_314478 + 0x3C) + *(_DWORD *)&unk_314478 + 0x28);
  printf(&v44);
  memset(v39, 0, 400);
  memset(dest, 0, 200);
  memset(flag, 255, 400);
  memset(table, 255, 256);
  v5 = 0;
  do
  {
    table[v5 + '0'] = v5;
    ++v5;
  }
  while ( v5 <= 9 );
  v6 = 0;
  do
  {
    table[v6 + 'A'] = v6 + 10;
    ++v6;
  }
  while ( v6 <= 5 );
  input = 0;
  length = 0;
  scanf(0x310CDC, &input, 1);                   // %c
  v8 = input;
  if ( input != 10 )
  {
    while ( length < 360 )
    {
      v9 = table[v8];
      if ( v9 == -1 )
      {
LABEL_52:
        printf(0x310C6C);
        printf(0x310C80);                       // 一个礼貌的开场白还是要的
        return 0;
      }
      flag[length++] = v9;
      scanf(0x310CDC, &input, 1);               // %c
      v8 = input;
      if ( input == '\n' )
        goto LABEL_14;
    }
LABEL_32:
    printf(0x310C6C);
    printf(0x310C70);                           // \f换页
    return 0;
  }
LABEL_14:
  v10 = 0;
  if ( length > 0 )
  {
    v11 = *(_DWORD *)&unk_31446C;
    while ( v11 )
    {
      v12 = flag[v10];
      if ( v12 == -1 )
        goto LABEL_52;
      v13 = flag[v10 + 1];
      if ( v13 == -1 )
        goto LABEL_52;
      v14 = v13 + 16 * v12;
      v15 = v10 >> 1;
      v10 += 2;
      *((_BYTE *)dest + v15) = v14;             // 4个输入构成一个int16
      if ( v10 >= length )
        goto LABEL_20;
    }
    goto LABEL_32;
  }
LABEL_20:
  v16 = 0;
  half_len = length >> 2;
  v18 = 0;
  v33 = 0;
  if ( half_len <= 0 )
    goto LABEL_57;
  v19 = 0;
  v32 = 0;
  do
  {
    v34 = -v16;
    sub_2F6305(v19);
    v20 = 0x65;
    do
    {
      v31 = sub_2F62E4();
      --v20;
    }
    while ( v20 );
    sub_2F6305(v34);
    v21 = 0x65;
    do
    {
      v35 = sub_2F62E4();
      --v21;
    }
    while ( v21 );
    v22 = (*(int (__stdcall **)(_DWORD))&unk_30B144)(0);// GetActiveWindow(0)
    if ( v22 )
    {
      v23 = (*(int (__stdcall **)(int))&unk_30B148)(v22);// GetWindowLongA(v22,GWL_STYLE)
      if ( v23 == 0x17CF0000 || v23 == 0x16CF0000 || v23 == 0x97CF0000 )
        goto LABEL_51;
    }
    v24 = dest[v32];                            // v32是满足条件v31的输入的index
    if ( v31 == v24 )
    {
      v39[v18++] = v32;                         // 将满足条件的index入队
    }
    else if ( v35 != v24 )
    {
      goto LABEL_52;
    }
    v16 = v33++ + 1;
    v19 = (unsigned __int16)v33;
    v32 = (unsigned __int16)v33;
  }
  while ( (unsigned __int16)v33 < half_len );
  if ( v18 < 12 )
  {
LABEL_57:
    printf(0x310C6C);
    printf(0x310C9C);                           // 行星太少了
    return 0;
  }
  if ( v39[1] - v39[0] > *(&v37 + v18) - *(&v36 + v18) )
  {
    printf(0x310C6C);
    printf(0x310CA8);                           // 穿越虫洞还得讲个顺序
    return 0;
  }
  memset(v43, 0, 100);
  v25 = 0;
  if ( v18 - 1 <= 0 )
  {
LABEL_49:
    if ( !*(_DWORD *)&unk_314470 )
      return 0;
    printf(*(_DWORD *)&unk_314474);             // Correct
    return 0;
  }
  v26 = v36;
  while ( 1 )
  {
    if ( !v26 )
    {
      printf(0x310C6C);
      printf(0x310C80);                         // 一个礼貌的开场白还是要的
LABEL_47:
      v26 = v36;
      goto LABEL_48;
    }
    v27 = v25 + 1;
    if ( v25 + 1 < v18 )
      break;
LABEL_48:
    if ( ++v25 >= v18 - 1 )
      goto LABEL_49;
  }
  v28 = v39[v25];
  while ( 1 )
  {
    v29 = v39[v27] - v28;                       // v29每次必须不一样
    if ( v43[v29] )                             // 队列中的indexes,两两的差必须唯一
      break;
    ++v27;
    v43[v29] = 1;
    if ( v27 >= v18 )
      goto LABEL_47;
  }
LABEL_51:
  printf(0x310C6C);
  printf(0x310CC0);                             // 有人说这题根本无解,你信吗
  return 0;
}
int sub_2F12B0()
{
  int v0; // esi
  char v1; // al
  char *v2; // ecx
  unsigned __int8 *v3; // ecx
  unsigned __int8 v4; // al
  signed int v5; // eax
  signed int v6; // ecx
  signed int length; // ebx
  unsigned __int8 v8; // al
  char v9; // al
  signed int v10; // edx
  int v11; // esi
  char v12; // cl
  char v13; // al
  char v14; // cl
  signed int v15; // eax
  __int16 v16; // ax
  signed int half_len; // ebx
  int v18; // edi
  int v19; // ecx
  signed int v20; // esi
  signed int v21; // esi
  int v22; // eax
  int v23; // eax
  __int16 v24; // ax
  int v25; // esi
  int v26; // eax
  int v27; // ecx
  int v28; // edx
  int v29; // eax
  __int16 v31; // [esp+Ch] [ebp-514h]
  int v32; // [esp+10h] [ebp-510h]
  int v33; // [esp+14h] [ebp-50Ch]
  unsigned __int16 v34; // [esp+18h] [ebp-508h]
  __int16 v35; // [esp+18h] [ebp-508h]
  int v36; // [esp+1Ch] [ebp-504h]
  int v37; // [esp+20h] [ebp-500h]
  unsigned __int8 input; // [esp+23h] [ebp-4FDh]
  int v39[100]; // [esp+24h] [ebp-4FCh]
  char flag[400]; // [esp+1B4h] [ebp-36Ch]
  char table[256]; // [esp+344h] [ebp-1DCh]
  __int16 dest[50]; // [esp+444h] [ebp-DCh]
  char v43[100]; // [esp+4A8h] [ebp-78h]
  char v44; // [esp+50Ch] [ebp-14h]
  int v45; // [esp+50Dh] [ebp-13h]
  int v46; // [esp+511h] [ebp-Fh]
  int v47; // [esp+515h] [ebp-Bh]
  __int16 v48; // [esp+519h] [ebp-7h]
 
  v0 = *(_DWORD *)&unk_314474;
  memset(*(_DWORD *)&unk_314474, 0, 256);
  v1 = *(_BYTE *)&unk_3138B0;
  if ( *(_BYTE *)&unk_3138B0 )
  {
    v2 = (_BYTE *)&unk_3138B0;
    do
    {
      *(++v2 - 1) = v1 ^ 0xE4;
      v1 = *v2;
    }
    while ( *v2 );
  }
  sub_2F5D70(v0, 0x3138B0, strlen((const char *)&unk_3138B0) + 1);// Correct
  v45 = 0x9091948A;
  v46 = 0x9681B7C4;
  v3 = (unsigned __int8 *)&v44;
  v47 = 0xDE88858D;
  v4 = 0xADu;
  v48 = 0xEE;
  do
  {
    *(++v3 - 1) = v4 ^ 0xE4;
    v4 = *v3;
  }
  while ( *v3 );                                // Input Serial:\n
  v36 = **(_DWORD **)(*(_DWORD *)(*(_DWORD *)&unk_314478 + 0x3C) + *(_DWORD *)&unk_314478 + 0x28);
  printf(&v44);
  memset(v39, 0, 400);
  memset(dest, 0, 200);
  memset(flag, 255, 400);
  memset(table, 255, 256);
  v5 = 0;
  do
  {
    table[v5 + '0'] = v5;
    ++v5;
  }
  while ( v5 <= 9 );
  v6 = 0;
  do
  {
    table[v6 + 'A'] = v6 + 10;
    ++v6;
  }
  while ( v6 <= 5 );
  input = 0;
  length = 0;
  scanf(0x310CDC, &input, 1);                   // %c
  v8 = input;
  if ( input != 10 )
  {
    while ( length < 360 )
    {
      v9 = table[v8];
      if ( v9 == -1 )
      {
LABEL_52:
        printf(0x310C6C);
        printf(0x310C80);                       // 一个礼貌的开场白还是要的
        return 0;
      }
      flag[length++] = v9;
      scanf(0x310CDC, &input, 1);               // %c
      v8 = input;
      if ( input == '\n' )
        goto LABEL_14;
    }
LABEL_32:
    printf(0x310C6C);
    printf(0x310C70);                           // \f换页
    return 0;
  }
LABEL_14:
  v10 = 0;
  if ( length > 0 )
  {
    v11 = *(_DWORD *)&unk_31446C;
    while ( v11 )
    {
      v12 = flag[v10];
      if ( v12 == -1 )
        goto LABEL_52;
      v13 = flag[v10 + 1];
      if ( v13 == -1 )
        goto LABEL_52;
      v14 = v13 + 16 * v12;
      v15 = v10 >> 1;
      v10 += 2;
      *((_BYTE *)dest + v15) = v14;             // 4个输入构成一个int16
      if ( v10 >= length )
        goto LABEL_20;
    }
    goto LABEL_32;
  }
LABEL_20:
  v16 = 0;
  half_len = length >> 2;
  v18 = 0;
  v33 = 0;
  if ( half_len <= 0 )
    goto LABEL_57;
  v19 = 0;
  v32 = 0;
  do
  {
    v34 = -v16;
    sub_2F6305(v19);
    v20 = 0x65;
    do
    {
      v31 = sub_2F62E4();
      --v20;
    }
    while ( v20 );
    sub_2F6305(v34);
    v21 = 0x65;
    do
    {
      v35 = sub_2F62E4();
      --v21;
    }
    while ( v21 );
    v22 = (*(int (__stdcall **)(_DWORD))&unk_30B144)(0);// GetActiveWindow(0)
    if ( v22 )
    {
      v23 = (*(int (__stdcall **)(int))&unk_30B148)(v22);// GetWindowLongA(v22,GWL_STYLE)
      if ( v23 == 0x17CF0000 || v23 == 0x16CF0000 || v23 == 0x97CF0000 )
        goto LABEL_51;
    }
    v24 = dest[v32];                            // v32是满足条件v31的输入的index
    if ( v31 == v24 )
    {
      v39[v18++] = v32;                         // 将满足条件的index入队
    }
    else if ( v35 != v24 )
    {
      goto LABEL_52;
    }
    v16 = v33++ + 1;
    v19 = (unsigned __int16)v33;
    v32 = (unsigned __int16)v33;
  }
  while ( (unsigned __int16)v33 < half_len );
  if ( v18 < 12 )
  {
LABEL_57:
    printf(0x310C6C);

[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

最后于 2020-11-20 20:24 被古月浪子编辑 ,原因: 补充求解算法
收藏
免费 1
支持
分享
最新回复 (1)
雪    币: 4709
活跃值: (1575)
能力值: ( LV2,RANK:15 )
在线值:
发帖
回帖
粉丝
2
冲了
2020-11-21 17:11
0
游客
登录 | 注册 方可回帖
返回
//