首页
论坛
课程
招聘
[原创]KCTF2022春季赛第2题 末日邀请
2022-5-12 16:52 5342

[原创]KCTF2022春季赛第2题 末日邀请

2022-5-12 16:52
5342

with Avalon

 

主函数第一部分:

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
printf(
  "%s\n 而你,作为一个操控韩立的人,千万不要让韩立 GAME OVER 了.\n现在,输入你的操作ID吧:",
  asc_7E55C0);
scanf("%s", flag);
printf("\n现在,你就是韩立,韩立就是你,如遇绝境,吼:男人至死是少年!");
flag[41] = 0;                                 // allocation == 42
flag_len = strlen(flag);
v5 = 0;
v38 = flag_len;
v6 = flag_len;
last_rnd_v10 = 0;
if ( flag_len )
{
  v7 = flag;
  do
  {
    v5 ^= *v7;
    --v6;                                     // length decreaser
    ++v7;                                     // input increaser
    v8 = 8;
    do
    {
      v9 = 2 * v5;
      v10 = v9 ^ 7;                           // xor(v9, 0b111) seems not executable?
      if ( v9 >= 0 )
        v10 = v9;
      v5 = v10;
      --v8;
    }
    while ( v8 );                             // 8 rounds
  }
  while ( v6 );
  flag_len = v38;
  last_rnd_v10 = v10;
}
assign_magic_arr();
v11 = 0xFFFFFFFF;
for ( i = 0; i < flag_len; ++i )
  v11 = magic_arr[(unsigned __int8)(v11 ^ flag[i])] ^ (v11 >> 8);
res = ~v11;

可以发现 flag 最长为41
下一段是计算 v5last_rnd_v10 并赋值 magic_arr 为一个固定值
下一部分:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
convert_base(flag, flag_len);
v13 = last_rnd_v10;
v36 = 1;
v35 = last_rnd_v10 + 1;
v14 = v35;
do
{
  v15 = v13;
  for ( j = 1; j < 200; ++j )
  {
    if ( (v15 & 1) != 0 )                     // odd
      v15 = 3 * v15 + 1;
    else                                      // even
      v15 >>= 1;
    v33[j] = v15;
  }
  ++v13;
}
while ( v13 < v14 );
v17 = v33[198] | v33[197] | v33[196];
v18 = v38;
if ( v17 != (flag[2] ^ flag[1] ^ flag[0]) )   // 前三位可爆

首先是进行一个数字和字符的无差别转换,然后是一个冰雹猜想,接着验证前三位
接下来验证中间四个字符,显然是 KCTF
接着是一段拼凑成数字并排序的验证:

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
v21 = 0;
  v38 = 0;
  if ( v19 > 0 )
  {
    v22 = 1;
    do
    {
      v23 = flag[v22 + 6] + 10 * v37;
      v24 = v23 - 0x37373737;                   // '7777'
      if ( v23 <= 0x4B435445 )                  // 'KCTE'
        v24 = v23;
      v37 = v24;
      if ( v24 % v36 )
        goto LABEL_50;
      v21 = v38 + 1;
      v22 = v36 + 1;
      v38 = v21;
      ++v36;
    }
    while ( v21 < v19 );
  }
 
......
 
  v25 = v19 - 1;
  if ( v19 - 1 > 0 )                            // bubble sort
  {
    v26 = v19 - 1;
    do
    {
      v27 = 0;
      if ( v25 > 0 )
      {
        do
        {
          v28 = flag[v27 + 7];
          v29 = flag[v27 + 8];
          if ( v28 > v29 )
          {
            flag[v27 + 7] = v29;
            flag[v27 + 8] = v28;
          }
          ++v27;
        }
        while ( v27 < v25 );
        no_0 = 0;
      }
      --v25;
      --v26;
    }
    while ( v26 );
  }
  convert_base(charset, v19);
  v30 = 0;
  if ( v19 > 0 )
  {
    while ( charset[v30] == flag[v30 + 7] )     // v19 = 9
    {
      if ( ++v30 >= v19 )
        goto LABEL_41;
    }
    goto LABEL_49;
  }

首先通过排序部分,猜测出关键数字 v19 == 9,然后逆向上面的,发现是将 flag 的从低到高位拼凑成一个 9 位的十进制数并满足要求,直接 z3 求解:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
from z3 import *
a = [Int('a_%d' % i) for i in range(9)]
print(a)
s = Solver()
for i in range(9):
    s.add(a[i] >= 1, a[i] <= 9)
    for j in range(i + 1, 9):
        s.add(a[i] != a[j])
s.add(a[0] % 1 == 0)
s.add((a[0] * 10 + a[1]) % 2 == 0)
s.add((a[0] * 100 + a[1] * 10 + a[2]) % 3 == 0)
s.add((a[0] * 1000 + a[1] * 100 + a[2] * 10 + a[3]) % 4 == 0)
s.add((a[0] * 10000 + a[1] * 1000 + a[2] * 100 + a[3] * 10 + a[4]) % 5 == 0)
s.add((a[0] * 100000 + a[1] * 10000 + a[2] * 1000 + a[3] * 100 + a[4] * 10 + a[5]) % 6 == 0)
s.add((a[0] * 1000000 + a[1] * 100000 + a[2] * 10000 + a[3] * 1000 + a[4] * 100 + a[5] * 10 + a[6]) % 7 == 0)
s.add((a[0] * 10000000 + a[1] * 1000000 + a[2] * 100000 + a[3] * 10000 + a[4] * 1000 + a[5] * 100 + a[6] * 10 + a[7]) % 8 == 0)
s.add((a[0] * 100000000 + a[1] * 10000000 + a[2] * 1000000 + a[3] * 100000 + a[4]*10000 + a[5] * 1000 + a[6] * 100 + a[7] * 10 + a[8]) % 9 == 0)
print(s.check())
m = s.model()
for d in m.decls():
    print(f'{d.name()} = {m[d]}') # KCTF381654729

拿到之后发现 v20 == 0 于是想构造一个 16 位的输入,那就直接爆前三位:

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
#include <stdio.h>
#include <stdint.h>
 
uint32_t magic_arr[] = {0x00000000, 0x09073096, 0x120E612C, 0x1B0951BA, 0xFF6DC419, 0xF66AF48F, 0xED63A535, 0xE46495A3,
                        0xFEDB8832, 0xF7DCB8A4, 0xECD5E91E, 0xE5D2D988, 0x01B64C2B, 0x08B17CBD, 0x13B82D07, 0x1ABF1D91,
                        0xFDB71064, 0xF4B020F2, 0xEFB97148, 0xE6BE41DE, 0x02DAD47D, 0x0BDDE4EB, 0x10D4B551, 0x19D385C7,
                        0x036C9856, 0x0A6BA8C0, 0x1162F97A, 0x1865C9EC, 0xFC015C4F, 0xF5066CD9, 0xEE0F3D63, 0xE7080DF5,
                        0xFB6E20C8, 0xF269105E, 0xE96041E4, 0xE0677172, 0x0403E4D1, 0x0D04D447, 0x160D85FD, 0x1F0AB56B,
                        0x05B5A8FA, 0x0CB2986C, 0x17BBC9D6, 0x1EBCF940, 0xFAD86CE3, 0xF3DF5C75, 0xE8D60DCF, 0xE1D13D59,
                        0x06D930AC, 0x0FDE003A, 0x14D75180, 0x1DD06116, 0xF9B4F4B5, 0xF0B3C423, 0xEBBA9599, 0xE2BDA50F,
                        0xF802B89E, 0xF1058808, 0xEA0CD9B2, 0xE30BE924, 0x076F7C87, 0x0E684C11, 0x15611DAB, 0x1C662D3D,
                        0xF6DC4190, 0xFFDB7106, 0xE4D220BC, 0xEDD5102A, 0x09B18589, 0x00B6B51F, 0x1BBFE4A5, 0x12B8D433,
                        0x0807C9A2, 0x0100F934, 0x1A09A88E, 0x130E9818, 0xF76A0DBB, 0xFE6D3D2D, 0xE5646C97, 0xEC635C01,
                        0x0B6B51F4, 0x026C6162, 0x196530D8, 0x1062004E, 0xF40695ED, 0xFD01A57B, 0xE608F4C1, 0xEF0FC457,
                        0xF5B0D9C6, 0xFCB7E950, 0xE7BEB8EA, 0xEEB9887C, 0x0ADD1DDF, 0x03DA2D49, 0x18D37CF3, 0x11D44C65,
                        0x0DB26158, 0x04B551CE, 0x1FBC0074, 0x16BB30E2, 0xF2DFA541, 0xFBD895D7, 0xE0D1C46D, 0xE9D6F4FB,
                        0xF369E96A, 0xFA6ED9FC, 0xE1678846, 0xE860B8D0, 0x0C042D73, 0x05031DE5, 0x1E0A4C5F, 0x170D7CC9,
                        0xF005713C, 0xF90241AA, 0xE20B1010, 0xEB0C2086, 0x0F68B525, 0x066F85B3, 0x1D66D409, 0x1461E49F,
                        0x0EDEF90E, 0x07D9C998, 0x1CD09822, 0x15D7A8B4, 0xF1B33D17, 0xF8B40D81, 0xE3BD5C3B, 0xEABA6CAD,
                        0xEDB88320, 0xE4BFB3B6, 0xFFB6E20C, 0xF6B1D29A, 0x12D54739, 0x1BD277AF, 0x00DB2615, 0x09DC1683,
                        0x13630B12, 0x1A643B84, 0x016D6A3E, 0x086A5AA8, 0xEC0ECF0B, 0xE509FF9D, 0xFE00AE27, 0xF7079EB1,
                        0x100F9344, 0x1908A3D2, 0x0201F268, 0x0B06C2FE, 0xEF62575D, 0xE66567CB, 0xFD6C3671, 0xF46B06E7,
                        0xEED41B76, 0xE7D32BE0, 0xFCDA7A5A, 0xF5DD4ACC, 0x11B9DF6F, 0x18BEEFF9, 0x03B7BE43, 0x0AB08ED5,
                        0x16D6A3E8, 0x1FD1937E, 0x04D8C2C4, 0x0DDFF252, 0xE9BB67F1, 0xE0BC5767, 0xFBB506DD, 0xF2B2364B,
                        0xE80D2BDA, 0xE10A1B4C, 0xFA034AF6, 0xF3047A60, 0x1760EFC3, 0x1E67DF55, 0x056E8EEF, 0x0C69BE79,
                        0xEB61B38C, 0xE266831A, 0xF96FD2A0, 0xF068E236, 0x140C7795, 0x1D0B4703, 0x060216B9, 0x0F05262F,
                        0x15BA3BBE, 0x1CBD0B28, 0x07B45A92, 0x0EB36A04, 0xEAD7FFA7, 0xE3D0CF31, 0xF8D99E8B, 0xF1DEAE1D,
                        0x1B64C2B0, 0x1263F226, 0x096AA39C, 0x006D930A, 0xE40906A9, 0xED0E363F, 0xF6076785, 0xFF005713,
                        0xE5BF4A82, 0xECB87A14, 0xF7B12BAE, 0xFEB61B38, 0x1AD28E9B, 0x13D5BE0D, 0x08DCEFB7, 0x01DBDF21,
                        0xE6D3D2D4, 0xEFD4E242, 0xF4DDB3F8, 0xFDDA836E, 0x19BE16CD, 0x10B9265B, 0x0BB077E1, 0x02B74777,
                        0x18085AE6, 0x110F6A70, 0x0A063BCA, 0x03010B5C, 0xE7659EFF, 0xEE62AE69, 0xF56BFFD3, 0xFC6CCF45,
                        0xE00AE278, 0xE90DD2EE, 0xF2048354, 0xFB03B3C2, 0x1F672661, 0x166016F7, 0x0D69474D, 0x046E77DB,
                        0x1ED16A4A, 0x17D65ADC, 0x0CDF0B66, 0x05D83BF0, 0xE1BCAE53, 0xE8BB9EC5, 0xF3B2CF7F, 0xFAB5FFE9,
                        0x1DBDF21C, 0x14BAC28A, 0x0FB39330, 0x06B4A3A6, 0xE2D03605, 0xEBD70693, 0xF0DE5729, 0xF9D967BF,
                        0xE3667A2E, 0xEA614AB8, 0xF1681B02, 0xF86F2B94, 0x1C0BBE37, 0x150C8EA1, 0x0E05DF1B, 0x0702EF8D};
 
char cstr[] = "...KCTF381654729";
 
int main() {
    for (int i = 0x20; i < 0x7e; i++) {
        for (int j = 0x20; j < 0x7e; j++) {
            for (int k = 0x20; k < 0x7e; k++) {
                cstr[0] = i;
                cstr[1] = j;
                cstr[2] = k;
                int32_t v11 = -1;
                for (int idx = 0; idx < 16; idx++) {
                    v11 = magic_arr[(uint8_t)(v11 ^ cstr[idx])] ^ (v11 >> 8);
                }
                if ((~v11) == 0xF52E0765) {  
                    printf("%c %c %c\n", i, j, k);
                }
            }
        }
    }
}

拿到一个满足条件的 flag == 421KCTF381654729


【公告】看雪招聘大学实习生!看雪20年安全圈的口碑,助你快速成长!

最后于 2022-5-15 13:48 被trackL编辑 ,原因:
收藏
点赞0
打赏
分享
最新回复 (0)
游客
登录 | 注册 方可回帖
返回