buu题解-[ACTF新生赛2020]usualCrypt

打开文件,查壳,无壳

拖入到ida中查看,找到主函数

​

int __cdecl main(int argc, const char **argv, const char **envp)
{
  int v3; // esi
  int v5[3]; // [esp+8h] [ebp-74h] BYREF
  __int16 v6; // [esp+14h] [ebp-68h]
  char v7; // [esp+16h] [ebp-66h]
  char v8[100]; // [esp+18h] [ebp-64h] BYREF

  sub_403CF8(&unk_40E140);
  scanf("%s", v8);
  memset(v5, 0, sizeof(v5));
  v6 = 0;
  v7 = 0;
  sub_401080(v8, strlen(v8), v5);
  v3 = 0;
  while ( *(v5 + v3) == byte_40E0E4[v3] )
  {
    if ( ++v3 > strlen(v5) )
      goto LABEL_6;
  }
  sub_403CF8(aError);
LABEL_6:
  if ( v3 - 1 == strlen(byte_40E0E4) )
    return sub_403CF8(aAreYouHappyYes);
  else
    return sub_403CF8(aAreYouHappyNo);
}

[点击并拖拽以移动]
​

 可以看到, sub_401080(v8, strlen(v8), v5);函数对输入的v8进行了处理,我们跟进查看

int __cdecl sub_401080(int a1, int a2, int a3)
{
  int v3; // edi
  int v4; // esi
  int v5; // edx
  int v6; // eax
  int v7; // ecx
  int v8; // esi
  int v9; // esi
  int v10; // esi
  int v11; // esi
  _BYTE *v12; // ecx
  int v13; // esi
  int v15; // [esp+18h] [ebp+8h]

  v3 = 0;
  v4 = 0;
  sub_401000();
  v5 = a2 % 3;
  v6 = a1;
  v7 = a2 - a2 % 3;
  v15 = a2 % 3;
  if ( v7 > 0 )
  {
    do
    {
      LOBYTE(v5) = *(a1 + v3);
      v3 += 3;
      v8 = v4 + 1;
      *(v8 + a3 - 1) = byte_40E0A0[(v5 >> 2) & 0x3F];
      *(++v8 + a3 - 1) = byte_40E0A0[16 * (*(a1 + v3 - 3) & 3) + ((*(a1 + v3 - 2) >> 4) & 0xF)];
      *(++v8 + a3 - 1) = byte_40E0A0[4 * (*(a1 + v3 - 2) & 0xF) + ((*(a1 + v3 - 1) >> 6) & 3)];
      v5 = *(a1 + v3 - 1) & 0x3F;
      v4 = v8 + 1;
      *(v4 + a3 - 1) = byte_40E0A0[v5];
    }
    while ( v3 < v7 );
    v5 = v15;
  }
  if ( v5 == 1 )
  {
    LOBYTE(v7) = *(v3 + a1);
    v9 = v4 + 1;
    *(v9 + a3 - 1) = byte_40E0A0[(v7 >> 2) & 0x3F];
    v10 = v9 + 1;
    *(v10 + a3 - 1) = byte_40E0A0[16 * (*(v3 + a1) & 3)];
    *(v10 + a3) = 61;
LABEL_8:
    v13 = v10 + 1;
    *(v13 + a3) = 61;
    v4 = v13 + 1;
    goto LABEL_9;
  }
  if ( v5 == 2 )
  {
    v11 = v4 + 1;
    *(v11 + a3 - 1) = byte_40E0A0[(*(v3 + a1) >> 2) & 0x3F];
    v12 = (v3 + a1 + 1);
    LOBYTE(v6) = *v12;
    v10 = v11 + 1;
    *(v10 + a3 - 1) = byte_40E0A0[16 * (*(v3 + a1) & 3) + ((v6 >> 4) & 0xF)];
    *(v10 + a3) = byte_40E0A0[4 * (*v12 & 0xF)];
    goto LABEL_8;
  }
LABEL_9:
  *(v4 + a3) = 0;
  return sub_401030(a3);
}

 可以看到是一个很明显的base64加密函数,但是注意看在对数据加密前有sub_401000()函数(做题的时候这个就没看到,哭.jpg)我们跟进查看这个函数

int sub_401000()
{
  int result; // eax
  char v1; // cl

  for ( result = 6; result < 15; ++result )
  {
    v1 = byte_40E0AA[result];
    byte_40E0AA[result] = byte_40E0A0[result];
    byte_40E0A0[result] = v1;
  }
  return result;
}

 可以看到,从第七个开始到第15个将byte_40E0AA与byte_40E0A0中的数据进行交换,可以找到byte_40E0AA与byte_40E0A0的数据分别为'KLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'和'ABCDEFGHIJ'变换后密码表为’ABCDEFQRSTUVWXYZGHIJKLMNOPabcdefghijklmnopqrstuvwxyz0123456789+/‘

然后接着往下看,发现最后返回的是sub_401030(a3)函数,我们再查看这个函数

int __cdecl sub_401030(const char *a1)
{
  __int64 v1; // rax
  char v2; // al

  v1 = 0i64;
  if ( strlen(a1) )
  {
    do
    {
      v2 = a1[HIDWORD(v1)];
      if ( v2 < 'a' || v2 > 'z' )
      {
        if ( v2 < 'A' || v2 > 'Z' )
          goto LABEL_9;
        LOBYTE(v1) = v2 + ' ';
      }
      else
      {
        LOBYTE(v1) = v2 - 32;
      }
      a1[HIDWORD(v1)] = v1;
LABEL_9:
      LODWORD(v1) = 0;
      ++HIDWORD(v1);
    }
    while ( HIDWORD(v1) < strlen(a1) );
  }
  return v1;
}

发现是大小写转换,转换后得到 byte_40E0E4(此处出自主函数),分析完后写脚本解密

import base64
import string

str = "ZmxhZ3tiGNXlXjHfaDTzN2FfK3LycRTpc2L9"   # 欲解密的字符串
outtab  = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"  #  原生字母表
intab   = "ABCDEFQRSTUVWXYZGHIJKLMNOPabcdefghijklmnopqrstuvwxyz0123456789+/"  #  换表之后的字母表

print (base64.b64decode(str.translate(str.maketrans(intab,outtab))))

得到flag

学到的知识点:

  • 判断函数代码是base64加密,确定是base64加密后,查看加密前后有无变换,此处附上常用的base64换表解密代码
    import base64
    import string
    
    str = ""   # 欲解密的字符串
    outtab  = ""  #  原生字母表
    intab   = ""  #  换表之后的字母表
    
    print (base64.b64decode(str.translate(str.maketrans(intab,outtab))))
  • 大小写转换代码
    int __cdecl sub_401030(const char *a1)
    {
      __int64 v1; // rax
      char v2; // al
    
      v1 = 0i64;
      if ( strlen(a1) )
      {
        do
        {
          v2 = a1[HIDWORD(v1)];
          if ( v2 < 'a' || v2 > 'z' )
          {
            if ( v2 < 'A' || v2 > 'Z' )
              goto LABEL_9;
            LOBYTE(v1) = v2 + ' ';
          }
          else
          {
            LOBYTE(v1) = v2 - 32;
          }
          a1[HIDWORD(v1)] = v1;
    LABEL_9:
          LODWORD(v1) = 0;
          ++HIDWORD(v1);
        }
        while ( HIDWORD(v1) < strlen(a1) );
      }
      return v1;
    }

     

  • 此处再补充一个关于base家族解密的工具 ,kali的basecrack感觉挺好用,具体参考一位大佬文章basecrack使用
  • 对来自用户输入的单个Base编码数据进行解码:python basecrack.py
    对通过参数(-b/--base)传递的单个Base编码数据进行解码:
    python basecrack.py -b SGVsbG8gV29ybGQh
    对通过文件(-f/--file)传递的多个Base编码数据进行解码:
    python basecrack.py -f file.txt
    对任意模式的多重Base编码数据进行解码(-m/--magic):
    python basecrack.py --magic
    使用解码的Base数据生成字典文件并输出(-o/--output):
    python basecrack.py -f file.txt -o output-wordlist.txt

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值