1
2
|
这是一道简单题,文件大小才
8K
。所以ida打开后主流程基本一览无余。在看完ida的数据流程后,基本可以肯定这个程序就是对输入的每个字节进行顺序判断,所以可以对每个字节进行遍历求取以判断当前字节是否正确。
将主函数稍微修改一下,让判断失败时返回
0
,判断成功时输出ans,需要进行下一位比较时返回
2
。得到如下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
|
int
Check(char
*
Input
)
{
char FakeFlag[
48
];
strcpy_s(FakeFlag,
48
,
"flag{BzcZDnfNIqmQCtkTGlwLyDYeiHIjxSXwkRKzpFPv}"
);
_BYTE Data[
27
];
strcpy_s((char
*
)Data,
27
,
"Can you crack me?^olo^"
);
int
StrLength
=
strlen(
Input
);
int
bFail1
=
0
, bFail2
=
0
, MayFail
=
0
;
int
v9, v20
=
0
;
int
Last
=
0
;
int
v11;
int
v26;
DWORD Index
=
0
;
char v7
=
FakeFlag[
42
];
bool
v8
=
StrLength >
0
;
do
{
if
(v8)
{
int
v19
=
Input
[Index];
if
(v19
-
(unsigned
int
)
'0'
>
9
)
/
/
大于‘
9
’失败?
{
return
0
;
bFail1
=
1
;
MayFail
=
1
;
goto LABEL_32;
}
v9
=
(v19
+
(
0xFFFEC610
>> (Index
%
0x1F
)))
%
0xA
;
if
((Index &
1
) !
=
v9 <
1
)
{
return
0
;
MayFail
=
1
;
}
}
else
{
v9
=
v20;
Last
=
1
;
}
v11
=
v9;
v26
=
*
(_DWORD
*
)&Data[
16
] ^
*
(_DWORD
*
)&Data[
12
] ^
*
(_DWORD
*
)&Data[
8
] ^
*
(_DWORD
*
)&Data[
4
] ^
*
(_DWORD
*
)Data;
if
(Last ||
1
)
{
if
((((unsigned __int8)v26 ^ (unsigned __int8)(Data[
18
] ^ Data[
14
] ^ Data[
10
] ^ Data[
6
] ^ Data[
2
])) &
0x1F
) !
=
0
|| ((HIBYTE(v26) ^ BYTE1(v26)) &
0x1F
) !
=
0
)
{
/
/
v11
=
-
1
;
/
/
if
(Last)
/
/
return
0
;
}
else
{
printf(
"ans: %s"
,
Input
);
getchar();
return
1
;
}
/
/
goto LABEL_26;
}
if
(v9 >
=
1
)
{
BYTE v12, v13, v14;
v12
=
BYTE2(v26);
if
(v9 >
=
6
)
{
if
((((unsigned __int8)v26 ^ BYTE2(v26)) &
0x1F
) !
=
0
)
{
LABEL_25:
return
0
;
v11
=
9
;
goto LABEL_26;
}
v12
=
HIBYTE(v26);
v13
=
13
-
v9;
v14
=
BYTE1(v26);
}
else
{
v13
=
8
-
v9;
v14
=
v26;
}
if
((((v14 << v13)
+
0x80
)&
0xff
)
=
=
((v12 << v13)&
0xff
))
{
if
(Index
=
=
StrLength
-
1
)
return
2
;
goto LABEL_26;
}
goto LABEL_25;
}
LABEL_26:
v20
=
v11;
if
(Last)
{
bool
v15
=
v11 <
0
;
bFail1
=
MayFail;
if
(v15)
bFail2
=
1
;
}
else
{
int
v16
=
*
(_DWORD
*
)&FakeFlag[
4
*
v11
+
5
];
*
(_DWORD
*
)Data ^
=
v16;
*
(_DWORD
*
)&Data[
4
] ^
=
v16;
*
(_DWORD
*
)&Data[
8
] ^
=
v16;
*
(_DWORD
*
)&Data[
12
] ^
=
v16;
v8
=
v11 <
=
8
;
bFail1
=
MayFail;
*
(_DWORD
*
)&Data[
16
] ^
=
v16;
if
(!v8 && (v7 &
0x10000000
)
=
=
0
)
{
v7
=
~v7 &
0x7F
;
FakeFlag[
42
]
=
v7;
}
}
LABEL_32:
v8
=
(
int
)
+
+
Index < StrLength;
}
while
((
int
)Index <
=
StrLength);
if
(bFail1 || bFail2)
return
0
;
return
2
;
}
|
1
|
继续构造主函数对每一字节进行遍历,一开始
Input
字节数没给够,导致遍历不出来,后面看到题目给了
1000
的缓存,修改后才得到答案。主程序如下:
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
int
main()
{
char
Input
[
1024
]
=
"0"
;
memset(&
Input
[
0
],
0
,
1000
);
int
Cur
=
0
;
while
(Cur <
1000
)
{
for
(
int
Index
=
0
; Index <
10
; Index
+
+
)
{
Input
[Cur]
=
0x30
+
Index;
int
res
=
Check(
Input
);
if
(res
=
=
2
)
{
Cur
+
+
;
break
;
}
}
}
}
|
1
2
|
因为题目限制了输入必须是字母
0
-
9
,所以这个答案基本上是秒出。得到flag为:
582606981190746395118531851185249089744027265368693769576937697816165851808443150195011501950410798490871663488927792799277958360668112074539521851185318514909974002766535869476937695769681626582180144305010501950115040079949037162348792789277927995826067811907483951185218511853490897410272653986937694769376988161658318084433501950105019504207984904716634829277927892779584606681100745395418511852185149009740027365358697769376947696816365821809443050125019501050400790490371673487927
。
ps:注意到
if
( !v8 && (v7 &
0x10000000
)
=
=
0
)这一段,有可能出题人的意思是让v11大于
8
时修改FakeFlag[
42
]的值,从而限制错误的输入,但是由于可以多次修改FakeFlag[
42
],导致该值不可预期,从而可以产生其他预期外的解。
|
更多【第八题 AI核心地带】相关视频教程:www.yxfzedu.com