• [buuctf][ACTF新生赛2020]usualCrypt


    [ACTF新生赛2020]usualCrypt

    解析

    第一步还是先查壳32位无壳软件,之后直接拖入ida中。
    还是进入main中,查看伪代码。

    int __cdecl main(int argc, const char **argv, const char **envp)
    {
      int v3; // esi
      int result; // eax
      int v5; // [esp+8h] [ebp-74h]
      int v6; // [esp+Ch] [ebp-70h]
      int v7; // [esp+10h] [ebp-6Ch]
      __int16 v8; // [esp+14h] [ebp-68h]
      char v9; // [esp+16h] [ebp-66h]
      char v10; // [esp+18h] [ebp-64h]
    
      sub_403CF8((int)&unk_40E140);
      scanf(aS, &v10);
      v5 = 0;
      v6 = 0;
      v7 = 0;
      v8 = 0;
      v9 = 0;
      sub_401080((int)&v10, strlen(&v10), (int)&v5);
      v3 = 0;
      while ( *((_BYTE *)&v5 + v3) == byte_40E0E4[v3] )
      {
        if ( ++v3 > strlen((const char *)&v5) )
          goto LABEL_6;
      }
      sub_403CF8((int)aError);
    LABEL_6:
      if ( v3 - 1 == strlen(byte_40E0E4) )
        result = sub_403CF8((int)aAreYouHappyYes);
      else
        result = sub_403CF8((int)aAreYouHappyNo);
      return result;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33

    主要在信息在函数sub_401080里面,进入继续查看。

    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) = *(_BYTE *)(a1 + v3);
          v3 += 3;
          v8 = v4 + 1;
          *(_BYTE *)(v8++ + a3 - 1) = byte_40E0A0[(v5 >> 2) & 0x3F];
          *(_BYTE *)(v8++ + a3 - 1) = byte_40E0A0[16 * (*(_BYTE *)(a1 + v3 - 3) & 3)
                                                + (((signed int)*(unsigned __int8 *)(a1 + v3 - 2) >> 4) & 0xF)];
          *(_BYTE *)(v8 + a3 - 1) = byte_40E0A0[4 * (*(_BYTE *)(a1 + v3 - 2) & 0xF)
                                              + (((signed int)*(unsigned __int8 *)(a1 + v3 - 1) >> 6) & 3)];
          v5 = *(_BYTE *)(a1 + v3 - 1) & 0x3F;
          v4 = v8 + 1;
          *(_BYTE *)(v4 + a3 - 1) = byte_40E0A0[v5];
        }
        while ( v3 < v7 );
        v5 = v15;
      }
      if ( v5 == 1 )
      {
        LOBYTE(v7) = *(_BYTE *)(v3 + a1);
        v9 = v4 + 1;
        *(_BYTE *)(v9 + a3 - 1) = byte_40E0A0[(v7 >> 2) & 0x3F];
        v10 = v9 + 1;
        *(_BYTE *)(v10 + a3 - 1) = byte_40E0A0[16 * (*(_BYTE *)(v3 + a1) & 3)];
        *(_BYTE *)(v10 + a3) = 61;
    LABEL_8:
        v13 = v10 + 1;
        *(_BYTE *)(v13 + a3) = 61;
        v4 = v13 + 1;
        goto LABEL_9;
      }
      if ( v5 == 2 )
      {
        v11 = v4 + 1;
        *(_BYTE *)(v11 + a3 - 1) = byte_40E0A0[((signed int)*(unsigned __int8 *)(v3 + a1) >> 2) & 0x3F];
        v12 = (_BYTE *)(v3 + a1 + 1);
        LOBYTE(v6) = *v12;
        v10 = v11 + 1;
        *(_BYTE *)(v10 + a3 - 1) = byte_40E0A0[16 * (*(_BYTE *)(v3 + a1) & 3) + ((v6 >> 4) & 0xF)];
        *(_BYTE *)(v10 + a3) = byte_40E0A0[4 * (*v12 & 0xF)];
        goto LABEL_8;
      }
    LABEL_9:
      *(_BYTE *)(v4 + a3) = 0;
      return sub_401030((const char *)a3);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70

    前面进入了函数sub_401000里面,继续进入查看。

    .data:0040E0A0 byte_40E0A0     db 'A'                  ; DATA XREF: sub_401000:loc_401005↑r
    .data:0040E0A0                                         ; sub_401000+17↑w ...
    .data:0040E0A1                 db  42h ; B
    .data:0040E0A2                 db  43h ; C
    .data:0040E0A3                 db  44h ; D
    .data:0040E0A4                 db  45h ; E
    .data:0040E0A5                 db  46h ; F
    .data:0040E0A6                 db  47h ; G
    .data:0040E0A7                 db  48h ; H
    .data:0040E0A8                 db  49h ; I
    .data:0040E0A9                 db  4Ah ; J
    .data:0040E0AA ; char byte_40E0AA[]
    .data:0040E0AA byte_40E0AA     db 'K'                  ; DATA XREF: sub_401000+B↑r
    .data:0040E0AA                                         ; sub_401000+11↑w
    .data:0040E0AB aLmnopqrstuvwxy db 'LMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/',0
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    signed int sub_401000()
    {
      signed int result; // eax
      char v1; // cl
    
      result = 6;
      do
      {
        v1 = byte_40E0AA[result];
        byte_40E0AA[result] = byte_40E0A0[result];
        byte_40E0A0[result++] = v1;
      }
      while ( result < 15 );
      return result;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    sub_401000对这个编码表做了什么,等下回来仔细分析,之后继续往下,是做了编码转换,做了base64的编码,之后最下面还有一个sub_401030进入查看一下。

    int __cdecl sub_401030(const char *a1)
    {
      __int64 v1; // rax
      char v2; // al
    
      v1 = 0i64;
      if ( strlen(a1) != 0 )
      {
        do
        {
          v2 = a1[HIDWORD(v1)];
          if ( v2 < 97 || v2 > 122 )
          {
            if ( v2 < 65 || v2 > 90 )
              goto LABEL_9;
            LOBYTE(v1) = v2 + 32;
          }
          else
          {
            LOBYTE(v1) = v2 - 32;
          }
          a1[HIDWORD(v1)] = v1;
    LABEL_9:
          LODWORD(v1) = 0;
          ++HIDWORD(v1);
        }
        while ( HIDWORD(v1) < strlen(a1) );
      }
      return v1;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30

    这就是一个大小写转换,之后回到了main函数,byte_40E0E4就是转换完成之后的,那么这道题就可以解了。

    脚本

    第一步,大小写转换。

    str = 'zMXHz3TIgnxLxJhFAdtZn2fFk3lYCrtPC2l9'
    print(str.swapcase())
    #输出ZmxhZ3tiGNXlXjHfaDTzN2FfK3LycRTpc2L9
    
    • 1
    • 2
    • 3

    第二步,看看那个sub_401000

    #include<stdio.h>
    char byte_40E0AA[56] = "KLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
    int result = 6;
    char byte_40E0A0[12] = "ABCDEFGHIJ";
    char v1;
    int main() {
    	do {
    		v1 = byte_40E0AA[result];
    		byte_40E0AA[result] = byte_40E0A0[result];
    		byte_40E0A0[result++] = v1;
    	} while (result < 15);
    	printf("%s", byte_40E0A0);
    	return 0;
    }
    //输出ABCDEFQRSTUVWXY
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    之后开始对照表,发现位置调换。
    byte_40E0AA第七个开始被调换,被调换了9个,正好位置是15,那就知道了,可以构建出来新的base编码表

    //ABCDEFQRSTUVWXYPGHIJKLMNOZabcdefghijklmnopqrstuvwxyz0123456789+/
    
    • 1

    通过网站链接: 自定义编码转换之后进行转换,获得flag是flag{bAse64_h2s_a_Surprise}

  • 相关阅读:
    HackTheBox UpDown python沙箱逃逸获得用户shell,sudo提权
    【高效开发工具系列】Postman
    2022联想创新科技大会--科技赋能教育数字化转型
    【35. 多重背包】
    【QT开发笔记-基础篇】| 第四章 事件QEvent | 4.9 右键菜单事件
    Dijkstra算法求最短路
    Windows11怎么直接显示更多选项?
    【云原生】使用nginx反向代理后台多服务器
    python+flask计算机毕业设计基于微信小程序的首饰商城系统(程序+开题+论文)
    别再羊了个羊了,大家都在玩刷了个题——LeetCode刷题第3周小结
  • 原文地址:https://blog.csdn.net/m0_71081503/article/details/125572168