1
2
3
4
5
6
7
|
/
/
称为flag[
10
],看做
10
个
int
数
00402100
66
6C
61
67
7B
42
7A
63
5A
44
6E
66
4E
49
71
6D
flag{BzcZDnfNIqm
00402110
51
43
74
6B
54
47
6C
77
4C
79
44
59
65
69
48
49
QCtkTGlwLyDYeiHI
00402120
6A
78
53
58
77
6B
52
4B
7A
70
46
50
76
7D
00
00
jxSXwkRKzpFPv}..
/
/
称为check[
5
],取
20
字节,看做
5
个
int
00402130
43
61
6E
20
79
6F
75
20
63
72
61
63
6B
20
6D
65
Can you crack me
00402140
3F
5E
6F
6C
6F
5E
00
00
?^olo^.
|
1
2
3
4
5
|
if
( input_len <
=
0
|| (input_len_1
=
input_len
-
1
,
input
[input_len
-
1
] !
=
'\n'
) )
{
v3
=
1
;
/
/
错误
v27
=
1
;
}
|
1
2
3
4
5
|
input_num
=
input
[v8];
if
( (unsigned
int
)(input_num
-
'0'
) <
=
9
)
/
/
只能输入数字
break
;
v3
=
1
;
/
/
这个数不能等于
1
v27
=
1
;
/
/
这个数也不能等于
1
|
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
|
/
/
根据下标和对应的数字,转换出一个
0
-
9
的数
v12
=
(input_num
+
(
0xFFFEC610
>> input_id
%
31
))
%
0xA
;
/
/
奇数位,v12
=
=
0
;偶数位,v12!
=
0
if
( (input_id &
1
) !
=
v12 <
1
)
v27
=
1
;
/
/
将check数组中
5
个
int
做xor,得到
4
字节
=
v28
v28
=
v38 ^ HIDWORD(v37) ^ v37 ^ HIDWORD(v36) ^ v36;
if
( v25 )
/
/
如果是
input
最后一位,就进行校验
{
/
/
v28的 (((bit0 ^ bit2) &
0x1F
)
=
=
0
)
/
/
v28的 (((bit1 ^ bit3) &
0x1F
)
=
=
0
)
if
( ((unsigned __int8)v28 ^ (unsigned __int8)(BYTE2(v38) ^ BYTE6(v37) ^ BYTE2(v37) ^ BYTE6(v36) ^ BYTE2(v36))) &
0x1F
/
/
也就是说这个条件,必须成立
|| (HIBYTE(v28) ^ BYTE1(v28)) &
0x1F
)
{
v13
=
-
1
;
/
/
v13等于
-
1
是成功状态
}
goto LABEL_27;
}
/
/
根据v12取出flag中的
4
字节,分别跟check的
5
个数xor
v17
=
v31[v12];
LODWORD(v36)
=
v17 ^ v36;
/
/
那
20
字节,跟选定的数字xor
HIDWORD(v36) ^
=
v17;
LODWORD(v37)
=
v17 ^ v37;
HIDWORD(v37) ^
=
v17;
/
/
xor后的数据要满足
if
( v12 >
=
6
)
{
if
( ((unsigned __int8)v28 ^ BYTE2(v28)) &
0x1F
)
{
LABEL_26:
v13
=
9
;
/
/
将当前v12重置为
9
goto LABEL_27;
}
v15
=
13
-
v12;
}
else
{
v15
=
8
-
v12;
v16
=
v28;
/
/
=
0
}
if
( (v16 << v15)
+
-
128
=
=
v14 << v15 )
/
/
需要成立
goto LABEL_27;
|
然后整理下大概逻辑:
check数组有初始状态
flag数组是始终不变的
根据input的每一位,计算出一个下标id,选取flag[id]
将check数组5个数,分别跟flag[id] xor,最终会进行一个校验
因为xor具有偶数次消除的性质,所以先编写脚本,跑出最终结果需要flag中的[0] [2] [4] [8]
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
|
/
/
标记
10
层,每层选取的元素是谁
unsigned
int
id08[
10
]
=
{
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
};
/
/
判断数组是否合规
1
=
合规
0
=
错误
int
judge08(unsigned
int
*
flag, unsigned
int
*
check)
{
unsigned
int
final[
5
]
=
{
0
};
for
(
int
i
=
0
; i <
5
; i
+
+
)
final[i]
=
check[i];
for
(
int
i
=
0
; i <
10
; i
+
+
)
/
/
flag用
10
次
{
if
(id08[i]
=
=
-
1
)
/
/
不跟这个数参与xor
continue
;
for
(
int
j
=
0
; j <
5
; j
+
+
)
/
/
check中是
5
个
4
位数
{
final[j] ^
=
flag[i];
}
}
final[
0
]
=
final[
0
] ^ final[
1
] ^ final[
2
] ^ final[
3
] ^ final[
4
];
int
bit0
=
(final[
0
] &
0xFF000000
) >>
24
;
int
bit1
=
(final[
0
] &
0xFF0000
) >>
16
;
int
bit2
=
(final[
0
] &
0xFF00
) >>
8
;
int
bit3
=
final[
0
] &
0xFF
;
printf(
"%x\n"
, final[
0
]);
int
e
=
bit0 ^ bit2;
int
f
=
bit1 ^ bit3;
printf(
"%x %x\n"
, e, f);
if
(((e &
0x1F
)
=
=
0
) && ((f &
0x1F
)
=
=
0
))
{
printf(
"%x %x\n"
, (e &
0x1F
), (f &
0x1F
));
return
1
;
}
return
0
;
}
/
/
depth表示当前层级,一共遍历
39
层
void search08(unsigned
int
*
flag, unsigned
int
*
check,
int
depth)
{
if
(depth
=
=
10
)
{
/
/
printArr(id08,
10
);
if
(judge08(flag, check))
{
printf(
"heihei\n"
);
printArr(id08,
10
);
exit(
0
);
}
return
;
}
for
(
int
i
=
0
; i <
2
; i
+
+
)
{
if
(i
=
=
0
)
id08[depth]
=
1
;
else
id08[depth]
=
-
1
;
search08(flag, check, depth
+
1
);
}
return
;
}
|
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
|
int
judge08_2(unsigned
int
*
flag, unsigned
int
*
check,
int
index)
{
for
(
int
j
=
0
; j <
5
; j
+
+
)
/
/
check中是
5
个
4
位数
{
check[j] ^
=
flag[index];
}
int
num
=
check[
0
] ^ check[
1
] ^ check[
2
] ^ check[
3
] ^ check[
4
];
int
bit0
=
(num &
0xFF000000
) >>
24
;
int
bit1
=
(num &
0xFF0000
) >>
16
;
int
bit2
=
(num &
0xFF00
) >>
8
;
int
bit3
=
num &
0xFF
;
/
/
printf(
"%x\n"
, num);
int
e
=
bit0 ^ bit2;
int
f
=
bit1 ^ bit3;
/
/
printf(
"%x %x\n"
, e, f);
if
(((e &
0x1F
)
=
=
0
) && ((f &
0x1F
)
=
=
0
))
{
/
/
printf(
"%x %x\n"
, (e &
0x1F
), (f &
0x1F
));
return
1
;
}
return
0
;
}
void ctf08()
{
unsigned
int
check[]
=
{
0x43616e20
,
0x796f7520
,
0x63726163
,
0x6b206d65
,
0x3f5e6f6c
};
unsigned
int
flag[]
=
{
0x427a635a
,
0x446e664e
,
0x49716d51
,
0x43746b54
,
0x476c774c
,
0x79445965
,
0x6948496a
,
0x78535877
,
0x6b524b7a
,
0x70465076
};
for
(
int
i
=
0
; i <
1000
; i
+
+
)
{
int
j
=
0
;
for
(; j <
10
; j
+
+
)
/
/
从
0
-
9
遍历
{
int
v12
=
((
0xFFFEC610
>> i
%
31
)
+
(
0x30
+
j))
%
0xA
;
if
((i &
1
) !
=
v12 <
1
)
/
/
过滤掉不符合的数字
continue
;
if
(v12
=
=
0
)
/
/
i是奇数位
{
for
(
int
k
=
0
; k <
5
; k
+
+
)
/
/
check中是
5
个
4
位数
{
check[k] ^
=
flag[v12];
/
/
其实也就是
0
位
}
printf(
"id=%d num=%d v12=%d\n"
, i, j, v12);
break
;
}
int
num
=
check[
0
] ^ check[
1
] ^ check[
2
] ^ check[
3
] ^ check[
4
];
/
/
75
73
1D
00
=
0x001d7375
int
al
=
(num &
0xFF00
) >>
8
;
/
/
73
int
dl
=
(num &
0xFF000000
) >>
24
;
int
v15;
if
(v12 >
=
6
)
{
int
e
=
al ^ dl;
if
((e &
0x1F
) !
=
0
)
continue
;
v15
=
13
-
v12;
al
=
num &
0xFF
;
dl
=
(num &
0xFF0000
) >>
16
;
}
else
v15
=
8
-
v12;
int
a
=
(al << v15) &
0xff
;
int
b
=
(dl << v15) &
0xff
;
if
(a
=
=
((
128
+
b) &
0xff
))
{
printf(
"id=%d num=%d v12=%d\n"
, i, j, v12);
if
(judge08_2(flag, check, v12))
{
printf(
"hahaha"
);
exit(
0
);
}
break
;
}
}
if
(j
=
=
10
)
/
/
没找到数字的话
{
for
(
int
k
=
0
; k <
5
; k
+
+
)
/
/
check中是
5
个
4
位数
{
check[j] ^
=
flag[
9
];
/
/
其实也就是
0
位
}
printf(
"id=%d [9]\n"
, i);
}
}
/
/
search08(flag, check,
0
);
}
|
更多【KCTF2023 第八题AI核心地带】相关视频教程:www.yxfzedu.com