[SCTF2019]creakme

这题用到的知识点很多,我们先一步步分析。
放到exeinfo和peid里面发现是32位无壳程序。
ida32打开。
首先看主函数:

int __cdecl main(int argc, const char **argv, const char **envp)
{
  HMODULE v3; // eax
  int v4; // eax
  _DWORD *v5; // eax
  unsigned int v6; // edx
  _DWORD *v7; // ecx
  unsigned int v8; // ebx
  char *v9; // edi
  unsigned int v10; // esi
  unsigned int v11; // esi
  bool v12; // cf
  unsigned __int8 v13; // al
  unsigned __int8 v14; // al
  unsigned __int8 v15; // al
  int v16; // esi
  void *v17; // ecx
  void *v18; // ecx
  const char *v19; // edx
  int v20; // eax
  void *Block[5]; // [esp+10h] [ebp-70h] BYREF
  unsigned int v23; // [esp+24h] [ebp-5Ch]
  void *v24[5]; // [esp+28h] [ebp-58h] BYREF
  unsigned int v25; // [esp+3Ch] [ebp-44h]
  char Src[48]; // [esp+40h] [ebp-40h] BYREF
  int v27; // [esp+7Ch] [ebp-4h]

  v3 = GetModuleHandleW(0);
  sub_402320(v3);                         //对.SCTF段数据SMC成可执行代码
  sub_4024A0();                           //调用SMC后的代码
  v4 = sub_402870(std::cout, "welcome to 2019 sctf");
  std::ostream::operator<<(v4, sub_402AC0);
  sub_402870(std::cout, "please input your ticket:");
  sub_402AF0(std::cin, Src);
  v24[4] = 0;
  v25 = 15;
  LOBYTE(v24[0]) = 0;
  sub_401D30(v24, Src, strlen(Src));
  v27 = 0;
  v5 = sub_4020D0(Block, v24);                  // aes加密算法,CBC模式,密码为sycloversyclover,偏移量为sctfsctfsctfsctf。
  v6 = strlen(aPvfqyc4ttc2uxr);                 // 获取字符串长度
  v7 = v5;
  if ( v5[5] >= 0x10u )
    v7 = *v5;
  v8 = v5[4];                                  
  v9 = aPvfqyc4ttc2uxr;
  v10 = v8;
  if ( v6 < v8 )
    v10 = v6;
  v12 = v10 < 4;                               
  v11 = v10 - 4;
  if ( v12 )
  {
LABEL_8:
    if ( v11 == -4 )
      goto LABEL_17;
  }
  else
  {
    while ( *v7 == *v9 )                        // 加密后的字符串与字符串aPvfqyc4ttc2uxr作比较
    {
      ++v7;                                     // v7是双字,v9是char型,v7自增1读取,v9就自增4
      v9 += 4;
      v12 = v11 < 4;
      v11 -= 4;
      if ( v12 )
        goto LABEL_8;
    }
  }
  v12 = *v7 < *v9;                              // v12==0
  if ( *v7 != *v9
    || v11 != -3
    && ((v13 = *(v7 + 1), v12 = v13 < v9[1], v13 != v9[1])
     || v11 != -2
     && ((v14 = *(v7 + 2), v12 = v14 < v9[2], v14 != v9[2])
      || v11 != -1 && (v15 = *(v7 + 3), v12 = v15 < v9[3], v15 != v9[3]))) )// *v7==*v9 。且v11==-3或者
                                                // if里的条件不能为1
  {
    v16 = v12 ? -1 : 1;
    goto LABEL_18;
  }
LABEL_17:
  v16 = 0;
LABEL_18:
  if ( !v16 )
  {
    if ( v6 <= v8 )
      v16 = v6 < v8;                            // v6==v8
    else
      v16 = -1;
  }
  if ( v23 >= 0x10 )
  {
    v17 = Block[0];
    if ( v23 + 1 >= 0x1000 )
    {
      v17 = *(Block[0] - 1);
      if ( (Block[0] - v17 - 4) > 0x1F )
        invalid_parameter_noinfo_noreturn();
    }
    sub_402F05(v17);
  }
  v27 = -1;
  Block[4] = 0;
  v23 = 15;
  LOBYTE(Block[0]) = 0;
  if ( v25 >= 0x10 )
  {
    v18 = v24[0];
    if ( v25 + 1 >= 0x1000 )
    {
      v18 = *(v24[0] - 1);
      if ( (v24[0] - v18 - 4) > 0x1F )
        invalid_parameter_noinfo_noreturn();
    }
    sub_402F05(v18);
  }
  v19 = "Have fun!";
  if ( v16 )                                    // v16==0
    v19 = "A forged ticket!!";
  v20 = sub_402870(std::cout, v19);
  std::ostream::operator<<(v20, sub_402AC0);
  system("pause");
  return 0;
}

首先看sub_402320和sub_4024A0这两个函数,
在这里插入图片描述在这里插入图片描述
首先我们注意到byte_404000是数据,但却在return后面作为函数运行,我们可以猜测是这里是smc。
对于sub_402320,我们结合汇编代码可以发现在DebugBreak函数和return之间有一段代码引用。
在这里插入图片描述
参考一些博主的wp我了解到sub_402320这个函数原来是通过调试器附加的方式来SMC修改。
程序运行过程中,该函数搜索到.SCTF区段后执行loc_4023EF代码,并在loc_4023EF中进行SMC。
在这里插入图片描述
要想运行那段代码需要结合OD。我们直接OD打开,因为有反调试,所以我们修改EIP为402421跳过反调试函数,然后运行loc_4023EF部分的代码,如下:
在这里插入图片描述
我们还可以进一步判断是402450函数进行SMC操作,单步步过修改数据为代码后,
接下来走出sub_402320这个函数,进入sub_4024A0函数,这个函数有两个跳转语句,一个跳到int 3中断,一个是exit函数,同样是反调试,修改EIP。
在这里插入图片描述
修改EIP后先不急着走出,我们可以进入smc后的404000函数,如下:
在这里插入图片描述
我们看寄存器窗口可以发现,这个smc后的函数一直在对字符串>pvfqYc,4tTc2UxRmlJ,sB{Fh4Ck2:CFOb4ErhtIcoLo操作,这个字符串其实是我们后面加密过后待比较的字符串,直接运行出看这个函数对该字符串进行了怎样的处理。
在这里插入图片描述
我们发现这个字符串变成了nKnbHsgqD3aNEB91jB3gEzAr+IklQwT1bSs3+bXpeuo=
接下来就可以分析加密函数sub_4020D0和sub_401690了,

int __thiscall sub_401690(int this, int a2, int a3, int a4, int a5)
{
  int v5; // ebx
  int v6; // eax
  int v7; // eax
  BOOL v8; // eax
  int v9; // ecx
  int v10; // esi
  int v11; // eax
  int v12; // ecx
  char *v13; // edx
  int v14; // edx
  char *v15; // esi
  const char *v16; // esi
  int v17; // kr04_4
  int *v18; // edx
  int result; // eax
  int v20; // edi
  int v21; // ebx
  int v22; // eax
  int v23; // edx
  int v24; // ecx
  int v25; // esi
  int v26; // edi
  int v27; // eax
  int v28; // eax
  int v29; // et2
  int v30; // ecx
  int v31; // edx
  char *v32; // eax
  int v33; // ecx
  int v34; // ecx
  int v35; // edx
  int v36; // eax
  int v37; // eax
  int v38; // edx
  int v39; // ecx
  int v40; // edx
  int v41; // ecx
  int v42; // eax
  _DWORD *v43; // ecx
  __int64 v44; // rax
  __int64 v45; // rt2
  int v46; // ecx
  int *v47; // edx
  int *v48; // esi
  int v49; // edi
  int v50; // edx
  int v52; // [esp+Ch] [ebp-18h]
  int v53; // [esp+Ch] [ebp-18h]
  int v54; // [esp+10h] [ebp-14h]
  int *v55; // [esp+10h] [ebp-14h]
  int *v56; // [esp+14h] [ebp-10h]
  _DWORD *v57; // [esp+14h] [ebp-10h]
  int *v58; // [esp+18h] [ebp-Ch]
  char *v59; // [esp+18h] [ebp-Ch]
  int v60; // [esp+1Ch] [ebp-8h]
  int v61; // [esp+20h] [ebp-4h]

  v5 = this;
  *(this + 972) = 16;
  *(this + 968) = 16;
  *(this + 980) = xmmword_407360;
  memcpy((this + 1012), &xmmword_407360, *(this + 972));
  v6 = *(v5 + 968);
  if ( v6 == 16 )
  {
    v9 = *(v5 + 972);
    if ( v9 == 16 )
    {
      v7 = 10;
      goto LABEL_9;
    }
    v8 = v9 != 24;
  }
  else
  {
    if ( v6 != 24 )
    {
      v7 = 14;
      goto LABEL_9;
    }
    v8 = *(v5 + 972) == 32;
  }
  v7 = 2 * v8 + 12;
LABEL_9:
  *(v5 + 976) = v7;
  v10 = 0;
  v11 = *(v5 + 976);
  v12 = *(v5 + 972) / 4;
  v61 = v12;
  if ( v11 >= 0 )
  {
    v13 = (v5 + 8);
    do
    {
      if ( v12 > 0 )
      {
        memset(v13, 0, 4 * v12);
        v12 = v61;
      }
      v11 = *(v5 + 976);
      ++v10;
      v13 += 32;
    }
    while ( v10 <= v11 );
  }
  v14 = 0;
  if ( v11 >= 0 )
  {
    v15 = (v5 + 488);
    do
    {
      if ( v12 > 0 )
      {
        memset(v15, 0, 4 * v12);
        v12 = v61;
      }
      v11 = *(v5 + 976);
      ++v14;
      v15 += 32;
    }
    while ( v14 <= v11 );
  }
  v16 = "sycloversyclover";
  v60 = v12 * (v11 + 1);
  v17 = *(v5 + 968);
  v18 = (v5 + 1044);
  result = v17 / 4;
  v20 = v5 + 1044;
  v54 = v17 / 4;
  v56 = (v5 + 1044);
  if ( v17 / 4 > 0 )
  {
    v21 = v17 / 4;
    do
    {
      v22 = *v16;
      v16 += 4;
      v22 <<= 24;
      v20 += 4;
      *(v20 - 4) = v22;
      v23 = v22 | (*(v16 - 3) << 16);
      *(v20 - 4) = v23;
      v24 = v23 | (*(v16 - 2) << 8);
      *(v20 - 4) = v24;
      result = v24 | *(v16 - 1);
      *(v20 - 4) = result;
      --v21;
    }
    while ( v21 );
    v5 = this;
    v12 = v61;
    v18 = v56;
  }
  v25 = v17 / 4;
  v26 = 0;
  if ( v54 > 0 )
  {
    v58 = v18;
    do
    {
      if ( v26 >= v60 )
        goto LABEL_44;
      v27 = v26++;
      v29 = v27 % v12;
      v28 = v27 / v12;
      *(v5 + 4 * (v29 + 8 * v28) + 8) = *v58;
      v25 = v17 / 4;
      v30 = v29 + 8 * (*(v5 + 976) - v28);
      result = *v58;
      *(v5 + 4 * v30 + 488) = *v58;
      v12 = v61;
      ++v58;
    }
    while ( v26 < v54 );
  }
  if ( v26 < v60 )
  {
    v59 = &unk_406B40;
    do
    {
      v31 = *(v5 + 4 * v25 + 1040);
      v32 = v59++;
      v33 = RijnDael_AES_LONG_405DE0[HIBYTE(v31)] ^ ((RijnDael_AES_LONG_405DE0[v31] ^ ((RijnDael_AES_LONG_405DE0[BYTE1(v31)] ^ ((*v32 ^ RijnDael_AES_LONG_405DE0[BYTE2(v31)]) << 8)) << 8)) << 8);
      result = v5 + 1044;
      *(v5 + 1044) ^= v33;
      if ( v25 == 8 )
      {
        v37 = v5 + 1048;
        v38 = 3;
        do
        {
          v39 = *(v37 - 4);
          v37 += 4;
          *(v37 - 4) ^= v39;
          --v38;
        }
        while ( v38 );
        v40 = 3;
        *(v5 + 1060) ^= RijnDael_AES_LONG_405DE0[*(v5 + 1056)] ^ ((RijnDael_AES_LONG_405DE0[BYTE1(*(v5 + 1056))] ^ ((RijnDael_AES_LONG_405DE0[BYTE2(*(v5 + 1056))] ^ (RijnDael_AES_LONG_405DE0[HIBYTE(*(v5 + 1056))] << 8)) << 8)) << 8);
        v41 = v5 + 1064;
        do
        {
          v42 = *(v41 - 4);
          v41 += 4;
          *(v41 - 4) ^= v42;
          --v40;
        }
        while ( v40 );
      }
      else
      {
        if ( v25 <= 1 )
          goto LABEL_39;
        v34 = v5 + 1048;
        v35 = v25 - 1;
        do
        {
          v36 = *(v34 - 4);
          v34 += 4;
          *(v34 - 4) ^= v36;
          --v35;
        }
        while ( v35 );
      }
      result = v5 + 1044;
LABEL_39:
      v52 = 0;
      if ( v25 > 0 )
      {
        v43 = result;
        v57 = result;
        while ( v26 < v60 )
        {
          v44 = v26++;
          v45 = v44 % v61;
          LODWORD(v44) = v44 / v61;
          *(v5 + 4 * (v45 + 8 * v44) + 8) = *v43;
          v25 = v17 / 4;
          *(v5 + 4 * (v45 + 8 * (*(v5 + 976) - v44)) + 488) = *v57;
          result = v52 + 1;
          v43 = v57 + 1;
          v52 = result;
          ++v57;
          if ( result >= v54 )
            goto LABEL_43;
        }
        break;
      }
LABEL_43:
      ;
    }
    while ( v26 < v60 );
  }
LABEL_44:
  v46 = 1;
  v53 = 1;
  if ( *(v5 + 976) <= 1 )
  {
    *(v5 + 4) = 1;
  }
  else
  {
    result = v61;
    v47 = (v5 + 520);
    v55 = (v5 + 520);
    do
    {
      if ( result > 0 )
      {
        v48 = v47;
        v49 = result;
        do
        {
          v50 = *v48++;
          *(v48 - 1) = dword_406B60[v50] ^ dword_4066E0[BYTE1(v50)] ^ dword_405EE0[BYTE2(v50)] ^ dword_406F60[HIBYTE(v50)];
          --v49;
        }
        while ( v49 );
        result = v61;
        v46 = v53;
        v47 = v55;
      }
      ++v46;
      v47 += 8;
      v53 = v46;
      v55 = v47;
    }
    while ( v46 < *(v5 + 976) );
    *(v5 + 4) = 1;
  }
  return result;
}

我们不难看出是aes加密算法,CBC模式,密码为sycloversyclover,偏移量为sctfsctfsctfsctf,
在线解密得flag

flag{Ae3_C8c_I28_pKcs79ad4}
  • 4
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Em0s_Er1t

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值