首页
论坛
课程
招聘
[原创]KCTF2021 第二题 write up
2021-5-12 01:05 3314

[原创]KCTF2021 第二题 write up

2021-5-12 01:05
3314

环境配置

系统 : win10 64bit \ Windows xp
程序 : pzcrackme.exe
要求 : 求flag
使用工具 :ida pro \ ollydbg \ 微步云沙箱

开始分析

这题有不少迷惑人的手段,所以需要尽可能把程序流程分析清楚,ida中main函数如下:

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
int __cdecl main(int argc, const char **argv, const char **envp)
{
  char Tmp_ch_in_input; // al
  int index_of_str; // esi
  int INDEX_01234567; // ecx
  int v7; // edx
  int sum_index; // eax
  unsigned int column; // ecx
  int choice; // eax
  signed int SIGNAL; // edx
  int T2; // eax
  char *a_pointer_of_matrix; // eax
  char *MATRIX; // eax
  int A_VALUE_SHOULD_BE_ZERO; // edx
  char *v16; // ecx
  int T1; // eax
  int T4; // eax
  int T3; // eax
  int v20; // [esp+1Ch] [ebp-60h]
  unsigned int row; // [esp+20h] [ebp-5Ch]
  unsigned int v22; // [esp+24h] [ebp-58h]
  char _0x30; // [esp+2Bh] [ebp-51h]
  int NUM_0x24; // [esp+2Ch] [ebp-50h]
  char STR[76]; // [esp+30h] [ebp-4Ch]
 
  sub_40AD70();
  sub_4AF840(&dword_4B8860, "Input your code: ");
  sub_4B0AB0(&dword_4B8680, STR);
  if ( strlen(STR) <= 0x30 )                    // len(str) <= 0x30
  {
    Tmp_ch_in_input = STR[0];
    if ( STR[0] )                               // str[0] != null
    {
      index_of_str = 0;
      row = 0;
      v22 = 0;
      NUM_0x24 = dword_4B7020;                  // 24 00 00 00
      _0x30 = a0123456789abcd[0];               // .data:004B7040 30 31 32 33 34 35+a0123456789abcd db '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ',0
While_start:
      if ( NUM_0x24 > 0 )
      {
        INDEX_01234567 = 0;
        if ( _0x30 == Tmp_ch_in_input )         // assert str[0] == 0x30
        {
other_start:
          v7 = (index_of_str + INDEX_01234567 / 6) % 6;
          sum_index = INDEX_01234567 + index_of_str;
          column = v22;
          v20 = v7;
          choice = 5 - sum_index % 6;           // 5 - (sum_index % 6)
          SIGNAL = 0;
          while ( 1 )
          {
            switch ( choice )
            {
              case 1:
                ++column;                       // ++column
                break;
              case 2:
                T1 = (row++ & 1) == 0;          // row++
                column += T1;                   // column += (row%2?0:1)
                break;
              case 3:
                T2 = (row++ & 1) != 0;          // row++
                column -= T2;                   // column -= (row%2?1:0)
                break;
              case 4:
                --column;                       // --column
                break;
              case 5:
                T3 = (row-- & 1) != 0;          // row--
                column -= T3;                   // column -= (row%2?1:0)
                break;
              default:
                T4 = (row-- & 1) == 0;          // row--
                column += T4;                   // column += (row%2?0:1)
                break;
            }
            if ( column > 9 )                   // ten columns
              break;                            // try again
            if ( row > 8 )                      // 9 rows
              break;                            // try again
            a_pointer_of_matrix = &matrix[10 * row + column];
            if ( *a_pointer_of_matrix )
              break;                            // try again
            *a_pointer_of_matrix = 1;
            if ( SIGNAL == 1 )                  // skip this at frist time
            {
              ++index_of_str;
              v22 = column;
              Tmp_ch_in_input = STR[index_of_str];
              if ( Tmp_ch_in_input )
                goto While_start;               // back to start
              goto check;
            }
            SIGNAL = 1;
            choice = v20;
          }
        }
        else                                    // _0x30 != Tmp_ch_in_input
        {
          while ( NUM_0x24 != ++INDEX_01234567 )
          {
            if ( a0123456789abcd[INDEX_01234567] == Tmp_ch_in_input )// .data:004B7040 30 31 32 33 34 35+a0123456789abcd db '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ',0
              goto other_start;
          }
        }
      }
    }
    else
    {
check:
      MATRIX = matrix;
      A_VALUE_SHOULD_BE_ZERO = 0;
      do                                        // check matrix
      {
        v16 = MATRIX + 10;
        do
          A_VALUE_SHOULD_BE_ZERO += *MATRIX++ < 1u;// all element in matrix have not to set as zero
        while ( v16 != MATRIX );
      }
      while ( &unk_4B70DA != v16 );
      if ( !A_VALUE_SHOULD_BE_ZERO )
      {
        printf_4ABF30(&dword_4B8860, "Good job!", 9);
        afterprintf_4AD980(&dword_4B8860);
        return 0;
      }
    }
  }
  printf_4ABF30(&dword_4B8860, "Try again...", 12);
  afterprintf_4AD980(&dword_4B8860);
  return 0;
}

将程序上传到云沙箱里看下,发现有tls_callback存在,可能是有反调试机制;不过先将程序运行起在等候输入的时候od附加就可以正常调试。

 

程序需要将一个matrix填满:

1
2
3
4
5
6
7
8
9
53 01 01 00 00 01 00 00 01 01
01 01 01 00 01 00 00 01 00 00
01 01 01 00 01 01 01 01 01 00
00 01 01 00 01 00 00 01 00 00
00 00 01 00 00 01 00 00 01 01
01 01 00 01 01 01 00 01 00 01
00 00 01 01 01 01 00 01 00 01
00 01 01 00 00 01 00 01 00 01
00 00 00 01 00 00 01 01 00 00

可以看到使用switch语句选择方向:

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
while ( 1 )
{
  switch ( choice )
  {
    case 1:
      ++column;                       // ++column
      break;
    case 2:
      T1 = (row++ & 1) == 0;          // row++
      column += T1;                   // column += (row%2?0:1)
      break;
    case 3:
      T2 = (row++ & 1) != 0;          // row++
      column -= T2;                   // column -= (row%2?1:0)
      break;
    case 4:
      --column;                       // --column
      break;
    case 5:
      T3 = (row-- & 1) != 0;          // row--
      column -= T3;                   // column -= (row%2?1:0)
      break;
    default:
      T4 = (row-- & 1) == 0;          // row--
      column += T4;                   // column += (row%2?0:1)
      break;
  }

手动填写一下:

1
2
3
4
5
6
7
8
9
53 FF 01 1F 20 01 23 24 01 01
01 01 02 1E 01 21 22 01 25 26
04 03 01 1D 01 01 01 01 01 27
05 01 01 1C 01 19 18 01 29 28
06 07 01 1B 1A 01 17 16 01 01
01 01 08 01 01 01 15 01 2B 01
0A 09 01 01 01 01 14 01 2C 01
0B 01 01 0F 10 01 13 01 2D 01
0C 0D 0E 01 11 12 01 01 2E 2F

接下来构造相应的输入了,这里要注意的一个坑点是一个输入控制两次行动而非一次:

1
2
3
4
5
6
7
8
9
10
11
        if ( SIGNAL == 1 )                  // skip this at frist time
        {
          ++index_of_str;
          v22 = column;
          Tmp_ch_in_input = STR[index_of_str];
          if ( Tmp_ch_in_input )
            goto While_start;               // back to start
          goto check;
        }
        SIGNAL = 1;
// jump to beginning of switch

做py如下:

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
matrix = 0x53, 0xFF, 0x01, 0x1E, 0x1F, 0x01, 0x22, 0x23, 0x01, 0x01, 0x01, 0x01, 0x02, 0x1D, 0x01, 0x20,
            0x21, 0x01, 0x24, 0x25, 0x04, 0x03, 0x01, 0x1C, 0x01, 0x01, 0x01, 0x01, 0x01, 0x26, 0x05, 0x01,
            0x01, 0x1B, 0x01, 0x18, 0x17, 0x01, 0x28, 0x27, 0x06, 0x07, 0x01, 0x1A, 0x19, 0x01, 0x16, 0x29,
            0x01, 0x01, 0x01, 0x01, 0x08, 0x01, 0x01, 0x01, 0x15, 0x01, 0x2A, 0x01, 0x0A, 0x09, 0x01, 0x01,
            0x01, 0x01, 0x14, 0x01, 0x2B, 0x01, 0x0B, 0x01, 0x01, 0x0F, 0x10, 0x01, 0x13, 0x01, 0x2C, 0x01,
            0x0C, 0x0D, 0x0E, 0x01, 0x11, 0x12, 0x01, 0x01, 0x2D, 0x2E]
 
'''
           switch ( choice )
            {
              case 1:
                ++column;                       // ++column
                break;
              case 2:
                T1 = (row++ & 1) == 0;          // row++
                column += T1;                   // >>> print((0&1)==0)
                break;
              case 3:
                T2 = (row++ & 1) != 0;          // row++
                column -= T2;                   // >>> print((0&1)!=0)
                break;
              case 4:
                --column;                       // --column
                break;
              case 5:
                T3 = (row-- & 1) != 0;          // row--
                column -= T3;                   // >>> print((0&1)!=0)
                break;
              default:
                T4 = (row-- & 1) == 0;          // row--
                column += T4;                   // >>> print((0&1)==0)
                break;
            }
'''
 
def find_choice(Row,Column,Nrow,Ncolumn):
    choice = 0
 
    for choice in range(0,6):
        row = Row
        column = Column
 
        if choice == 0:
            T4 = (row & 1) == 0
            column += T4
            row -= 1
        if choice == 1:
            column += 1
        if choice == 2:
            T1 = (row & 1) == 0
            column += T1
            row += 1
        if choice == 3:
            T2 = (row & 1) != 0;
            column -= T2
            row += 1
        if choice == 4:
            column -= 1
        if choice == 5:
            T3 = (row & 1) != 0
            column -= T3
            row -= 1
 
        if matrix[row*10+column] == matrix[Nrow*10+Ncolumn]:
            return choice
 
    print('error')
    exit(0)
 
def find_next(row,column):
    if matrix[row*10+column] == 0x53:
        return 0,1
    if matrix[row*10+column] == 0xFF:
        return 1,2
 
    data = matrix[row*10+column]+1
    pos = matrix.index(data)
    return (int(pos/10),pos%10)
 
 
row = 0
column = 0
choices = []
while 1:
    #print(row,column,end=",")
    #print('------->[%d]' % matrix[row*10+column])
    if matrix[row*10+column] == 0x2E:
        #print('Done')
        break
    Nrow,Ncolumn = find_next(row,column)
    choice = find_choice(row,column,Nrow,Ncolumn)
    #print(choice)
    choices.append(choice)
    row,column = Nrow,Ncolumn
 
a123 = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
first_time = True
flag = ""
 
'''
for index_0123 in range(0x24):
    if ( 5 - ((index_0123) % 6) == choices[0] ) and ( choices[1] == int(index_0123 / 6) % 6 ):
        flag += a123[index_0123]
 
for index_0123 in range(0x24):
    if ( 5 - ((index_0123+1) % 6) == choices[2] ) and ( choices[3] == int(1+ index_0123 / 6) % 6 ):
        flag += a123[index_0123]
 
for index_0123 in range(0x24):
    if ( 5 - ((index_0123+2) % 6) == choices[4] ) and ( choices[5] == int(2+ index_0123 / 6) % 6 ):
        flag += a123[index_0123]
'''
 
for index in range(0,len(choices),2):
    Got = False
    for index_0123 in range(0x24):
        if Got == False:
            if ( 5 - ((index_0123+index/2) % 6) == choices[index] ) and ( choices[index+1] == int(index/2+index_0123 / 6) % 6 ):
                Got = True
                flag += a123[index_0123]
 
assert flag == "GJ0V4LA4VKEVQZSVCNGJ00N"

看雪招聘平台创建简历并且简历完整度达到90%及以上可获得500看雪币~

收藏
点赞0
打赏
分享
最新回复 (0)
游客
登录 | 注册 方可回帖
返回