三年三班三井寿 发表于 2020-10-12 15:28

2020西湖论剑 re-Cellular

本帖最后由 三年三班三井寿 于 2020-10-12 15:35 编辑

没有什么花里胡哨的东西,进去之后逻辑很清晰
```
int __cdecl main(int argc, const char **argv, const char **envp)
{
Honeycomb *v3; // ebx
char *Format; //
int i; //
Honeycomb *v7; //
char v8; //

_alloca((size_t)Format);
__main();
memset(&v8, 0, 0x1Au);
v3 = (Honeycomb *)operator new(8u);
Honeycomb::Honeycomb(v3);
v7 = v3;
for ( i = 0; i <= 4; ++i )
    Honeycomb::IncDepth(v7);
printf("Path:");
scanf("%25s", &v8);
if ( (unsigned __int8)Honeycomb::CheckFlag(v7, &v8) )
{
    puts("Congrulations!");
    puts("The flag is md5(Path)!");
}
else
{
    puts("Wrong~");
}
system("pause");
return 0;
}
```
通过CheckFlag将输入的"%25s"与之前构建的数据结构判断。
输入按字节循环,‘L'或’R‘进行左旋或右旋操作,其他均为无效输入。
```
signed int __cdecl Honeycomb::CheckFlag(Honeycomb *this, char *Str)
{
signed int v3; //
char str_i; //
size_t i; //
_DWORD *v7; //

v7 = *(_DWORD **)this;
for ( i = 0; i < strlen(Str); ++i )
{
    str_i = Str;
    if ( str_i == 76 )
    {
      if ( *(_DWORD **)this == v7 )
      {
      if ( !(unsigned __int8)Honeycomb::RotateL(this, (Hexagon **)&v7, 0) )
          return 0;
      }
      else if ( !(unsigned __int8)Honeycomb::Clockwise(this, (Hexagon **)&v7) )
      {
      return 0;
      }
    }
    else if ( str_i == 82 )
    {
      if ( *(_DWORD **)this == v7 )
      {
      if ( !(unsigned __int8)Honeycomb::RotateR(this, (Hexagon **)&v7, 0) )
          return 0;
      }
      else if ( !(unsigned __int8)Honeycomb::Counterclockwise(this, (Hexagon **)&v7) )
      {
      return 0;
      }
    }
}
v3 = 0;
if ( *v7 == 0x23 && Honeycomb::CheckUseCount(this) == 0x5E )
    v3 = 1;
return v3;
}
```
数据中初始化生成,每个节点长度为0x14。操作后需要找到0x23(#)的节点,所有节点的值存在一个全局数组中char map[] = "*-----++++--++--------------------------------+++-#-----------++-------------------+++++++++----+++---++++++++---++++---+------+++++++++++++++++++---+";
本来想画出结构再去解,后来实在是弄不下去了。三个指针的逻辑也不是父左右子节点。有师傅知道的告知一下,我也不是ctfer,很多基础估计也不知道。
最后只能扣代码实现爆破。因为其输入的限制,爆破起来也很快。
直接扣出相关代码
```
char map[] = "*-----++++--++--------------------------------+++-#-----------++-------------------+++++++++----+++---++++++++---++++---+------+++++++++++++++++++---+";
BYTE pathL[] = { 01, 01, 01, 01, 01, 02, 01, 01,03, 02, 01, 01, 03, 02, 03, 01,03, 02, 03, 02, 03, 02, 03, 02,01, 02, 03, 02, 01, 01, 03, 02,01 ,01, 03, 02 ,01, 03, 02, 01,01, 03, 02, 01, 03, 03, 02, 01,03, 02, 00, 00, 00, 00, 00, 00,00, 00, 00, 00 };
BYTE pathR[] = {02,02,02,02,02,01,02,02,03,01,02,02,03,01,03,02,03,01,03,01,03,01,03,01,02,01,03,01,02,02,03,01,02,02,03,01,02,03,01,02,02,03,01,02,03,03,01,02,03,01,00,00,00,00,00,00,00,00,00,00 };
int g_num = 0;
_DWORD* InsertHexagon(_DWORD arg1, _DWORD arg2) {
      int v2; // esi
      _DWORD *v3; // ebx
      int v4; // esi
      _DWORD *v5; // ebx
      int v6; // esi
      _DWORD *v7; // ebx
      int v8; // esi
      _DWORD *v9; // ebx
      int v10; // esi
      _DWORD *v11; // ebx
      _DWORD *result; // eax
      int j; //
      signed int i; //
      _DWORD *v15; //
      _DWORD *v16; //
      _DWORD *arg2a; //
      _DWORD *arg2c; //
      _DWORD *arg2d; //
      _DWORD *arg2b; //
      _DWORD *arg2e; //
      v15 = 0;
      while (*((_DWORD *)arg2 + 4))
                arg2 = (_DWORD)(*(_DWORD **)(*((_DWORD *)arg2 + 4) + 8));
      for (i = 0; i <= 5; ++i) {
                v16 = (_DWORD *)*((_DWORD *)arg2 + 3);//*NEXT
                v2 = map;
                v3 = (_DWORD *) new char{ 0 };
                *(_DWORD *)v3 = v2;
                *((_DWORD *)arg2 + 4) = (_DWORD)v3;
                *((_DWORD *)v3 + 4) = arg2;
                arg2a = v3;
                if (v15) {
                        *((_DWORD *)v3 + 3) = (_DWORD)v15;
                        *((_DWORD *)v15 + 3) = (_DWORD)v3;
                }
                v4 = map;
                v5 = (_DWORD *) new char{ 0 };
                *(_DWORD *)v5 = v4;
                *((_DWORD *)arg2a + 2) = (_DWORD)v5;
                *((_DWORD *)v5 + 2) = (_DWORD)arg2a;
                arg2c = v5;
                v6 = map;
                v7 = (_DWORD *) new char{ 0 };
                *(_DWORD *)v7 = v6;
                *((_DWORD *)arg2c + 3) = (_DWORD)v7;
                *((_DWORD *)v7 + 2) = (_DWORD)arg2c;
                v15 = v7;
                for (j = 0; *((_DWORD *)arg1 + 1) > 1 && *((_DWORD *)arg1 + 1) - 1 > j; ++j)
                {
                        arg2d = v16;
                        v16 = *(_DWORD **)(*((_DWORD *)v16 + 3) + 8);
                        v8 = map;
                        v9 = (_DWORD *) new char{ 0 };
                        *(_DWORD *)v9 = v8;
                        *((_DWORD *)arg2d + 4) = (_DWORD)v9;
                        *((_DWORD *)v9 + 4) = (_DWORD)arg2d;
                        arg2b = v9;
                        if (v15)
                        {
                              *((_DWORD *)v9 + 3) = (_DWORD)v15;
                              *((_DWORD *)v15 + 3) = (_DWORD)v9;
                        }
                        v10 = map;
                        v11 = (_DWORD *) new char{ 0 };
                        *(_DWORD *)v11 = v10;
                        *((_DWORD *)arg2b + 2) = (_DWORD)v11;
                        *((_DWORD *)v11 + 2) = (_DWORD)arg2b;
                        v15 = v11;
                }
                if (*((_DWORD *)v16 + 4)) {
                        arg2e = (_DWORD *)*((_DWORD *)v16 + 4);
                        *((_DWORD *)arg2e + 3) = (_DWORD)v15;
                        *((_DWORD *)v15 + 3) = (_DWORD)arg2e;
                        break;
                }
                arg2 = (_DWORD)v16;
      }
      result = (_DWORD*)arg1;
      ++*((_DWORD *)result + 1);
      return result;
}
signed int IncDepth(char* arg) {
      int v1; // esi
      int v3;
      char* v4;
      if (*(_DWORD *)arg) {
                return (unsigned int)InsertHexagon((DWORD)arg, *(DWORD*)arg);
      }
      v1 = map;
      char* v2= new char{ 0 };
      *(_DWORD *)v2 = v1;
      *(_DWORD *)arg = (_DWORD)v2;
      *(_DWORD *)(*(_DWORD *)arg + 4) = 1;
      _DWORD * v8 = *(_DWORD **)arg;
      for (signed int i = 0; i <= 4; ++i) {
               v3 = map;
               v4 = new char{ 0 };
               *(_DWORD *)v4 = v3;
               *((_DWORD *)v8 + 3) = (_DWORD)v4;
               *((_DWORD *)v4 + 2) = (_DWORD)v8;
               v8 = (_DWORD*)v4;
      }
      *(_DWORD *)(*(_DWORD *)arg + 8) = (_DWORD)v8;
      *((_DWORD *)v8 + 3) = *(_DWORD *)arg;
      ++*((_DWORD *)arg + 1);
      return 1;
}
signed int __cdecl RotateL(_DWORD *this_, _DWORD **a2, int a3)
{
      char v4; //
      signed int i; //
      _DWORD *v7; //
      _DWORD *v8; //
      _DWORD *v9; //

      for (i = 0; i <= 4; ++i)
      {
                v9 = (_DWORD *)*((_DWORD *)*a2 + 2);
                v8 = (_DWORD *)*((_DWORD *)*a2 + 3);
                v7 = (_DWORD *)*((_DWORD *)*a2 + 4);
                v4 = pathL;
                if (v4 == 2)
                {
                        if (*(_DWORD *)v8 == 43)
                              return 0;
                        if ((*(_DWORD *)v8 != 45 || *((_DWORD *)v8 + 1)) && *(_DWORD *)v9 != 35)
                        {
                              if (*((_DWORD *)v8 + 1) == 1)
                                        return 1;
                        }
                        else
                        {
                              *a2 = v8;
                              *((_DWORD *)*a2 + 1) = 1;
                        }
                }
                else if (v4 > 2)
                {
                        if (v4 == 3)
                        {
                              if (v7==0||*(_DWORD *)v7 == 43)
                                        return 0;
                              if ((*(_DWORD *)v7 != 45 || *((_DWORD *)v7 + 1)) && *(_DWORD *)v9 != 35)
                              {
                                        if (*((_DWORD *)v7 + 1) == 1)
                                                return 1;
                              }
                              else
                              {
                                        *a2 = v7;
                                        *((_DWORD *)*a2 + 1) = 1;
                              }
                        }
                }
                else if (v4 == 1)
                {
                        if (*(_DWORD *)v9 == 43)
                              return 0;
                        if ((*(_DWORD *)v9 != 45 || *((_DWORD *)v9 + 1)) && *(_DWORD *)v9 != 35)
                        {
                              if (*((_DWORD *)v9 + 1) == 1)
                                        return 1;
                        }
                        else
                        {
                              *a2 = v9;
                              *((_DWORD *)*a2 + 1) = 1;
                        }
                }
      }
      return 1;
}
signed int __cdecl RotateR(_DWORD *this_, _DWORD **a2, int a3) {
      char v4; //
      signed int i; //
      _DWORD *v7; //
      _DWORD *v8; //
      _DWORD *v9; //
      for (i = 0; i <= 4; ++i)
      {
                v9 = (_DWORD *)*((_DWORD *)*a2 + 2);
                v8 = (_DWORD *)*((_DWORD *)*a2 + 3);
                v7 = (_DWORD *)*((_DWORD *)*a2 + 4);
                v4 = pathR;
                if (v4 == 2)
                {
                        if (*(_DWORD *)v8 == 43)
                              return 0;
                        if ((*(_DWORD *)v8 != 45 || *((_DWORD *)v8 + 1)) && *(_DWORD *)v9 != 35)
                        {
                              if (*((_DWORD *)v8 + 1) == 1)
                                        return 1;
                        }
                        else
                        {
                              *a2 = v8;
                              *((_DWORD *)*a2 + 1) = 1;
                        }
                }
                else if (v4 > 2)
                {
                        if (v4 == 3)
                        {
                              if (v7==0||*(_DWORD *)v7 == 43)
                                        return 0;
                              if ((*(_DWORD *)v7 != 45 || *((_DWORD *)v7 + 1)) && *(_DWORD *)v9 != 35)
                              {
                                        if (*((_DWORD *)v7 + 1) == 1)
                                                return 1;
                              }
                              else
                              {
                                        *a2 = v7;
                                        *((_DWORD *)*a2 + 1) = 1;
                              }
                        }
                }
                else if (v4 == 1)
                {
                        if (*(_DWORD *)v9 == 43)
                              return 0;
                        if ((*(_DWORD *)v9 != 45 || *((_DWORD *)v9 + 1)) && *(_DWORD *)v9 != 35)
                        {
                              if (*((_DWORD *)v9 + 1) == 1)
                                        return 1;
                        }
                        else
                        {
                              *a2 = v9;
                              *((_DWORD *)*a2 + 1) = 1;
                        }
                }
      }
      return 1;
}
intDirectionL(_DWORD *this_, _DWORD **a2, int a3, int a4, int a5) {
      int v7; //
      int v8; //
      int v9; //
      v9 = *((_DWORD *)*a2 + 2);
      v8 = *((_DWORD *)*a2 + 3);
      v7 = *((_DWORD *)*a2 + 4);
      if (*(_DWORD *)(v9 + 4) == 1 && *(_DWORD *)(v8 + 4) == 1)
                return (unsigned __int8)RotateL(this_, a2, a3);
      if (*(_DWORD *)(v9 + 4) == 1 && *(_DWORD *)(v7 + 4) == 1)
                return (unsigned __int8)RotateL(this_, a2, a4);
      if (*(_DWORD *)(v8 + 4) != 1 || *(_DWORD *)(v7 + 4) != 1)
                return 0;
      return (unsigned __int8)RotateL(this_, a2, a5);
}
intDirectionR(_DWORD *this_, _DWORD **a2, int a3, int a4, int a5) {
      int v7; //
      int v8; //
      int v9; //

      v9 = *((_DWORD *)*a2 + 2);
      v8 = *((_DWORD *)*a2 + 3);
      v7 = *((_DWORD *)*a2 + 4);
      if (*(_DWORD *)(v9 + 4) == 1 && *(_DWORD *)(v8 + 4) == 1)
                return (unsigned __int8)RotateR(this_, a2, a3);
      if (*(_DWORD *)(v9 + 4) == 1 && *(_DWORD *)(v7 + 4) == 1)
                return (unsigned __int8)RotateR(this_, a2, a4);
      if (*(_DWORD *)(v8 + 4) != 1 || *(_DWORD *)(v7 + 4) != 1)
                return 0;
      return (unsigned __int8)RotateR(this_, a2, a5);
}
intClockwise(_DWORD *this_, _DWORD **a2) {
      int v2; // ST20_4
      int v5; //
      int v6; //
      int v7; //
      int v8; //

      v8 = *((_DWORD *)*a2 + 2);
      v7 = *((_DWORD *)*a2 + 3);
      v2 = *((_DWORD *)*a2 + 4);
      v6 = *(_DWORD *)(*((_DWORD *)*a2 + 3) + 8);
      v5 = *(_DWORD *)(*((_DWORD *)*a2 + 2) + 12);
      if (*(_DWORD *)v8 == 42 || *(_DWORD *)v7 == 42)
                return (unsigned __int8)RotateL(this_, a2, 6);
      if (*(_DWORD **)(*(_DWORD *)(v6 + 12) + 12) == *a2 && *(_DWORD **)(*(_DWORD *)(v5 + 8) + 8) == *a2)
                return (unsigned __int8)DirectionL(this_, a2, 4, 1, 8);
      if (*(_DWORD **)(v8 + 12) == *a2 && *(_DWORD **)(v7 + 12) == *a2)
                return (unsigned __int8)DirectionL(this_, a2, 6, 7, 2);
      if (*(_DWORD **)(v7 + 8) == *a2 && *(_DWORD **)(v8 + 8) == *a2)
                return (unsigned __int8)DirectionL(this_, a2, 9, 5, 3);
      if (*(_DWORD **)(*(_DWORD *)(v6 + 12) + 12) == *a2)
                return (unsigned __int8)DirectionL(this_, a2, 9, 1, 8);
      if (*(_DWORD **)(*(_DWORD *)(v5 + 8) + 8) == *a2)
                return (unsigned __int8)DirectionL(this_, a2, 4, 7, 8);
      return (unsigned __int8)DirectionL(this_, a2, 9, 7, 8);
}
intCounterclockwise(_DWORD *this_, _DWORD **a2) {
      int v4; //
      int v5; //
      int v6; //
      int v7; //

      v7 = *((_DWORD *)*a2 + 2);
      v6 = *((_DWORD *)*a2 + 3);
      v5 = *(_DWORD *)(*((_DWORD *)*a2 + 3) + 8);
      v4 = *(_DWORD *)(*((_DWORD *)*a2 + 2) + 12);
      if (*(_DWORD *)v7 == 42 || *(_DWORD *)v6 == 42)
                return (unsigned __int8)RotateR(this_, a2, 6);
      if (*(_DWORD **)(*(_DWORD *)(v5 + 12) + 12) == *a2 && *(_DWORD **)(*(_DWORD *)(v4 + 8) + 8) == *a2)
                return (unsigned __int8)DirectionR(this_, a2, 4, 8, 1);
      if (*(_DWORD **)(v7 + 12) == *a2 && *(_DWORD **)(v6 + 12) == *a2)
                return (unsigned __int8)DirectionR(this_, a2, 9, 3, 5);
      if (*(_DWORD **)(v6 + 8) == *a2 && *(_DWORD **)(v7 + 8) == *a2)
                return (unsigned __int8)DirectionR(this_, a2, 6, 2, 7);
      if (*(_DWORD **)(*(_DWORD *)(v5 + 12) + 12) == *a2)
                return (unsigned __int8)DirectionR(this_, a2, 4, 8, 7);
      if (*(_DWORD **)(*(_DWORD *)(v4 + 8) + 8) == *a2)
                return (unsigned __int8)DirectionR(this_, a2, 9, 8, 1);
      return (unsigned __int8)DirectionR(this_, a2, 9, 8, 7);
}
intCheckUseCount(_DWORD *this_) {
      _DWORD *v1; // ST10_4
      int l; //
      int j; //
      signed int k; //
      int i; //
      _DWORD *v7; //
      _DWORD *v8; //
      int v9; //

      v9 = 0;
      v1 = *(_DWORD **)this_;
      for (i = 0; *((_DWORD *)this_ + 1) > i; ++i)
      {
                v8 = *(_DWORD **)this_;
                for (j = 0; j < i; ++j)
                        v8 = *(_DWORD **)(v8 + 8);
                if (*(_DWORD **)this_ != v8 && *(_DWORD *)(v8 + 4) == 1)
                        ++v9;
                v7 = v8;
                for (k = 0; k <= 5; ++k)
                {
                        if (v8 == 1)
                              ++v9;
                        v8 = (_DWORD *)v8;
                        for (l = 0; l < i; ++l)
                        {
                              if (v8 == 1)
                                        ++v9;
                              v8 = (_DWORD *)v8;
                              if ((_DWORD *)v8 == v7)
                                        break;
                              if (v8 == 1)
                                        ++v9;
                              v8 = (_DWORD *)v8;
                        }
                }
      }
      return v9;
}
int CheckFlag(_DWORD*arg1, char* Str) {
      signed int v3; //
      char v4; //
      size_t i; //
      _DWORD *v7; //
      v7 = *(_DWORD **)arg1;
      int dep = 0;
      for (i = 0; i < strlen(Str); ++i) {
                v4 = Str;
                if (v4 == 76)
                {
                        if (*(_DWORD **)arg1 == v7)
                        {
                              if (!(unsigned __int8)RotateL(arg1, (_DWORD **)&v7, 0))
                                        return dep;
                        }
                        else if (!(unsigned __int8)Clockwise(arg1, (_DWORD **)&v7))
                        {
                              return dep;
                        }
                        dep++;
                }
               
                else if (v4 == 82)
                {
                        if (*(_DWORD **)arg1 == v7)
                        {
                              if (!(unsigned __int8)RotateR(arg1, (_DWORD **)&v7, 0))
                                        return dep;
                        }
                        else if (!(unsigned __int8)Counterclockwise(arg1, (_DWORD **)&v7))
                        {
                              return dep;
                        }
                        dep++;
                }
      }
      //v3 = 0;
      if (*v7 == 35 && CheckUseCount(arg1) == 94) {
                //v3 = 1;
                dep = -1;
      }
      if (dep == strlen(Str)) {
                dep = strlen(Str)-1;
      }
      return dep;
}
```
而爆破的思路也很简单。我们将CheckFlag稍做修改,使其返回正确或检测发生错误时的下标。初始输入全为L,“LLLLLLLLLLLLLLLLLLLLLLLLL”当检测出错下标值为L时,替换为R。当为R时,则向前找最近的一个L变为R,后面再全置为L。以及一个标识记录检测正确的位数。
最后通过递归实现爆破
```
int find_lastL(char* input,int err_index) {
      while (input == 'R') {
                err_index--;
      }
      return err_index;
}
void new_input(char*input, int R_index) {
      input = 'R';
      for (int i = R_index+1; i < 25; i++) {
                input = 'L';
      }
}
int m_check(char* input,int right_count) {
      char* v3 = new char{ 0 };
      char*v7 = v3;
      for (int i = 0; i <= 4; ++i) {
                IncDepth(v7);
      }
      g_num = 0;
      int err_index = CheckFlag((_DWORD*)v7, input);
      if (err_index != -1) {//=-1为正确
                if (input == 'L') {
                        input = 'R';
                }
                else {
                        int lastL = find_lastL(input, err_index);
                        if (right_count <= lastL) {
                              new_input(input, lastL);
                              if (right_count == lastL ) {
                                        right_count++;
                              }
                        }
                }
                return m_check(input, right_count);
      }
      return 1;
}
int main()
{
      char input[] = "LLLLLLLLLLLLLLLLLLLLLLLLL";
      m_check(input, 0);
      printf("%s", input);
      return 0;
}
```

生锈的M4A1 发表于 2020-10-12 16:18

虽然我看不懂代码,但我知道西湖论剑主办方是杭州安恒{:1_893:}

Dboykey 发表于 2020-10-12 16:48

硬核,看不懂!

yu6319119 发表于 2020-10-12 18:05

完全看不懂啊,要多学习才行了

bob1994 发表于 2020-10-12 18:28

杭州安恒{:1_926:}{:1_926:}

anlovedong 发表于 2020-10-13 05:14

可惜小白的我,看的有点懵

xiatian5200 发表于 2020-10-13 08:05

啥东西都是代码看不明白

谈何易i 发表于 2020-10-13 09:56

卧槽牛逼,直接爆破出来!

chen4490 发表于 2020-10-13 15:25


学习了!谢谢!

ghostsang 发表于 2020-10-13 16:37

本帖最后由 ghostsang 于 2020-10-13 16:41 编辑

大佬代码是IDA直接反编译扣出来的吗, 我做的时候也想着爆破,不会整,直接手动输入爆破{:1_909:}
页: [1] 2
查看完整版本: 2020西湖论剑 re-Cellular