游戏过关 WriteUp

Author Avatar
ciaoly 2021年08月08日
  • 在其它设备中阅读本文章

题目来源: 游戏过关 - Bugku CTF

挺简单的一道签到题. 直接动态调试拿内存就行.

IDA静态分析

f5拿到伪代码

拖到IDA里打开, f5转伪代码, 一直跟踪函数跳转, 直到进入主函数_main_0. 得到程序主循环, 其代码大致如下:

void __cdecl main_0()
{
  //...
  while ( 1 )
  {
    while ( 1 )
    {
      sub_CCA7BE("input n,n(1-8)\n");
      sub_CC9418();
      sub_CCA7BE("n=");
      sub_CC96D4("%d", &v1);
      sub_CCA7BE("\n");
      if ( v1 >= 0 && v1 <= 8 )
        break;
      sub_CCA7BE("sorry,n error,try again\n");
    }
    if ( v1 )
    {
      sub_CC76D6(v1 - 1);
    }
    else
    {
      for ( i = 0; i < 8; ++i )
      {
        if ( (unsigned int)i >= 9 )
          j____report_rangecheckfailure();
        byte_DA2E28[i] = 0;
      }
    }
    j__system("CLS");
    sub_CC8054();
    if ( byte_DA2E28[0] == 1 && byte_DA2E28[1] == 1 && byte_DA2E28[2] == 1 && byte_DA2E28[3] == 1 && byte_DA2E28[4] == 1 && byte_DA2E28[5] == 1 && byte_DA2E28[6] == 1 && byte_DA2E28[7] == 1 )
    {
      sub_CC7AB4(); // 这里极有可能是打印flag的函数
    }
  }
}

直接跳到函数sub_CC7AB4, 一直追踪函数跳转情况, 得到关键代码如下所示:

int sub_CCE940()
{
  //...
  for ( i = 0; i < 56; ++i )
  {
    *(&v2 + i) ^= *(&v59 + i);
    *(&v2 + i) ^= 0x13u;
  }
  return sub_CCA7BE("%s\n");
}

此处即为打印flag的函数. 尝试使用x32dbg动态调试程序, 将内存里的flag数据拿出来.

动态调试

使用x32dbg加载程序, 在"内存布局"窗口查看代码段的基址,在IDA的edit->segments->rebase program处设置基址, 找到上文所述的函数sub_CC7AB4的地址, 在x32dbg中跳转到该地址, 在函数返回处设置断点.

在x32dbg中右键选择"设置新的运行点", 把EIP指到上述函数的循环体的起始处, 点击运行, 其会运行到返回语句处断掉, 此时即可在寄存器窗口看到flag

zsctf{T9is_tOpic_1s_v5ry_int7resting_b6t_others_are_n0t}