• buuoj[ACTF_Junior_2020]Splendid_MineCraft WriteUp


    Splendid_MineCraft

    题目标题就已经暗示这题是SMC了(self-modifying code)。

    工具:exeinfo,x32dbg和IDA7.0

    先丢进exeinfo里查看相关信息:

     用IDA打开:

    根据可以字符串“Wrong! ”直接锁定sub_401080为main函数。

    int sub_401080()
    {
      char *v0; // eax
      char *v1; // eax
      char *v2; // ST28_4
      signed int i; // [esp+14h] [ebp-54h]
      int v5; // [esp+20h] [ebp-48h]
      char Str1; // [esp+24h] [ebp-44h]
      char v7; // [esp+3Dh] [ebp-2Bh]
      int v8; // [esp+44h] [ebp-24h]
      __int16 v9; // [esp+48h] [ebp-20h]
      char v10[4]; // [esp+4Ch] [ebp-1Ch]
      __int16 v11; // [esp+50h] [ebp-18h]
      int v12; // [esp+54h] [ebp-14h]
      __int16 v13; // [esp+58h] [ebp-10h]
      int v14; // [esp+5Ch] [ebp-Ch]
      __int16 v15; // [esp+60h] [ebp-8h]
    
      sub_401020((const char *)&unk_404118, (unsigned int)"Welcome to ACTF_Splendid_MineCraft!");
      sub_401050((const char *)&unk_40411C, (unsigned int)&Str1);
      if ( strlen(&Str1) == 26 )
      {
        if ( !strncmp(&Str1, "ACTF{", 5u) && v7 == 125 )
        {
          v7 = 0;
          v0 = strtok(&Str1, "_");
          v12 = *(_DWORD *)(v0 + 5);
          v13 = *(_WORD *)(v0 + 9);
          v14 = *(_DWORD *)(v0 + 5);
          v15 = *(_WORD *)(v0 + 9);
          v1 = strtok(0, "_");
          v8 = *(_DWORD *)v1;
          v9 = *((_WORD *)v1 + 2);
          v2 = strtok(0, "_");
          *(_DWORD *)v10 = *(_DWORD *)v2;
          v11 = *((_WORD *)v2 + 2);
          dword_403354 = (int)dword_4051D8;
          if ( ((int (__cdecl *)(int *))dword_4051D8[0])(&v12) )
          {
            v5 = SBYTE2(v14) ^ SHIBYTE(v15) ^ (char)v14 ^ SHIBYTE(v14) ^ SBYTE1(v14) ^ (char)v15;
            for ( i = 256; i < 496; ++i )
              byte_405018[i] ^= v5;
            JUMPOUT(__CS__, &byte_405018[256]);
          }
          sub_401020("Wrong
    ");
        }
        else
        {
          sub_401020("Wrong
    ");
        }
      }
      else
      {
        sub_401020("Wrong
    ");
      }
      return 0;
    }

    由三个strtok函数可知,flag{}里的内容应该是被_分成了三个部分,根据输入长度猜测每个部分应该是6字节长(这三个部分我们分别称为flag_sec1,flag_sec2和flag_sec3)。

    flag_sec1

    因为是SMC基本上确定是要动态调试的,所以大致了解一下main函数的结构,就丢进x32dbg里开始调试。

    先搜索字符串,直接进入main函数:

     到call CB1050时调试会卡住,说明程序此时正在等待输入,于是我们可以得到:

    先随便输入一个flag:ACTF{123456_ABCDEF_abcdef}

    我们向下浏览会发现有三个strtok()函数,如图

    正好与IDA反编译的结果相吻合,所以这三个函数后面应该是对flag内容的比较。

    在最后一个strtok()函数后面打个断点,直接跳过中间的内容,然后进行单步调试,直到进入这个call。

     进入call后会发现很多奇怪的指令,这才进入到我们这篇WP真正的主题:SMC

     一步一步F7调试,会发现随着如下循环的进行,奇怪的汇编指令也会被改变:

     跳过SMC循环继续调试,会发现又有一个大循环:

     经过一遍又一遍的调试,会发现里面的三条关键指令:

    异或和求和的过程中并没有用到我们的输入,结果都储存到ss:[ebp+eax-20]里,直接运行完follow in dump:

     这就是上面循环得到的结果。

    阅读循环可知:00CB5332的cmp edx,ecx就是比较用户输入和flag的过程。

    flag_sec1 = yOu0y*

    flag_sec2

     这段也是SMC,修改后面jmp EAX里面的代码。

    重新调试,输入flag_sec1正确的字符串继续调试。没啥好说的,知道调试到jmp eax:

     一进去就遇到个循环,但是这个循环非常诡异,因为中间有多余代码,其实不断的调试就会发现,中间的多余代码是会被修改的!这其实就是SMC,但是本该是数据却被x32dbg识别成了代码而已,通过

    右键->Analysis->Treat from section as byte就可以将其转化为数据了,如下图:

    这个循环只是把用户输入的flag_sec2保存到了这个区域里(ABCDEF对应着41-46)。

    后面有个循环:

     (一边F7一边查看dump窗口。不好意思没看出来有啥用,估计是烟雾弹)

    其实就是EAX[flag_sec2[i]^(0x83+i)] == EAX[EDI+166]

    flag_sec2 = knowo3

    flag_sec3

    题目里直接明文strcmp,

    flag_sec3 = 5mcsM<

    综上:flag{yOu0y*_knowo3_5mcsM<}

  • 相关阅读:
    python hmac解密
    pymongo加索引以及查看索引例子
    语音-数字中继-E1-学习帖
    Partition does not start on physical sector boundary
    吃自助餐怎么样一个顺序吃法才合算?
    关于ROS证书导入的步骤
    MikroTik-ROS-无线设备传输距离
    这个移动通讯中 DB 、DBm 、瓦的基本知识的问题:
    涨姿势 | 无线通讯距离现场评估知多少?
    linux下生成https的crt和key证书
  • 原文地址:https://www.cnblogs.com/csuchenzc/p/13876127.html
Copyright © 2020-2023  润新知