首页
社区
课程
招聘
[原创]看雪.纽盾 KCTF晋级赛2019 Q2 第六题 消失的岛屿
发表于: 2019-6-18 14:37 2787

[原创]看雪.纽盾 KCTF晋级赛2019 Q2 第六题 消失的岛屿

2019-6-18 14:37
2787

用IDA载入文件,提示有DWARF debug information,选择yes,可以看到更多的信息。然后我们找到main函数。

int __cdecl main(int argc, const char **argv, const char **envp)
{
  int v3; // eax
  uint8_t bindata; // [esp+11h] [ebp-3Fh]
  const char *v6; // [esp+48h] [ebp-8h]
  char *v7; // [esp+4Ch] [ebp-4h]

  __main();
  printf("please enter Serial:");
  scanf(" %s", &bindata);
  if ( strlen((const char *)&bindata) > 0x31 )
    puts("error");
  v7 = (char *)calloc(1u, 0x400u);
  v3 = strlen((const char *)&bindata);
  base64_encode(&bindata, v7, v3);
  v6 = "!NGV%,$h1f4S3%2P(hkQ94==";
  if ( !strcmp("!NGV%,$h1f4S3%2P(hkQ94==", v7) )
    puts("Success");
  else
    puts("Please Try Again");
  free(v7);
  system("pause");
  return 0;
}
这几乎是源代码了,而且代码逻辑也很简单,输入的字符串base64编码以后跟"!NGV%,$h1f4S3%2P(hkQ94=="比较,相同则成功。但是这个看起来不是标准base64编码,进入base64_encode函数看看。
int __cdecl base64_encode(const uint8_t *bindata, char *base64, int binlength)
{
  int v3; // eax
  char *v4; // ebx
  int v5; // eax
  int v6; // ST0C_4
  char *v7; // ebx
  int v8; // eax
  int v9; // eax
  char *v10; // ebx
  int v11; // eax
  int v12; // eax
  char *v13; // ebx
  uint8_t current; // [esp+Bh] [ebp-Dh]
  uint8_t currenta; // [esp+Bh] [ebp-Dh]
  int j; // [esp+Ch] [ebp-Ch]
  int ja; // [esp+Ch] [ebp-Ch]
  int jb; // [esp+Ch] [ebp-Ch]
  int i; // [esp+10h] [ebp-8h]

  i = 0;
  j = 0;
  while ( i < binlength )
  {
    v3 = j;
    ja = j + 1;
    v4 = &base64[v3];
    *v4 = charEncrypt((bindata[i] >> 2) & 0x3F);
    current = 16 * bindata[i] & 0x30;
    if ( i + 1 >= binlength )
    {
      v5 = ja;
      v6 = ja + 1;
      v7 = &base64[v5];
      *v7 = charEncrypt(current);
      base64[v6] = 61;
      v8 = v6 + 1;
      j = v6 + 2;
      base64[v8] = 61;
      break;
    }
    v9 = ja;
    jb = ja + 1;
    v10 = &base64[v9];
    *v10 = charEncrypt((bindata[i + 1] >> 4) | current);
    currenta = 4 * bindata[i + 1] & 0x3C;
    if ( i + 2 >= binlength )
    {
      base64[jb] = charEncrypt(currenta);
      v11 = jb + 1;
      j = jb + 2;
      base64[v11] = '=';
      break;
    }
    base64[jb] = charEncrypt((bindata[i + 2] >> 6) | currenta);
    v12 = jb + 1;
    j = jb + 2;
    v13 = &base64[v12];
    *v13 = charEncrypt(bindata[i + 2] & 0x3F);
    i += 3;
  }
  base64[j] = 0;
  return j;
}
charEncrypt函数
char __cdecl charEncrypt(int data)
{
  int dataa; // [esp+18h] [ebp+8h]

  dataa = aTuvwxtulmnopqr[data];
  if ( dataa > '@' && dataa <= 'Z' )
    return 0x9B - dataa;
  if ( dataa > '`' && dataa <= 'z' )
    return dataa - 0x40;
  if ( dataa > '/' && dataa <= '9' )
    return dataa + '2';
  if ( dataa == '+' )
    return 'w';
  if ( dataa == '/' )
    dataa = 'y';
  return dataa;
}
我们可以通过 charEncrypt函数得到真实的码表,把代码复制一份,做点小修改
#include <stdio.h>
char b64_chr[] = "tuvwxTUlmnopqrs7YZabcdefghij8yz0123456VWXkABCDEFGHIJKLMNOPQRS9+/";
char  charEncrypt(int data)
{
  int dataa; // [esp+18h] [ebp+8h]

  dataa = data;
  if ( dataa > '@' && dataa <= 'Z' )
    return 0x9B - dataa;
  if ( dataa > '`' && dataa <= 'z' )
    return dataa - 0x40;
  if ( dataa > '/' && dataa <= '9' )
    return dataa + '2';
  if ( dataa == '+' )
    return 'w';
  if ( dataa == '/' )
    dataa = 'y';
  return dataa;
}
int main(int argc, char const *argv[])
{
	for (int i = 0; i < sizeof(b64_chr); ++i)
	{
		printf("%c",charEncrypt(b64_chr[i]));
	}
	return 0;
}
运行得到"45678GF,-./0123iBA!\"#$%&'()*j9:bcdefghEDC+ZYXWVUTSRQPONMLKJIHkwy",这个就是真正的码表。
用这个码表解密" !NGV%,$h1f4S3%2P(hkQ94==",得到key:KanXue2019ctf_st
int __cdecl main(int argc, const char **argv, const char **envp)
{
  int v3; // eax
  uint8_t bindata; // [esp+11h] [ebp-3Fh]
  const char *v6; // [esp+48h] [ebp-8h]
  char *v7; // [esp+4Ch] [ebp-4h]

  __main();
  printf("please enter Serial:");
  scanf(" %s", &bindata);
  if ( strlen((const char *)&bindata) > 0x31 )
    puts("error");
  v7 = (char *)calloc(1u, 0x400u);
  v3 = strlen((const char *)&bindata);
  base64_encode(&bindata, v7, v3);
  v6 = "!NGV%,$h1f4S3%2P(hkQ94==";
  if ( !strcmp("!NGV%,$h1f4S3%2P(hkQ94==", v7) )
    puts("Success");
  else
    puts("Please Try Again");
  free(v7);
  system("pause");
  return 0;
}
这几乎是源代码了,而且代码逻辑也很简单,输入的字符串base64编码以后跟"!NGV%,$h1f4S3%2P(hkQ94=="比较,相同则成功。但是这个看起来不是标准base64编码,进入base64_encode函数看看。
int __cdecl base64_encode(const uint8_t *bindata, char *base64, int binlength)
{
  int v3; // eax
  char *v4; // ebx
  int v5; // eax
  int v6; // ST0C_4
  char *v7; // ebx
  int v8; // eax
  int v9; // eax
  char *v10; // ebx
  int v11; // eax
  int v12; // eax
  char *v13; // ebx
  uint8_t current; // [esp+Bh] [ebp-Dh]
  uint8_t currenta; // [esp+Bh] [ebp-Dh]
  int j; // [esp+Ch] [ebp-Ch]
  int ja; // [esp+Ch] [ebp-Ch]
  int jb; // [esp+Ch] [ebp-Ch]
  int i; // [esp+10h] [ebp-8h]

  i = 0;
  j = 0;
  while ( i < binlength )
  {
    v3 = j;
    ja = j + 1;
    v4 = &base64[v3];
    *v4 = charEncrypt((bindata[i] >> 2) & 0x3F);
    current = 16 * bindata[i] & 0x30;
    if ( i + 1 >= binlength )
    {
      v5 = ja;
      v6 = ja + 1;
      v7 = &base64[v5];
      *v7 = charEncrypt(current);
      base64[v6] = 61;
      v8 = v6 + 1;
      j = v6 + 2;
      base64[v8] = 61;
      break;
    }
    v9 = ja;
    jb = ja + 1;
    v10 = &base64[v9];
    *v10 = charEncrypt((bindata[i + 1] >> 4) | current);
    currenta = 4 * bindata[i + 1] & 0x3C;
    if ( i + 2 >= binlength )
    {
      base64[jb] = charEncrypt(currenta);
      v11 = jb + 1;
      j = jb + 2;
      base64[v11] = '=';
      break;
    }
    base64[jb] = charEncrypt((bindata[i + 2] >> 6) | currenta);
    v12 = jb + 1;
    j = jb + 2;
    v13 = &base64[v12];
    *v13 = charEncrypt(bindata[i + 2] & 0x3F);
    i += 3;
  }
  base64[j] = 0;
  return j;
}
charEncrypt函数
int __cdecl base64_encode(const uint8_t *bindata, char *base64, int binlength)
{
  int v3; // eax
  char *v4; // ebx
  int v5; // eax
  int v6; // ST0C_4
  char *v7; // ebx
  int v8; // eax
  int v9; // eax
  char *v10; // ebx
  int v11; // eax
  int v12; // eax
  char *v13; // ebx
  uint8_t current; // [esp+Bh] [ebp-Dh]
  uint8_t currenta; // [esp+Bh] [ebp-Dh]
  int j; // [esp+Ch] [ebp-Ch]
  int ja; // [esp+Ch] [ebp-Ch]
  int jb; // [esp+Ch] [ebp-Ch]
  int i; // [esp+10h] [ebp-8h]

  i = 0;
  j = 0;
  while ( i < binlength )
  {
    v3 = j;
    ja = j + 1;
    v4 = &base64[v3];
    *v4 = charEncrypt((bindata[i] >> 2) & 0x3F);
    current = 16 * bindata[i] & 0x30;
    if ( i + 1 >= binlength )
    {
      v5 = ja;
      v6 = ja + 1;
      v7 = &base64[v5];
      *v7 = charEncrypt(current);
      base64[v6] = 61;
      v8 = v6 + 1;
      j = v6 + 2;
      base64[v8] = 61;
      break;
    }
    v9 = ja;
    jb = ja + 1;
    v10 = &base64[v9];
    *v10 = charEncrypt((bindata[i + 1] >> 4) | current);
    currenta = 4 * bindata[i + 1] & 0x3C;
    if ( i + 2 >= binlength )
    {
      base64[jb] = charEncrypt(currenta);
      v11 = jb + 1;
      j = jb + 2;
      base64[v11] = '=';
      break;
    }
    base64[jb] = charEncrypt((bindata[i + 2] >> 6) | currenta);
    v12 = jb + 1;
    j = jb + 2;
    v13 = &base64[v12];
    *v13 = charEncrypt(bindata[i + 2] & 0x3F);
    i += 3;
  }
  base64[j] = 0;
  return j;
}
charEncrypt函数
char __cdecl charEncrypt(int data)
{
  int dataa; // [esp+18h] [ebp+8h]

  dataa = aTuvwxtulmnopqr[data];
  if ( dataa > '@' && dataa <= 'Z' )
    return 0x9B - dataa;
  if ( dataa > '`' && dataa <= 'z' )
    return dataa - 0x40;
  if ( dataa > '/' && dataa <= '9' )
    return dataa + '2';
  if ( dataa == '+' )
    return 'w';
  if ( dataa == '/' )
    dataa = 'y';
  return dataa;
}
我们可以通过 charEncrypt函数得到真实的码表,把代码复制一份,做点小修改
char __cdecl charEncrypt(int data)
{
  int dataa; // [esp+18h] [ebp+8h]

  dataa = aTuvwxtulmnopqr[data];
  if ( dataa > '@' && dataa <= 'Z' )
    return 0x9B - dataa;
  if ( dataa > '`' && dataa <= 'z' )
    return dataa - 0x40;
  if ( dataa > '/' && dataa <= '9' )
    return dataa + '2';
  if ( dataa == '+' )
    return 'w';
  if ( dataa == '/' )
    dataa = 'y';
  return dataa;
}

[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

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