[NKCTF2023]PMKF RE

定位到关键函数

int sub_401090()
{
  int v1; // [esp+20h] [ebp-140h]
  int v2; // [esp+24h] [ebp-13Ch]
  int k; // [esp+2Ch] [ebp-134h]
  int i; // [esp+30h] [ebp-130h]
  int v5; // [esp+30h] [ebp-130h]
  int j; // [esp+30h] [ebp-130h]
  int v7; // [esp+30h] [ebp-130h]
  char v8; // [esp+34h] [ebp-12Ch]
  DWORD NumberOfBytesRead; // [esp+3Ch] [ebp-124h] BYREF
  unsigned __int8 Buffer; // [esp+43h] [ebp-11Dh] BYREF
  char v11[16]; // [esp+44h] [ebp-11Ch] BYREF
  char v12[256]; // [esp+54h] [ebp-10Ch] BYREF

  memset(v12, 0, sizeof(v12));
  ReadFile(hObject, &Buffer, 1u, &NumberOfBytesRead, 0);
  if ( Buffer != 5 )
  {
    sub_401690((int)"Wrong!\n");
    CloseHandle(hObject);
    exit(0);
  }
  ReadFile(hObject, v12, Buffer, &NumberOfBytesRead, 0);
  for ( i = 0; i < Buffer; ++i )
  {
    if ( v12[i] != byte_405100[i] )
    {
      sub_401690((int)"Wrong!\n");
      CloseHandle(hObject);
      exit(0);
    }
  }
  v5 = 0;
  v8 = 0;
  while ( v5 < Buffer )
    v8 += v12[v5++];
  ReadFile(hObject, v11, 0x10u, &NumberOfBytesRead, 0);
  v2 = 18;
  for ( j = 0; j < 16; ++j )
    v11[j] ^= v8;
  v7 = 0;
  v1 = 1;
  while ( v7 < 16 )
  {
    for ( k = 6; k >= 0; k -= 2 )
    {
      switch ( ((unsigned __int8)v11[v7] >> k) & 3 )
      {
        case 0:
          v2 -= 18;
          break;
        case 1:
          ++v2;
          break;
        case 2:
          v2 += 18;
          break;
        case 3:
          --v2;
          break;
        default:
          break;
      }
      if ( aN[v2] == 42 || aN[v2] == 32 )
      {
        v1 = 0;
        break;
      }
      if ( aN[v2] == 75 )
      {
        sub_401690((int)"Congratulations! you found it!\n");
        break;
      }
    }
    ++v7;
  }
  CloseHandle(hObject);
  return v1;
}

从文件中读入一个5,然后从byte_405100中读取5个字符,点进去可知为"nkman"然后求和得v8,v8作为异或的值
aN为一个迷宫。

******************
N...*****...*....*
**.*****..*...**.*
...*****.*****.*.*
.**....*..*...*..*
....**.*.*..*...**
*.**...*.*.*******
..*****..*......**
.*......**.****.**
...*****...*K...**
******************

然后继续从文件中读入,异或v8,手动走一下迷宫
ddssaassdssassddwdddddwdwwwwwdwddsddwdddsssasaawaasassdddddssaaa
switch语句简单看一下得出上是0,右是1,下是2,左是3
1122332212232211011111010000010112110111222323303323221111122333
关键是这句话的理解for ( k = 6; k >= 0; k -= 2 ) (v11[v7] >> k) & 3
这句话是将v11的每两个二进制位转换为一个四进制位,
那我们就需要转换回去,转回16进制再加上05和'nkman'即为flag
flag:nkctf{056e6b6d616e4fef7eb0004415047000bea9eeb043aa}

v12 = [0x6E, 0x6B, 0x6D, 0x61, 0x6E]#nkman
v8 = 0
for i in range(5):
    v8 += v12[i]
v8 ^= 0x200 
#因为ReadFile(hObject, &Buffer, 1u, &NumberOfBytesRead, 0);
#这段读入函数只读取了v11中的0x10u即16个字节的数据,也就是取了低八位,
#所以等价于与v8的低八位的异或,v8是0x215,我们只取0x15
#有以下迷宫,N为起点,K为终点,只能走'.'的地方,上下左右分别用wsad表示
# ******************
# N...*****...*....*
# **.*****..*...**.*
# ...*****.*****.*.*
# .**....*..*...*..*
# ....**.*.*..*...**
# *.**...*.*.*******
# ..*****..*......**
# .*......**.****.**
# ...*****...*K...**
# ******************
path="ddssaassdssassddwdddddwdwwwwwdwddsddwdddsssasaawaasassdddddssaaa"
path =path.replace("w","0")
path =path.replace("d","1")
path =path.replace("s","2")
path =path.replace("a","3")
s = [path[i:i+4] for i in range(0, len(path), 4)]
qua = [int(x, 4) for x in s]
for i in range(len(qua)):
    qua[i]^=v8
v11=['0x05', '0x6e', '0x6b', '0x6d', '0x61', '0x6e']
for i in range(len(qua)):
    v11.append(hex(qua[i]).zfill(4))#有0x0出现用zfill填满四位
flag = 'nkctf{'+''.join(v11).replace('0x','')+'}'
print(flag)
posted @ 2023-03-30 12:17  Tree_24  阅读(28)  评论(0编辑  收藏  举报