• 2022年深信服杯四川省大学生信息安全技术大赛-CTF-Reverse复现(部分)


    Rush B

    在这里插入图片描述

    开始先设置一下数字以16进制格式显示

    在这里插入图片描述
    在这里插入图片描述

    看主函数

    __int64 __fastcall main(int a1, char **a2, char **a3)
    {
      int v3; // eax
      size_t v4; // rax
      int v5; // ecx
      char v6; // al
      int v7; // ecx
      int v9; // [rsp+3Ch] [rbp-404h]
      char s[1000]; // [rsp+40h] [rbp-400h] BYREF
      char **v11; // [rsp+428h] [rbp-18h]
      int v12; // [rsp+434h] [rbp-Ch]
      unsigned int v13; // [rsp+438h] [rbp-8h]
      int v14; // [rsp+43Ch] [rbp-4h]
    
      v13 = 0;
      v12 = a1;
      v11 = a2;
      memset(s, 0, sizeof(s));
      v14 = v12;
      v9 = 0xC1C2064A;
      while ( 1 )
      {
        while ( 1 )
        {
          while ( v9 == 0x8EA211B0 )
          {
            v6 = sub_4005A0(v11[1]);
            v7 = 0xB732FD38;
            if ( v6 )
              v7 = 0x3C9B63CE;
            v9 = v7;
          }
          if ( v9 != 0x8FD5B3CA )
            break;
          v13 = 0;
          v9 = 0xA66258D6;
        }
        if ( v9 == 0xA66258D6 )
          break;
        switch ( v9 )
        {
          case 0xB732FD38:
            printf("RUSH AGAIN!\n");
            v13 = 1;
            v9 = 0xA66258D6;
            break;
          case 0xC1C2064A:
            v3 = 0xBCCA5E6;
            if ( v14 != 2 )
              v3 = 0xB732FD38;
            v9 = v3;
            break;
          case 0xBCCA5E6:
            v4 = strlen(v11[1]);
            v5 = 0x8EA211B0;
            if ( v4 != 0x44 )
              v5 = 0xB732FD38;
            v9 = v5;
            break;
          default:
            v9 = 0x8FD5B3CA;
            printf("Congratulations! You have rushed B! Flag is flag{md5(input)}...\n");
            break;
        }
      }
      return v13;
    }
    
    • 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

    分析一下初始 v9 = 0xC1C2064A; ,那么执行的就是这一段,

     case 0xC1C2064A:
            v3 = 0xBCCA5E6;
            if ( v14 != 2 )
              v3 = 0xB732FD38;
            v9 = v3;
            break;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    v9=0xB732FD38 就会退出,所以初始v14就要等于2

    在这里插入图片描述

    这里有个算字符串长度的,输入的字符串长度要等于68 ,v11[1]中存的是字符串指针的指针

     case 0xBCCA5E6:
            v4 = strlen(v11[1]);
            v5 = 0x8EA211B0;
            if ( v4 != 0x44 )
              v5 = 0xB732FD38;
            v9 = v5;
            break;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    重点就是sub_4005A0这个函数

    在这里插入图片描述

    一坨的while循环

    在这里插入图片描述

    看到这个经典的判断语句

    在这里插入图片描述

    经典迷宫

    在这里插入图片描述

    转到16进制窗口,先提取出来,18个数据一行,把地图画出来

    在这里插入图片描述

    初始点位为(1,1)

    在这里插入图片描述

    地图

    00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
    00 01 02 0B 0A 0A 09 02 0B 08 03 0B 0A 0A 0A 0A 09 00 
    00 06 09 05 03 08 06 09 05 03 0C 06 09 03 0A 09 04 00 
    00 01 06 0C 05 03 0A 0C 06 0E 0A 08 07 0C 01 06 09 00 
    00 07 0A 0B 0D 05 02 0B 0A 0A 0A 09 06 0A 0E 09 05 00 
    00 06 08 05 04 06 0A 0C 03 0B 08 06 0A 09 03 0C 05 00 
    00 03 09 06 0A 0A 0B 09 05 04 03 09 03 0C 04 03 0C 00 
    00 05 06 0A 09 03 0C 05 06 09 05 05 05 03 09 06 09 00 
    00 05 03 09 05 05 03 0C 03 0D 05 06 0C 05 05 03 0D 00 
    00 05 05 04 06 0C 06 0A 0C 05 05 01 03 0D 06 0C 05 00 
    00 05 07 0A 09 03 0B 0A 08 05 05 06 0C 07 09 01 05 00 
    00 05 06 08 06 0C 06 0A 0A 0C 06 0A 09 04 05 07 0C 00 
    00 05 03 0A 09 03 09 03 0A 0A 0B 08 05 03 0C 05 01 00 
    00 05 05 01 05 05 06 0C 03 09 06 09 06 0C 01 06 0D 00 
    00 05 06 0D 05 05 01 03 0D 06 08 07 0A 0A 0E 08 05 00 
    00 07 08 05 06 0C 06 0C 05 03 0A 0C 03 09 03 09 05 00 
    00 06 0A 0E 0A 0A 0A 0A 0C 06 0A 0A 0C 06 0C 06 1E 00 
    00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    判断路能不能走,v14一共有4种取值,0,1,2,3

    在这里插入图片描述

    可以先将成立的情况列出来,byte_602040[] 的取值为0x00 - 0x0E (唯一一个0x1E就是终点),

    byte_602040[] 取值v14 取值
    0x00没有v14的值满足条件
    0x010
    0x021
    0x030, 1
    0x042
    0x050,2
    0x061,2
    0x070,1,2
    0x083
    0x090,3
    0x0A1,3
    0x0B0,1,3
    0x0C2,3
    0x0D0,2,3
    0x0E1,2,3

    结束条件,要让条件成立byte_602040[] 就得大于等于0x10,满足条件的只有一个0x1E

    在这里插入图片描述

    如果路可以走,就变化v16和v15的值,v16是行 ,v15是列

    在这里插入图片描述

    这玩意麻烦就麻烦在你能走的路径是会变的,先分析前几步理一下思路,我把循环层数标了下,一共14层循环。。。

    __int64 __fastcall sub_4005A0(__int64 a1)
    {
      unsigned int v1; // eax
      unsigned int v2; // eax
      unsigned int v3; // eax
      int v4; // eax
      int v5; // eax
      int v6; // eax
      unsigned int v7; // eax
      unsigned int v8; // eax
      int v9; // eax
      unsigned int v10; // eax
      unsigned int v12; // [rsp+68h] [rbp-20h]
      unsigned __int8 v13; // [rsp+6Ch] [rbp-1Ch]
      unsigned __int8 v14; // [rsp+6Dh] [rbp-1Bh]
      char v15; // [rsp+6Eh] [rbp-1Ah]
      char v16; // [rsp+6Fh] [rbp-19h]
      __int64 v17; // [rsp+70h] [rbp-18h]
      __int64 v18; // [rsp+78h] [rbp-10h]
      unsigned __int8 v19; // [rsp+83h] [rbp-5h]
      int v20; // [rsp+84h] [rbp-4h]
    
      v18 = a1;
      v17 = 0x1010000FFFF00LL;
      v16 = 1;
      v15 = 1;
      v13 = 0;
      v12 = 0x8CF907F5;
      while ( 1 )
      {                                             // 1 
        while ( 1 )
        {                                           // 2
          while ( 1 )
          {                                         // 3
            while ( 1 )
            {                                       // 4
              while ( 1 )
              {                                     // 5
                while ( 1 )
                {                                   // 6
                  while ( 1 )
                  {                                 // 7
                    while ( 1 )
                    {                               // 8
                      while ( 1 )
                      {                             // 9
                        while ( 1 )                 // 12
                        {                           // 10
                          while ( 1 )
                          {                         // 11
                            while ( 1 )
                            {                       // 12
                              while ( 1 )          
                              {    					 // 13
                                while ( v12 == 0x803BA95E )
                                {                   // 14
                                  v19 = 0;
                                  v12 = 0xF4078EB1;
                                }                   // 14
                                if ( v12 != 0x8CF907F5 )
                                  break;
                                v1 = 0xABC759CB;
                                if ( v13 < 0x44u )
                                  v1 = 0xD87E0B66;
                                v12 = v1;
                              }                     // 13
                              if ( v12 != 0x8DA6A494 )
                                break;
                              ++v13;                
                              v12 = 0x8CF907F5;
                            }						// 12
                            if ( v12 != 0x91BFBC64 )
                              break;
                            v14 = 1;
                            v12 = 0xBB25C497;
                          }							//11
                          if ( v12 != 0x97DCB23D )
                            break;
                          v10 = 0x52BAF199;
                          if ( (byte_602040[0x12 * v16 + v15] & 0x10) != 0 )
                            v10 = 0x9F36EED5;
                          v12 = v10;
                        }							//10
                        if ( v12 != 0x990181F1 )
                          break;
                        v14 = 3;
                        v12 = 0xBB25C497;
                      }								//9
                      if ( v12 != 0x9F36EED5 )
                        break;
                      v19 = 1;
                      v12 = 0xF4078EB1;
                    }						//8
                    if ( v12 != 0xABC759CB )
                      break;
                    v19 = 0;
                    v12 = 0xF4078EB1;
                  }							//7
                  if ( v12 != 0xB397B4AE )
                    break;
                  v4 = 0x4157602D;
                  if ( v20 == 0x77 )
                    v4 = 0x4D29FD46;
                  v12 = v4;
                }							//6
                if ( v12 != 0xBB25C497 )
                  break;
                v9 = 0x1C918C9E;
                if ( ((1 << v14) & byte_602040[0x12 * v16 + v15]) != 0 )
                  v9 = 0x23EDBCE0;
                v12 = v9;
              }							//5
              if ( v12 != 0xC91BB3A3 )
                break;
              v2 = 0x2C1C4A6F;
              if ( v20 < 0x73 )
                v2 = 0xE7D58653;
              v12 = v2;
            }							//4
            if ( v12 != 0xD87E0B66 )
              break;
            v20 = *(char *)(v18 + v13);
            v12 = 0xC91BB3A3;
          }							//3
          if ( v12 != 0xE7D58653 )
            break;
          v6 = 0x3EE42C64;
          if ( v20 < 0x64 )
            v6 = 0x1BB52CB7;
          v12 = v6;
        }						//2
        if ( v12 == 0xF4078EB1 )
          break;
        switch ( v12 )
        {
          case 0x1BB52CB7u:
            v8 = 0x4157602D;
            if ( v20 == 0x61 )
              v8 = 0x990181F1;
            v12 = v8;
            break;
          case 0x1C918C9Eu:
            v19 = 0;
            v12 = 0xF4078EB1;
            break;
          case 0x23EDBCE0u:
            v16 += *((_BYTE *)&v17 + 2 * (3 - v14));
            v15 += *((_BYTE *)&v17 + 2 * (3 - v14) + 1);
            v12 = 0x97DCB23D;
            break;
          case 0x2C1C4A6Fu:
            v3 = 0xB397B4AE;
            if ( v20 < 0x77 )
              v3 = 0x4495DA98;
            v12 = v3;
            break;
          case 0x39324084u:
            v14 = 0;
            v12 = 0xBB25C497;
            break;
          case 0x3EE42C64u:
            v7 = 0x4157602D;
            if ( v20 == 0x64 )
              v7 = 0x91BFBC64;
            v12 = v7;
            break;
          case 0x4157602Du:
            v12 = 0x803BA95E;
            break;
          case 0x4495DA98u:
            v5 = 0x4157602D;
            if ( v20 == 0x73 )
              v5 = 0x39324084;
            v12 = v5;
            break;
          case 0x4D29FD46u:
            v14 = 2;
            v12 = 0xBB25C497;
            break;
          default:
            v12 = 0x8DA6A494;
            break;
        }
      }				//1
      return v19;
    }
    
    • 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
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150
    • 151
    • 152
    • 153
    • 154
    • 155
    • 156
    • 157
    • 158
    • 159
    • 160
    • 161
    • 162
    • 163
    • 164
    • 165
    • 166
    • 167
    • 168
    • 169
    • 170
    • 171
    • 172
    • 173
    • 174
    • 175
    • 176
    • 177
    • 178
    • 179
    • 180
    • 181
    • 182
    • 183
    • 184
    • 185
    • 186

    初始 v12 = 0x8CF907F5; ,执行到第13层循环, v12 = 0xD87E0B66

    在这里插入图片描述

    然后会一直跳出到第 3层循环, 取flag的第一个字符到v20中, v12 = 0xC91BB3A3

    在这里插入图片描述

    然后到第4层循环, 0x73 就是 ‘s’ , 盲猜wsad控制上下左右,先假设第一步往右走即 v20 < 0x73 ,v12 = 0xE7D58653

    在这里插入图片描述

    到第2层循环 ,0x64 就是 ‘d’v12=0x3EE42C64

    在这里插入图片描述

    到第1层循环, v12 = 0x91BFBC64

    在这里插入图片描述

    到第11层循环, v14 = 1 , v12 = 0xBB25C497

    在这里插入图片描述

    到第5层循环, 此时byte_602040 = 0x01,v14 = 1 很明显不满足条件, v12 = 0x1C918C9E

    在这里插入图片描述

    到第1层循环,v12 = 0xF4078EB1

    在这里插入图片描述

    再继续就直接退出循环了

    在这里插入图片描述

    然后可以假设第一步是 ‘s’ 的情况,此时 byte_602040 = 0x01,v14 = 0 可以满足条件

    然后推出
    ‘w’ ,v14 = 2 ,
    ‘s’ ,v14 = 0
    ‘a’ ,v14 = 3
    ‘d’ ,v14 = 1

    即 当v14 = 2 时,上一步一定是 w

    简单的说就是根据当前位置来推断出下一步可以走哪几个位置

    比如:
    byte_602040 = 0x01 v14 = 0 ,即只能往下(s)走
    然后下一步
    byte_602040 = 0x06 v14可以取 1,2, 即可以往右(d)或者往上(w),因为这迷宫路径肯定也不能走重复的路径,也不能走死路,那么下一步只能往右走
    下一步
    byte_602040= 0x09 , v14可以取0,3,即可以往下(s)或者往左(a),0x00肯定不能走,所以也只能往下走

    如此反复可以把路径画出来,大概是这样,这图是第一次画的可能有错,我画了两次,第二次忘存了,懒得再画了

    在这里插入图片描述

    最终路径:
    sdsdwwdddsdsaassddwddddsddsassawwasssssddssdwdwwawwwdssdwdsssassdsss

    然后flag就是把路径md5一下就行

    在这里插入图片描述

  • 相关阅读:
    【第92题】JAVA高级技术-网络编程11(简易聊天室6:使用Socket通信)
    `算法知识` 线段树
    混沌工程-经典案例分享
    Chrome Dev Tools
    人脸识别:概述【Loss:Softmax loss、Triplet loss、Centre loss、SphereFace、CosFace、ArcFace】
    这么简单,还不会使用java8 stream流的map()方法吗?
    TCP: 传输控制协议
    【毕业季】总结过去,展望未来
    Go语言Gin框架中使用MySQL数据库的三种方式
    [ESP32 IDF+Vscode]OLED多级菜单显示(摇杆控制)
  • 原文地址:https://blog.csdn.net/ookami6497/article/details/127841610