首页
社区
课程
招聘
[原创]KCTF Q3 第五题:魅影舞姬
发表于: 2019-9-24 03:26 3185

[原创]KCTF Q3 第五题:魅影舞姬

2019-9-24 03:26
3185
IDA载入CM,粗略分析下main函数,如下。
int __cdecl main(int argc, const char **argv, const char **envp)
{
  __int64 v3; // rax
  _BOOL1 v4; // bl
  __int64 v5; // rax
  void *v6; // rsp
  size_t v7; // rbx
  const char *v8; // rax
  size_t v9; // rbx
  const char *v10; // rax
  size_t v11; // rbx
  const char *v12; // rax
  size_t v13; // rbx
  const char *v14; // rax
  size_t v15; // rbx
  const char *v16; // rax
  __int64 v17; // rax
  __int64 v18; // rax
  unsigned __int8 v20; // [rsp+20h] [rbp-60h]
  char v21; // [rsp+40h] [rbp-40h]
  char v22; // [rsp+50h] [rbp-30h]
  char input8; // [rsp+60h] [rbp-20h]
  char base64de; // [rsp+70h] [rbp-10h]
  unsigned __int64 v25; // [rsp+80h] [rbp+0h]
  unsigned __int64 v26; // [rsp+90h] [rbp+10h]
  char v27; // [rsp+A0h] [rbp+20h]
  char v28; // [rsp+B0h] [rbp+30h]
  char v29; // [rsp+C0h] [rbp+40h]
  char v30; // [rsp+D0h] [rbp+50h]
  char v31; // [rsp+E0h] [rbp+60h]
  char v32; // [rsp+F0h] [rbp+70h]
  char v33; // [rsp+100h] [rbp+80h]
  char v34; // [rsp+110h] [rbp+90h]
  char v35; // [rsp+120h] [rbp+A0h]
  char v36; // [rsp+130h] [rbp+B0h]
  char v37; // [rsp+140h] [rbp+C0h]
  int v38; // [rsp+14Ch] [rbp+CCh]
  char *Str; // [rsp+150h] [rbp+D0h]
  __int64 v40; // [rsp+158h] [rbp+D8h]

  _main();
  std::string::string((std::string *)&v26);
  std::operator<<<std::char_traits<char>>(refptr__ZSt4cout, "please input your serial:\n");
  std::operator>><char,std::char_traits<char>,std::allocator<char>>(refptr__ZSt3cin, (std::string *)&v26);
  std::string::operator+=(&v26, "Welcome/to/this/very/simple/challenge");
  if ( (unsigned __int64)std::string::length((std::string *)&v26) > 0x55 )// 加上上面的字符串长度不大于0x55
  {
    v3 = std::operator<<<std::char_traits<char>>(refptr__ZSt4cout, "incorrect!");
    std::ostream::operator<<(v3, refptr__ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_);
    system("pause");
  }
  else
  {
    std::string::string((std::string *)&v27, (const std::string *)&v26);
    v4 = !check_fun((__int64)&v27);             // 防多解,调试时可以先跳过
    std::string::~string((std::string *)&v27);
    if ( v4 )
    {
      v5 = std::operator<<<std::char_traits<char>>(refptr__ZSt4cout, "incorrect!");
      std::ostream::operator<<(v5, refptr__ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_);
      system("pause");
    }
    else
    {
      std::string::substr((std::string *)&v28, (const std::string *)&v26, 0i64, 0x24ui64);// 取前36个字符
      base64decode((std::string *)&v25, (std::string *)&v28);// base64解码
      std::string::~string((std::string *)&v28);
      v40 = std::string::length((std::string *)&v26);
      v6 = alloca(16 * ((unsigned __int64)(v40 + 16) >> 4));
      Str = (char *)&v20;
      std::string::substr((std::string *)&v29, (const std::string *)&v25, 0x12ui64, 0xFFFFFFFFFFFFFFFFui64);
      v7 = std::string::length((std::string *)&v29) + 1;
      std::string::substr((std::string *)&v30, (const std::string *)&v25, 0x12ui64, 0xFFFFFFFFFFFFFFFFui64);
      v8 = (const char *)std::string::c_str((std::string *)&v30);
      strncpy(&base64de, v8, v7);
      std::string::~string((std::string *)&v30);
      std::string::~string((std::string *)&v29);
      std::string::substr((std::string *)&v31, (const std::string *)&v26, 0i64, 8ui64);
      v9 = std::string::length((std::string *)&v31) + 1;
      std::string::substr((std::string *)&v32, (const std::string *)&v26, 0i64, 8ui64);
      v10 = (const char *)std::string::c_str((std::string *)&v32);
      strncpy(&input8, v10, v9);
      std::string::~string((std::string *)&v32);
      std::string::~string((std::string *)&v31);
      std::string::substr((std::string *)&v33, (const std::string *)&v26, 8ui64, 8ui64);
      v11 = std::string::length((std::string *)&v33) + 1;
      std::string::substr((std::string *)&v34, (const std::string *)&v26, 8ui64, 8ui64);
      v12 = (const char *)std::string::c_str((std::string *)&v34);
      strncpy(&v22, v12, v11);
      std::string::~string((std::string *)&v34);
      std::string::~string((std::string *)&v33);
      std::string::substr((std::string *)&v35, (const std::string *)&v26, 0x10ui64, 8ui64);
      v13 = std::string::length((std::string *)&v35) + 1;
      std::string::substr((std::string *)&v36, (const std::string *)&v26, 0x10ui64, 8ui64);
      v14 = (const char *)std::string::c_str((std::string *)&v36);
      strncpy(&v21, v14, v13);
      std::string::~string((std::string *)&v36);
      std::string::~string((std::string *)&v35);
      v15 = std::string::length((std::string *)&v26) + 1;
      v16 = (const char *)std::string::c_str((std::string *)&v26);
      strncpy(Str, v16, v15);
      desdecrypt(&base64de, &v21, &base64de);   // 用输入字符串的16-23位作为密钥解密
      desencrypt(&base64de, &v22, &base64de);   // 8-15
      v38 = strlen(Str);
      md5(&v20, Str, v38);
      desdecrypt(&base64de, &input8, &base64de);// 0-7
      std::string::replace((std::string *)&v25, 0x12ui64, 8ui64, &base64de);
      std::string::string((std::string *)&v37, (const std::string *)&v25);
      checkgame((const std::string *)&v37);     // 游戏
      std::string::~string((std::string *)&v37);
      if ( (unsigned __int8)std::operator==<char>(&v20, &strmd5) )// 比较输入字符的MD5,防多解
      {
        if ( checkresult == 4 )                 // checkgame函数内检查成功则加1,一共检查4次
          v17 = std::operator<<<std::char_traits<char>>(refptr__ZSt4cout, "correct!");
        else
          v17 = std::operator<<<std::char_traits<char>>(refptr__ZSt4cout, "incorrect!");
        std::ostream::operator<<(v17, refptr__ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_);
      }
      else
      {
        v18 = std::operator<<<std::char_traits<char>>(refptr__ZSt4cout, "incorrect!");
        std::ostream::operator<<(v18, refptr__ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_);
      }
      system("pause");
      std::string::~string((std::string *)&v20);
      std::string::~string((std::string *)&v25);
    }
  }
  std::string::~string((std::string *)&v26);
  return 0;
}
checkgame函数。
__int64 __fastcall checkstr(const std::string *a1)
{
  __int64 v2; // [rsp+0h] [rbp-80h]
  char v3; // [rsp+20h] [rbp-60h]
  char v4; // [rsp+30h] [rbp-50h]
  char v5; // [rsp+40h] [rbp-40h]
  char v6; // [rsp+50h] [rbp-30h]
  const std::string *v7; // [rsp+80h] [rbp+0h]

  v7 = a1;
  std::string::substr((std::string *)(&v2 + 4), a1, 0i64, 6ui64);// 取base64解码后的6个字节
  checkresult += (unsigned __int8)check((std::string *)&v3);
  std::string::~string((std::string *)&v3);
  replacegame(4, 5);                            // 替换布局,后面都是
  replacegame(9, 10);
  replacegame(10, 11);
  std::string::substr((std::string *)&v4, v7, 6ui64, 6ui64);
  checkresult += (unsigned __int8)check((std::string *)&v4);
  std::string::~string((std::string *)&v4);
  replacegame(5, 7);
  replacegame(9, 12);
  replacegame(11, 12);
  std::string::substr((std::string *)&v5, v7, 0xCui64, 6ui64);
  checkresult += (unsigned __int8)check((std::string *)&v5);
  std::string::~string((std::string *)&v5);
  replacegame(2, 12);
  replace(7, 9);
  replace(5, 3);
  replace(5, 11);
  replace(4, 7);
  replace(4, 8);
  std::string::substr((std::string *)&v6, v7, 0x12ui64, 0xFFFFFFFFFFFFFFFFui64);
  checkresult += (unsigned __int8)check((std::string *)&v6);
  return std::string::~string((std::string *)&v6);
}
check函数
_BOOL8 __fastcall check(std::string *a1)
{
  int v1; // eax
  _BOOL1 v2; // al
  signed int j; // [rsp+2Ch] [rbp-14h]
  unsigned __int64 i; // [rsp+30h] [rbp-10h]
  int v6; // [rsp+3Ch] [rbp-4h]
  std::string *v7; // [rsp+50h] [rbp+10h]

  v7 = a1;
  v6 = std::string::find((std::string *)&str, '@', 0i64);// 从'@'开始
  for ( i = 0i64; std::string::length(v7) > i; ++i )// 一字节可以走4步,每次只有6字节(最后一个不是),所以在24步之内走到终点即可
  {
    for ( j = 6; j >= 0; j -= 2 )
    {
      v1 = ((signed int)*(unsigned __int8 *)std::string::operator[](v7, i) >> j) & 3;
      if ( v1 == 1 )                            // down
      {
        v6 += 13;
      }
      else if ( v1 > 1 )
      {
        if ( v1 == 2 )                          // left
        {
          --v6;
        }
        else if ( v1 == 3 )                     // right
        {
          ++v6;
        }
      }
      else if ( !v1 )                           // up
      {
        v6 -= 13;
      }
      v2 = *(_BYTE *)std::string::operator[](&str, v6) != '-' && *(_BYTE *)std::string::operator[](&str, v6) != '#';// '@'碰到'-'则失败
      if ( v2 )
        return 0i64;                            // '@'到达'#'则成功
    }
  }
  return *(_BYTE *)std::string::operator[](&str, v6) == '#';
}

动态调试抓取到4个游戏布局,如下
*************
*@***********
*-***********
*--**----****
*-***-**-****
*-***#**-****
*--*****-****
**-*****-****
**-------****
**-*-----****
**---**-*****
**-****--****
*************
111113113333330000022211

*************
*@***********
*-***********
*-***-**-****
*--**----****
*-***#**-****
*--*****-****
**-*****-****
**-*-----****
**---**-*****
**-------****
**-****--****
*************
111113111330333300002221

*************
*@***********
*-***********
*-***-**-****
*--*****-****
*-***#**-****
*--**----****
**-*****-****
**-****--****
**---**-*****
**-*-----****
**-------****
*************
111113111331333003002220

*************
**-------****
*--*****-****
*-***-**-****
*--*****-****
*-***#**-****
*-***-**-****
*-***-**-****
*--**----****
**---**-*****
*--*****-****
*@***********
*************
03002000000303333331111111222000
最后一个并不是24步而是32步,将所有步数加起来除以4等于26。
前面用来base64解码的字符串有36个,如果没有"=",解码后的字节数是27个,所以flag有一个等号。
将步骤恢复成6个字节,再base64编码,注意后8个字节需要DES处理一下。
IDA载入CM,粗略分析下main函数,如下。
int __cdecl main(int argc, const char **argv, const char **envp)
{
  __int64 v3; // rax
  _BOOL1 v4; // bl
  __int64 v5; // rax
  void *v6; // rsp
  size_t v7; // rbx
  const char *v8; // rax
  size_t v9; // rbx
  const char *v10; // rax
  size_t v11; // rbx
  const char *v12; // rax
  size_t v13; // rbx
  const char *v14; // rax
  size_t v15; // rbx
  const char *v16; // rax
  __int64 v17; // rax
  __int64 v18; // rax
  unsigned __int8 v20; // [rsp+20h] [rbp-60h]
  char v21; // [rsp+40h] [rbp-40h]
  char v22; // [rsp+50h] [rbp-30h]
  char input8; // [rsp+60h] [rbp-20h]
  char base64de; // [rsp+70h] [rbp-10h]
  unsigned __int64 v25; // [rsp+80h] [rbp+0h]
  unsigned __int64 v26; // [rsp+90h] [rbp+10h]
  char v27; // [rsp+A0h] [rbp+20h]
  char v28; // [rsp+B0h] [rbp+30h]
  char v29; // [rsp+C0h] [rbp+40h]
  char v30; // [rsp+D0h] [rbp+50h]
  char v31; // [rsp+E0h] [rbp+60h]
  char v32; // [rsp+F0h] [rbp+70h]
  char v33; // [rsp+100h] [rbp+80h]
  char v34; // [rsp+110h] [rbp+90h]
  char v35; // [rsp+120h] [rbp+A0h]
  char v36; // [rsp+130h] [rbp+B0h]
  char v37; // [rsp+140h] [rbp+C0h]
  int v38; // [rsp+14Ch] [rbp+CCh]
  char *Str; // [rsp+150h] [rbp+D0h]
  __int64 v40; // [rsp+158h] [rbp+D8h]

  _main();
  std::string::string((std::string *)&v26);
  std::operator<<<std::char_traits<char>>(refptr__ZSt4cout, "please input your serial:\n");
  std::operator>><char,std::char_traits<char>,std::allocator<char>>(refptr__ZSt3cin, (std::string *)&v26);
  std::string::operator+=(&v26, "Welcome/to/this/very/simple/challenge");
  if ( (unsigned __int64)std::string::length((std::string *)&v26) > 0x55 )// 加上上面的字符串长度不大于0x55
  {
    v3 = std::operator<<<std::char_traits<char>>(refptr__ZSt4cout, "incorrect!");
    std::ostream::operator<<(v3, refptr__ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_);
    system("pause");
  }
  else
  {
    std::string::string((std::string *)&v27, (const std::string *)&v26);
    v4 = !check_fun((__int64)&v27);             // 防多解,调试时可以先跳过
    std::string::~string((std::string *)&v27);
    if ( v4 )
    {
      v5 = std::operator<<<std::char_traits<char>>(refptr__ZSt4cout, "incorrect!");
      std::ostream::operator<<(v5, refptr__ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_);
      system("pause");
    }
    else
    {
      std::string::substr((std::string *)&v28, (const std::string *)&v26, 0i64, 0x24ui64);// 取前36个字符
      base64decode((std::string *)&v25, (std::string *)&v28);// base64解码
      std::string::~string((std::string *)&v28);
      v40 = std::string::length((std::string *)&v26);
      v6 = alloca(16 * ((unsigned __int64)(v40 + 16) >> 4));
      Str = (char *)&v20;
      std::string::substr((std::string *)&v29, (const std::string *)&v25, 0x12ui64, 0xFFFFFFFFFFFFFFFFui64);
      v7 = std::string::length((std::string *)&v29) + 1;
      std::string::substr((std::string *)&v30, (const std::string *)&v25, 0x12ui64, 0xFFFFFFFFFFFFFFFFui64);
      v8 = (const char *)std::string::c_str((std::string *)&v30);
      strncpy(&base64de, v8, v7);
      std::string::~string((std::string *)&v30);
      std::string::~string((std::string *)&v29);
      std::string::substr((std::string *)&v31, (const std::string *)&v26, 0i64, 8ui64);
      v9 = std::string::length((std::string *)&v31) + 1;
      std::string::substr((std::string *)&v32, (const std::string *)&v26, 0i64, 8ui64);
      v10 = (const char *)std::string::c_str((std::string *)&v32);
      strncpy(&input8, v10, v9);
      std::string::~string((std::string *)&v32);
      std::string::~string((std::string *)&v31);
      std::string::substr((std::string *)&v33, (const std::string *)&v26, 8ui64, 8ui64);
      v11 = std::string::length((std::string *)&v33) + 1;
      std::string::substr((std::string *)&v34, (const std::string *)&v26, 8ui64, 8ui64);
      v12 = (const char *)std::string::c_str((std::string *)&v34);
      strncpy(&v22, v12, v11);
      std::string::~string((std::string *)&v34);
      std::string::~string((std::string *)&v33);
      std::string::substr((std::string *)&v35, (const std::string *)&v26, 0x10ui64, 8ui64);
      v13 = std::string::length((std::string *)&v35) + 1;
      std::string::substr((std::string *)&v36, (const std::string *)&v26, 0x10ui64, 8ui64);
      v14 = (const char *)std::string::c_str((std::string *)&v36);
      strncpy(&v21, v14, v13);
      std::string::~string((std::string *)&v36);
      std::string::~string((std::string *)&v35);
      v15 = std::string::length((std::string *)&v26) + 1;
      v16 = (const char *)std::string::c_str((std::string *)&v26);
      strncpy(Str, v16, v15);
      desdecrypt(&base64de, &v21, &base64de);   // 用输入字符串的16-23位作为密钥解密
      desencrypt(&base64de, &v22, &base64de);   // 8-15
      v38 = strlen(Str);
      md5(&v20, Str, v38);
      desdecrypt(&base64de, &input8, &base64de);// 0-7
      std::string::replace((std::string *)&v25, 0x12ui64, 8ui64, &base64de);
      std::string::string((std::string *)&v37, (const std::string *)&v25);
      checkgame((const std::string *)&v37);     // 游戏
      std::string::~string((std::string *)&v37);
      if ( (unsigned __int8)std::operator==<char>(&v20, &strmd5) )// 比较输入字符的MD5,防多解
      {
        if ( checkresult == 4 )                 // checkgame函数内检查成功则加1,一共检查4次
          v17 = std::operator<<<std::char_traits<char>>(refptr__ZSt4cout, "correct!");
        else
          v17 = std::operator<<<std::char_traits<char>>(refptr__ZSt4cout, "incorrect!");
        std::ostream::operator<<(v17, refptr__ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_);
      }
      else
      {
        v18 = std::operator<<<std::char_traits<char>>(refptr__ZSt4cout, "incorrect!");
        std::ostream::operator<<(v18, refptr__ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_);
      }
      system("pause");
      std::string::~string((std::string *)&v20);
      std::string::~string((std::string *)&v25);
    }
  }
  std::string::~string((std::string *)&v26);
  return 0;
}
checkgame函数。
int __cdecl main(int argc, const char **argv, const char **envp)
{
  __int64 v3; // rax
  _BOOL1 v4; // bl
  __int64 v5; // rax
  void *v6; // rsp
  size_t v7; // rbx
  const char *v8; // rax
  size_t v9; // rbx
  const char *v10; // rax
  size_t v11; // rbx
  const char *v12; // rax
  size_t v13; // rbx
  const char *v14; // rax
  size_t v15; // rbx
  const char *v16; // rax
  __int64 v17; // rax
  __int64 v18; // rax
  unsigned __int8 v20; // [rsp+20h] [rbp-60h]
  char v21; // [rsp+40h] [rbp-40h]
  char v22; // [rsp+50h] [rbp-30h]
  char input8; // [rsp+60h] [rbp-20h]
  char base64de; // [rsp+70h] [rbp-10h]
  unsigned __int64 v25; // [rsp+80h] [rbp+0h]
  unsigned __int64 v26; // [rsp+90h] [rbp+10h]
  char v27; // [rsp+A0h] [rbp+20h]
  char v28; // [rsp+B0h] [rbp+30h]
  char v29; // [rsp+C0h] [rbp+40h]
  char v30; // [rsp+D0h] [rbp+50h]
  char v31; // [rsp+E0h] [rbp+60h]
  char v32; // [rsp+F0h] [rbp+70h]
  char v33; // [rsp+100h] [rbp+80h]
  char v34; // [rsp+110h] [rbp+90h]
  char v35; // [rsp+120h] [rbp+A0h]
  char v36; // [rsp+130h] [rbp+B0h]
  char v37; // [rsp+140h] [rbp+C0h]
  int v38; // [rsp+14Ch] [rbp+CCh]
  char *Str; // [rsp+150h] [rbp+D0h]
  __int64 v40; // [rsp+158h] [rbp+D8h]

  _main();
  std::string::string((std::string *)&v26);
  std::operator<<<std::char_traits<char>>(refptr__ZSt4cout, "please input your serial:\n");
  std::operator>><char,std::char_traits<char>,std::allocator<char>>(refptr__ZSt3cin, (std::string *)&v26);
  std::string::operator+=(&v26, "Welcome/to/this/very/simple/challenge");
  if ( (unsigned __int64)std::string::length((std::string *)&v26) > 0x55 )// 加上上面的字符串长度不大于0x55
  {
    v3 = std::operator<<<std::char_traits<char>>(refptr__ZSt4cout, "incorrect!");
    std::ostream::operator<<(v3, refptr__ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_);
    system("pause");
  }
  else
  {
    std::string::string((std::string *)&v27, (const std::string *)&v26);
    v4 = !check_fun((__int64)&v27);             // 防多解,调试时可以先跳过
    std::string::~string((std::string *)&v27);
    if ( v4 )
    {
      v5 = std::operator<<<std::char_traits<char>>(refptr__ZSt4cout, "incorrect!");
      std::ostream::operator<<(v5, refptr__ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_);
      system("pause");
    }
    else
    {
      std::string::substr((std::string *)&v28, (const std::string *)&v26, 0i64, 0x24ui64);// 取前36个字符
      base64decode((std::string *)&v25, (std::string *)&v28);// base64解码
      std::string::~string((std::string *)&v28);
      v40 = std::string::length((std::string *)&v26);
      v6 = alloca(16 * ((unsigned __int64)(v40 + 16) >> 4));
      Str = (char *)&v20;
      std::string::substr((std::string *)&v29, (const std::string *)&v25, 0x12ui64, 0xFFFFFFFFFFFFFFFFui64);
      v7 = std::string::length((std::string *)&v29) + 1;
      std::string::substr((std::string *)&v30, (const std::string *)&v25, 0x12ui64, 0xFFFFFFFFFFFFFFFFui64);
      v8 = (const char *)std::string::c_str((std::string *)&v30);
      strncpy(&base64de, v8, v7);
      std::string::~string((std::string *)&v30);
      std::string::~string((std::string *)&v29);
      std::string::substr((std::string *)&v31, (const std::string *)&v26, 0i64, 8ui64);
      v9 = std::string::length((std::string *)&v31) + 1;
      std::string::substr((std::string *)&v32, (const std::string *)&v26, 0i64, 8ui64);
      v10 = (const char *)std::string::c_str((std::string *)&v32);
      strncpy(&input8, v10, v9);
      std::string::~string((std::string *)&v32);
      std::string::~string((std::string *)&v31);
      std::string::substr((std::string *)&v33, (const std::string *)&v26, 8ui64, 8ui64);
      v11 = std::string::length((std::string *)&v33) + 1;
      std::string::substr((std::string *)&v34, (const std::string *)&v26, 8ui64, 8ui64);
      v12 = (const char *)std::string::c_str((std::string *)&v34);
      strncpy(&v22, v12, v11);
      std::string::~string((std::string *)&v34);
      std::string::~string((std::string *)&v33);
      std::string::substr((std::string *)&v35, (const std::string *)&v26, 0x10ui64, 8ui64);
      v13 = std::string::length((std::string *)&v35) + 1;
      std::string::substr((std::string *)&v36, (const std::string *)&v26, 0x10ui64, 8ui64);
      v14 = (const char *)std::string::c_str((std::string *)&v36);
      strncpy(&v21, v14, v13);
      std::string::~string((std::string *)&v36);
      std::string::~string((std::string *)&v35);
      v15 = std::string::length((std::string *)&v26) + 1;
      v16 = (const char *)std::string::c_str((std::string *)&v26);
      strncpy(Str, v16, v15);
      desdecrypt(&base64de, &v21, &base64de);   // 用输入字符串的16-23位作为密钥解密
      desencrypt(&base64de, &v22, &base64de);   // 8-15
      v38 = strlen(Str);
      md5(&v20, Str, v38);
      desdecrypt(&base64de, &input8, &base64de);// 0-7
      std::string::replace((std::string *)&v25, 0x12ui64, 8ui64, &base64de);
      std::string::string((std::string *)&v37, (const std::string *)&v25);
      checkgame((const std::string *)&v37);     // 游戏
      std::string::~string((std::string *)&v37);
      if ( (unsigned __int8)std::operator==<char>(&v20, &strmd5) )// 比较输入字符的MD5,防多解
      {
        if ( checkresult == 4 )                 // checkgame函数内检查成功则加1,一共检查4次
          v17 = std::operator<<<std::char_traits<char>>(refptr__ZSt4cout, "correct!");
        else
          v17 = std::operator<<<std::char_traits<char>>(refptr__ZSt4cout, "incorrect!");
        std::ostream::operator<<(v17, refptr__ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_);
      }
      else
      {
        v18 = std::operator<<<std::char_traits<char>>(refptr__ZSt4cout, "incorrect!");
        std::ostream::operator<<(v18, refptr__ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_);
      }
      system("pause");
      std::string::~string((std::string *)&v20);
      std::string::~string((std::string *)&v25);
    }
  }
  std::string::~string((std::string *)&v26);
  return 0;
}
checkgame函数。
__int64 __fastcall checkstr(const std::string *a1)
{
  __int64 v2; // [rsp+0h] [rbp-80h]
  char v3; // [rsp+20h] [rbp-60h]
  char v4; // [rsp+30h] [rbp-50h]
  char v5; // [rsp+40h] [rbp-40h]
  char v6; // [rsp+50h] [rbp-30h]
  const std::string *v7; // [rsp+80h] [rbp+0h]

  v7 = a1;
  std::string::substr((std::string *)(&v2 + 4), a1, 0i64, 6ui64);// 取base64解码后的6个字节
  checkresult += (unsigned __int8)check((std::string *)&v3);
  std::string::~string((std::string *)&v3);
  replacegame(4, 5);                            // 替换布局,后面都是
  replacegame(9, 10);
  replacegame(10, 11);
  std::string::substr((std::string *)&v4, v7, 6ui64, 6ui64);
  checkresult += (unsigned __int8)check((std::string *)&v4);
  std::string::~string((std::string *)&v4);
  replacegame(5, 7);
  replacegame(9, 12);
  replacegame(11, 12);
  std::string::substr((std::string *)&v5, v7, 0xCui64, 6ui64);
  checkresult += (unsigned __int8)check((std::string *)&v5);
  std::string::~string((std::string *)&v5);
  replacegame(2, 12);
  replace(7, 9);
  replace(5, 3);
  replace(5, 11);
  replace(4, 7);
  replace(4, 8);
  std::string::substr((std::string *)&v6, v7, 0x12ui64, 0xFFFFFFFFFFFFFFFFui64);
  checkresult += (unsigned __int8)check((std::string *)&v6);
  return std::string::~string((std::string *)&v6);
}
check函数
__int64 __fastcall checkstr(const std::string *a1)
{
  __int64 v2; // [rsp+0h] [rbp-80h]
  char v3; // [rsp+20h] [rbp-60h]
  char v4; // [rsp+30h] [rbp-50h]
  char v5; // [rsp+40h] [rbp-40h]
  char v6; // [rsp+50h] [rbp-30h]
  const std::string *v7; // [rsp+80h] [rbp+0h]

  v7 = a1;
  std::string::substr((std::string *)(&v2 + 4), a1, 0i64, 6ui64);// 取base64解码后的6个字节
  checkresult += (unsigned __int8)check((std::string *)&v3);
  std::string::~string((std::string *)&v3);
  replacegame(4, 5);                            // 替换布局,后面都是
  replacegame(9, 10);
  replacegame(10, 11);
  std::string::substr((std::string *)&v4, v7, 6ui64, 6ui64);
  checkresult += (unsigned __int8)check((std::string *)&v4);
  std::string::~string((std::string *)&v4);
  replacegame(5, 7);
  replacegame(9, 12);
  replacegame(11, 12);
  std::string::substr((std::string *)&v5, v7, 0xCui64, 6ui64);
  checkresult += (unsigned __int8)check((std::string *)&v5);
  std::string::~string((std::string *)&v5);
  replacegame(2, 12);
  replace(7, 9);
  replace(5, 3);
  replace(5, 11);
  replace(4, 7);
  replace(4, 8);
  std::string::substr((std::string *)&v6, v7, 0x12ui64, 0xFFFFFFFFFFFFFFFFui64);
  checkresult += (unsigned __int8)check((std::string *)&v6);
  return std::string::~string((std::string *)&v6);
}
check函数
_BOOL8 __fastcall check(std::string *a1)
{
  int v1; // eax
  _BOOL1 v2; // al
  signed int j; // [rsp+2Ch] [rbp-14h]
  unsigned __int64 i; // [rsp+30h] [rbp-10h]
  int v6; // [rsp+3Ch] [rbp-4h]
  std::string *v7; // [rsp+50h] [rbp+10h]

  v7 = a1;
  v6 = std::string::find((std::string *)&str, '@', 0i64);// 从'@'开始
  for ( i = 0i64; std::string::length(v7) > i; ++i )// 一字节可以走4步,每次只有6字节(最后一个不是),所以在24步之内走到终点即可
  {
    for ( j = 6; j >= 0; j -= 2 )
    {
      v1 = ((signed int)*(unsigned __int8 *)std::string::operator[](v7, i) >> j) & 3;
      if ( v1 == 1 )                            // down
      {
        v6 += 13;
      }
      else if ( v1 > 1 )
      {
        if ( v1 == 2 )                          // left
        {
          --v6;
        }
        else if ( v1 == 3 )                     // right
        {
          ++v6;
        }
      }
      else if ( !v1 )                           // up
      {
        v6 -= 13;
      }
      v2 = *(_BYTE *)std::string::operator[](&str, v6) != '-' && *(_BYTE *)std::string::operator[](&str, v6) != '#';// '@'碰到'-'则失败
      if ( v2 )
        return 0i64;                            // '@'到达'#'则成功
    }
  }
  return *(_BYTE *)std::string::operator[](&str, v6) == '#';
}

_BOOL8 __fastcall check(std::string *a1)
{
  int v1; // eax
  _BOOL1 v2; // al
  signed int j; // [rsp+2Ch] [rbp-14h]
  unsigned __int64 i; // [rsp+30h] [rbp-10h]
  int v6; // [rsp+3Ch] [rbp-4h]
  std::string *v7; // [rsp+50h] [rbp+10h]

  v7 = a1;
  v6 = std::string::find((std::string *)&str, '@', 0i64);// 从'@'开始
  for ( i = 0i64; std::string::length(v7) > i; ++i )// 一字节可以走4步,每次只有6字节(最后一个不是),所以在24步之内走到终点即可
  {
    for ( j = 6; j >= 0; j -= 2 )
    {
      v1 = ((signed int)*(unsigned __int8 *)std::string::operator[](v7, i) >> j) & 3;
      if ( v1 == 1 )                            // down
      {
        v6 += 13;
      }
      else if ( v1 > 1 )
      {
        if ( v1 == 2 )                          // left
        {
          --v6;
        }
        else if ( v1 == 3 )                     // right
        {
          ++v6;
        }
      }
      else if ( !v1 )                           // up
      {
        v6 -= 13;
      }
      v2 = *(_BYTE *)std::string::operator[](&str, v6) != '-' && *(_BYTE *)std::string::operator[](&str, v6) != '#';// '@'碰到'-'则失败
      if ( v2 )
        return 0i64;                            // '@'到达'#'则成功
    }
  }
  return *(_BYTE *)std::string::operator[](&str, v6) == '#';
}

动态调试抓取到4个游戏布局,如下
*************
*@***********
*-***********
*--**----****
*-***-**-****
*-***#**-****
*--*****-****
**-*****-****
**-------****
**-*-----****
**---**-*****
**-****--****
*************
111113113333330000022211

*************
*@***********
*-***********
*-***-**-****
*--**----****
*-***#**-****
*--*****-****
**-*****-****
**-*-----****
**---**-*****
**-------****
**-****--****
*************
111113111330333300002221

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

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