首页
社区
课程
招聘
[原创] KCTF 2023 第八题 wp - 98k
2023-9-17 15:44 7924

[原创] KCTF 2023 第八题 wp - 98k

2023-9-17 15:44
7924

代码量非常少,不过编译器优化得到逻辑很乱。整理下逻辑:

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
int check(char* input, int length) {
    char _flag[10][4];
    char key[5][4];
 
    for (int i = 0; i < length; i++) {
        int j = trans(input, i); // 0~9
        if (i & 1) assert(j == 0);
        else assert(j != 0);
        if (!check(key, j)) j = 9;
        for (int a = 0; a < 5; a++) {
            for (int b = 0; b < 4; b++) {
                key[a][b] ^= _flag[j][b];
            }
        }
        if (j == 9) {
            _flag[9][1] = ~_flag[9][1] & 0x7f;
        }
    }
    int a = 0;
    int b = 0;
    for (int i = 0; i < 5; i++) {
        a ^= key[i][0] ^ key[i][2];
        b ^= key[i][1] ^ key[i][3];
    }
    return (a & 0x1f) == 0 && (b & 0x1f) == 0;
}

所以问题大致是这样的,给定了 10 个初始比特值,还给了 10 组(实际上是 11 组)比特值,每次从这 10 组中有限制的选择一组出来,异或到初始比特值中,要求最后使 10 个比特值都变成 0 。

将初始比特值和可选择异或的比特值计算出来得到:

1
2
3
4
5
6
7
8
9
10
11
12
01000 10101
 
00000 00001
00000 00010
00000 00100
00000 01000
00000 10000
00001 00000
00010 00000
00100 00000
01000 00000
10000 00000

也就是每次可以改变 1 比特。限制条件为每隔一轮需要将最低比特改掉;除最低比特外,能修改某个比特位的条件就是它后续的比特位最高位为 1 ,后面的全是 0 (上面代码中 check 的检查)

根据这些限制条件就可以手动构造,再转成输入:

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
#!/usr/bin/env python3
 
def check(input):
    _flag = list(b'flag{BzcZDnfNIqmQCtkTGlwLyDYeiHIjxSXwkRKzpFPv}\x00\x00')
    key = list(b'Can you crack me?^olo^\x00\x00')
    v7 = _flag[42]
    for i in range(len(input)):
        c = input[i]
        v9 = (c + (0xFFFEC610 >> (i % 31))) % 10
        assert (i & 1) == int(v9 < 1)
        v26 = 0
        for j in range(4):
            v26 |= (key[16 + j] ^ key[12 + j] ^ key[8 + j] ^ key[4 + j] ^ key[j]) << (8 * j)
        # print(hex(v26))
        # print(((v26 >> 16) ^ v26) & 0x1f, ((v26 >> 24) ^ (v26 >> 8)) & 0x1f)
        while v9 >= 1:
            if v9 >= 6:
                if (v26 ^ (v26 >> 16)) & 0x1f != 0:
                    v9 = 9
                    break
                else:
                    v12 = (v26 >> 24) & 0xff
                    v13 = 13 - v9
                    v14 = (v26 >> 8) & 0xff
            else:
                v12 = (v26 >> 16) & 0xff
                v13 = 8 - v9
                v14 = v26 & 0xff
            # print(bin(v12)[2:].rjust(8, '0'), bin(v14)[2:].rjust(8, '0'), v13)
            if (((v14 << v13) + 0x80) & 0xff) != ((v12 << v13) & 0xff):
                v9 = 9
            break
        if v9: print(v9, end=' ')
        for i in range(5):
            for j in range(4):
                key[4 * i + j] ^= _flag[4 * v9 + 5 + j]
        if v9 > 8:
            v7 = ~v7 & 0x7f
            _flag[42] = v7 # 42 - 5 = 37, (9, 1)
    print()
    v26 = 0
    for j in range(4):
        v26 |= (key[16 + j] ^ key[12 + j] ^ key[8 + j] ^ key[4 + j] ^ key[j]) << (8 * j)
    print(hex(v26), bin(((v26 >> 16) ^ v26) & 0x1f)[2: ].rjust(5, '0'), bin(((v26 >> 24) ^ (v26 >> 8)) & 0x1f)[2: ].rjust(5, '0'))
    if ((v26 >> 16) ^ v26) & 0x1f != 0 or ((v26 >> 24) ^ (v26 >> 8)) & 0x1f != 0:
        return False
    else:
        return True
 
'''
flag = [0x3f] * 62
 
for i in range(len(flag)):
    if i & 1:
        flag[i] = (10 - (0xFFFEC610 >> (i % 31))) % 10
    else:
        flag[i] = (9 - (0xFFFEC610 >> (i % 31))) % 10
    while flag[i] < 0x30:
        flag[i] += 10
 
print(bytes(flag))
# 38968638916054237581658165816584705954700796332849074907490749
 
print(check(bytes(flag)))
'''
 
 
key = b'Can you crack me?^ol'
 
s = [0] * 2
for i in range(2):
    for j in range(0, len(key), 4):
        s[i] ^= (key[j + i] ^ key[j + i + 2]) & 0x1f
 
_flag = b'BzcZDnfNIqmQCtkTGlwLyDYeiHIjxSXwkRKzpFPvp9Pv'
# _flag = b'BzcZDnfNIqmQCtkTGlwLyDYeiHIjxSXwkRKzp9Pv'
t = []
for i in range(11):
    t.append([])
    for j in range(2):
        t[-1].append((_flag[4 * i + j] ^ _flag[4 * i + j + 2]) & 0x1f)
 
print(' '.join(bin(i)[2:].rjust(5, '0') for i in s[::-1]))
print()
for _t in t:
    print(' '.join(bin(i)[2:].rjust(5, '0') for i in _t[::-1]))
 
flag = []
values = [
       # 01000 10101
    1, # 01000 10110
    2, # 01000 10011
    1, # 01000 10000
    5, # 01001 10001
    1, # 01001 10010
    2, # 01001 10111
    1, # 01001 10100
    3, # 01001 11101
    1, # 01001 11110
    2, # 01001 11011
    1, # 01001 11000
    4, # 01001 01001
    1, # 01001 01010
    2, # 01001 01111
    1, # 01001 01100
    3, # 01001 00101
    1, # 01001 00110
    2, # 01001 00011
    1, # 01001 00000
    6, # 01011 00001
    1, # 01011 00010
    2, # 01011 00111
    1, # 01011 00100
    3, # 01011 01101
    1, # 01011 01110
    2, # 01011 01011
    1, # 01011 01000
    4, # 01011 11001
    1, # 01011 11010
    2, # 01011 11111
    1, # 01011 11100
    3, # 01011 10101
    1, # 01011 10110
    2, # 01011 10011
    1, # 01011 10000
    5, # 01010 10001
    1, 2, 1, 3, 1, 2, 1, 4, 1, 2, 1, 3, 1, 2, 1, 7, # 01110 00001
    1, 2, 1, 3, 1, 2, 1, 4, 1, 2, 1, 3, 1, 2, 1, 5, # 01111 10001
    1, 2, 1, 3, 1, 2, 1, 4, 1, 2, 1, 3, 1, 2, 1, 6, # 01101 00001
    1, 2, 1, 3, 1, 2, 1, 4, 1, 2, 1, 3, 1, 2, 1, 5, # 01100 10001
    1, # 01100 10010
    2, # 01100 10111
    1, # 01100 10100
    3, # 01100 11101
    1, # 01100 11110
    2, # 01100 11011
    1, # 01100 11000
    4, # 01100 01001
    1, 2, 1, 3, 1, 2, 1, # 01100 00000
    8# 00100 00001
    1, 2, 1, 3, 1, 2, 1, 4, 1, 2, 1, 3, 1, 2, 1, 5, # 00101 10001
    1, 2, 1, 3, 1, 2, 1, 4, 1, 2, 1, 3, 1, 2, 1, 6, # 00111 00001
    1, 2, 1, 3, 1, 2, 1, 4, 1, 2, 1, 3, 1, 2, 1, 5, # 00110 10001
    1, 2, 1, 3, 1, 2, 1, 4, 1, 2, 1, 3, 1, 2, 1, 7, # 00010 00001
    1, 2, 1, 3, 1, 2, 1, 4, 1, 2, 1, 3, 1, 2, 1, 5, # 00011 10001
    1, 2, 1, 3, 1, 2, 1, 4, 1, 2, 1, 3, 1, 2, 1, 6, # 00001 00001
    1, 2, 1, 3, 1, 2, 1, 4, 1, 2, 1, 3, 1, 2, 1, 5, # 00000 10001
    1, 2, 1, 3, 1, 2, 1, 4, 1, 2, 1, 3, 1, 2, 1,
]
 
values += [9, 9, 9, 9] * 0
 
for i in range(2 * len(values)):
    if i & 1:
        flag.append((0 - (0xFFFEC610 >> (i % 31))) % 10)
    else:
        flag.append((values[i // 2] - (0xFFFEC610 >> (i % 31))) % 10)
    while flag[-1] < 0x30:
        flag[-1] += 10
 
print(bytes(flag))
print(check(bytes(flag)))
 
 
# 582606981190746395118531851185249089744027265368693769576937697816165851808443150195011501950410798490871663488927792799277958360668112074539521851185318514909974002766535869476937695769681626582180144305010501950115040079949037162348792789277927995826067811907483951185218511853490897410272653986937694769376988161658318084433501950105019504207984904716634829277927892779584606681100745395418511852185149009740027365358697769376947696816365821809443050125019501050400790490371673487927
# 58260698119074639511853185118524908974402726536869376957693769781616585180844315019501150195041079849087166348892779279927795836066811207453952185118531851490997400276653586947693769576968162658218014430501050195011504007994903716234879278927792799582606781190748395118521851185349089741027265398693769476937698816165831808443350195010501950420798490471663482927792789277958460668110074539541851185218514900974002736535869776937694769681636582180944305012501950105040079049037167348792749074907
# 5826069811907463951185318511852490897440272653686937695769376978161658518084431501950115019504107984908716634889277927992779583606681120745395218511853185149099740027665358694769376957696816265821801443050105019501150400799490371623487927892779279958260678119074839511852185118534908974102726539869376947693769881616583180844335019501050195042079849047166348292779278927795846066811007453954185118521851490097400273653586977693769476968163658218094430501250195010504007904903716734879274907490749389686
# 582606981190746395118531851185249089744027265368693769576937697816165851808443150195011501950410798490871663488927792799277958360668112074539521851185318514909974002766535869476937695769681626582180144305010501950115040079949037162348792789277927995826067811907483951185218511853490897410272653986937694769376988161658318084433501950105019504207984904716634829277927892779584606681100745395418511852185149009740027365358697769376947696816365821809443050125019501050400790490371673487927490749074938968638916054
# 58260698119074639511853185118524908974402726536869376957693769781616585180844315019501150195041079849087166348892779279927795836066811207453952185118531851490997400276653586947693769576968162658218014430501050195011504007994903716234879278927792799582606781190748395118521851185349089741027265398693769476937698816165831808443350195010501950420798490471663482927792789277958460668110074539541851185218514900974002736535869776937694769681636582180944305012501950105040079049037167348792749074907493896863891605423758165
# 5826069811907463951185318511852490897440272653686937695769376978161658518084431501950115019504107984908716634889277927992779583606681120745395218511853185149099740027665358694769376957696816265821801443050105019501150400799490371623487927892779279958260678119074839511852185118534908974102726539869376947693769881616583180844335019501050195042079849047166348292779278927795846066811007453954185118521851490097400273653586977693769476968163658218094430501250195010504007904903716734879274907490749389686389160542375816581658165

正常来说输入转换得到的数字应该不能为 9 ,但是程序中并没有对 9 做错误的返回,所以可以在输入的任意 4 个连续的偶数位置插 9 (奇数位补0),得到的结果不变,就能构造出多解。上面代码中给出了在末尾补 9 时得到的几组多解。


[CTF入门培训]顶尖高校博士及硕士团队亲授《30小时教你玩转CTF》,视频+靶场+题目!助力进入CTF世界

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