没有什么花里胡哨的东西,进去之后逻辑很清晰
int __cdecl main(int argc, const char **argv, const char **envp)
{
Honeycomb *v3; // ebx
char *Format; // [esp+0h] [ebp-58h]
int i; // [esp+28h] [ebp-30h]
Honeycomb *v7; // [esp+2Ch] [ebp-2Ch]
char v8; // [esp+30h] [ebp-28h]
_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; // [esp+14h] [ebp-14h]
char str_i; // [esp+1Bh] [ebp-Dh]
size_t i; // [esp+20h] [ebp-8h]
_DWORD *v7; // [esp+24h] [ebp-4h]
v7 = *(_DWORD **)this;
for ( i = 0; i < strlen(Str); ++i )
{
str_i = Str[i];
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; // [esp+8h] [ebp-20h]
signed int i; // [esp+Ch] [ebp-1Ch]
_DWORD *v15; // [esp+18h] [ebp-10h]
_DWORD *v16; // [esp+1Ch] [ebp-Ch]
_DWORD *arg2a; // [esp+34h] [ebp+Ch]
_DWORD *arg2c; // [esp+34h] [ebp+Ch]
_DWORD *arg2d; // [esp+34h] [ebp+Ch]
_DWORD *arg2b; // [esp+34h] [ebp+Ch]
_DWORD *arg2e; // [esp+34h] [ebp+Ch]
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[g_num++];
v3 = (_DWORD *) new char[0x14]{ 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[g_num++];
v5 = (_DWORD *) new char[0x14]{ 0 };
*(_DWORD *)v5 = v4;
*((_DWORD *)arg2a + 2) = (_DWORD)v5;
*((_DWORD *)v5 + 2) = (_DWORD)arg2a;
arg2c = v5;
v6 = map[g_num++];
v7 = (_DWORD *) new char[0x14]{ 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[g_num++];
v9 = (_DWORD *) new char[0x14]{ 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[g_num++];
v11 = (_DWORD *) new char[0x14]{ 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[g_num++];
char* v2= new char[0x14]{ 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[g_num++];
v4 = new char[0x14]{ 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; // [esp+3h] [ebp-15h]
signed int i; // [esp+8h] [ebp-10h]
_DWORD *v7; // [esp+Ch] [ebp-Ch]
_DWORD *v8; // [esp+10h] [ebp-8h]
_DWORD *v9; // [esp+14h] [ebp-4h]
for (i = 0; i <= 4; ++i)
{
v9 = (_DWORD *)*((_DWORD *)*a2 + 2);
v8 = (_DWORD *)*((_DWORD *)*a2 + 3);
v7 = (_DWORD *)*((_DWORD *)*a2 + 4);
v4 = pathL[5 * a3 + i];
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; // [esp+3h] [ebp-15h]
signed int i; // [esp+8h] [ebp-10h]
_DWORD *v7; // [esp+Ch] [ebp-Ch]
_DWORD *v8; // [esp+10h] [ebp-8h]
_DWORD *v9; // [esp+14h] [ebp-4h]
for (i = 0; i <= 4; ++i)
{
v9 = (_DWORD *)*((_DWORD *)*a2 + 2);
v8 = (_DWORD *)*((_DWORD *)*a2 + 3);
v7 = (_DWORD *)*((_DWORD *)*a2 + 4);
v4 = pathR[5 * a3 + i];
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;
}
int DirectionL(_DWORD *this_, _DWORD **a2, int a3, int a4, int a5) {
int v7; // [esp+10h] [ebp-Ch]
int v8; // [esp+14h] [ebp-8h]
int v9; // [esp+18h] [ebp-4h]
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);
}
int DirectionR(_DWORD *this_, _DWORD **a2, int a3, int a4, int a5) {
int v7; // [esp+10h] [ebp-Ch]
int v8; // [esp+14h] [ebp-8h]
int v9; // [esp+18h] [ebp-4h]
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);
}
int Clockwise(_DWORD *this_, _DWORD **a2) {
int v2; // ST20_4
int v5; // [esp+18h] [ebp-14h]
int v6; // [esp+1Ch] [ebp-10h]
int v7; // [esp+24h] [ebp-8h]
int v8; // [esp+28h] [ebp-4h]
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);
}
int Counterclockwise(_DWORD *this_, _DWORD **a2) {
int v4; // [esp+18h] [ebp-10h]
int v5; // [esp+1Ch] [ebp-Ch]
int v6; // [esp+20h] [ebp-8h]
int v7; // [esp+24h] [ebp-4h]
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);
}
int CheckUseCount(_DWORD *this_) {
_DWORD *v1; // ST10_4
int l; // [esp+0h] [ebp-18h]
int j; // [esp+4h] [ebp-14h]
signed int k; // [esp+4h] [ebp-14h]
int i; // [esp+8h] [ebp-10h]
_DWORD *v7; // [esp+Ch] [ebp-Ch]
_DWORD *v8; // [esp+10h] [ebp-8h]
int v9; // [esp+14h] [ebp-4h]
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[4] + 8);
if (*(_DWORD **)this_ != v8 && *(_DWORD *)(v8[2] + 4) == 1)
++v9;
v7 = v8;
for (k = 0; k <= 5; ++k)
{
if (v8[1] == 1)
++v9;
v8 = (_DWORD *)v8[3];
for (l = 0; l < i; ++l)
{
if (v8[1] == 1)
++v9;
v8 = (_DWORD *)v8[3];
if ((_DWORD *)v8[2] == v7)
break;
if (v8[1] == 1)
++v9;
v8 = (_DWORD *)v8[2];
}
}
}
return v9;
}
int CheckFlag(_DWORD*arg1, char* Str) {
signed int v3; // [esp+14h] [ebp-14h]
char v4; // [esp+1Bh] [ebp-Dh]
size_t i; // [esp+20h] [ebp-8h]
_DWORD *v7; // [esp+24h] [ebp-4h]
v7 = *(_DWORD **)arg1;
int dep = 0;
for (i = 0; i < strlen(Str); ++i) {
v4 = Str[i];
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[err_index] == 'R') {
err_index--;
}
return err_index;
}
void new_input(char*input, int R_index) {
input[R_index] = 'R';
for (int i = R_index+1; i < 25; i++) {
input[i] = 'L';
}
}
int m_check(char* input,int right_count) {
char* v3 = new char[8]{ 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[err_index] == 'L') {
input[err_index] = '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;
}