-
-
[原创]第二题 南冥神功
-
发表于: 2021-5-12 15:38 4920
-
IDA分析,结构很清晰。
for循环两次,正确的情况下,输入的一个字符将会把byte_4B7080两个不同地方的0变为1。
让我有许多疑惑的就是for循环中的switch结构,一开始我猜测byte_4B7080是一个迷宫数据,然后我被v9和v21给迷惑住了,以为迷宫是v9*v21的一个长度,但这显然与最后的判定循环次数为90次不符,然后又猜测是不是v9*10,这样确实是符合了数据长度,接下来我以9*10的形式dump下byte_4B7080数据:
这个迷宫数据很特别,要怎么走取决于switch结构的运算,在动态调试的时候也不是很明白switch中控制的方向如何,它不是常见的上、下、左、右四种方向,尤其是switch中的位运算,给我一种乱糟糟的感觉。我看不懂方向,所以没法手动去画出路线,这是一个拖我节奏的地方了。也正是看不懂方向,甚至让我怀疑这不是一道迷宫题,而只是另一种算法题——要求在位置不重复的情况下,通过switch结构,将byte_4B7080序列中的0全变为1。
然后,我将伪代码翻译成python代码,并在某些地方做了一些剪枝,试图利用递归去解决这个问题。我通过计数byte_4B7080中的0确定了输入的长度为23。下面是我的解题脚本:
很遗憾,我算法太弱了,这道题我卡在了算法和逆向走迷宫的方向上,超时了2个半小时才解出来,比赛中没能做出来。T口T.
int
__cdecl main(
int
argc, const char
*
*
argv, const char
*
*
envp)
{
...
printf_0((
int
)&dword_4B8860,
"Input your code: "
);
scanf((
int
)&dword_4B8680,
input
);
/
/
接受用户输入
if
( strlen(
input
) <
=
0x30
)
/
/
长度不能超过
0x30
{
v3
=
input
[
0
];
if
(
input
[
0
] )
{
v4
=
0
;
v21
=
0
;
v22
=
0
;
v24
=
dword_4B7020;
/
/
0x24
v23
=
byte_4B7040[
0
];
LABEL_4:
if
( v24 >
0
)
{
v5
=
0
;
if
( v23
=
=
v3 )
{
LABEL_11:
/
/
这是一个循环结构的循环首,循环次数为
input
的长度
v7
=
(v4
+
v5
/
6
)
%
6
;
v8
=
v5
+
v4;
v9
=
v22;
v20
=
v7;
v10
=
5
-
v8
%
6
;
for
( i
=
0
; ; i
=
1
)
/
/
实际循环两次
{
switch ( v10 )
{
case
1
:
+
+
v9;
break
;
case
2
:
v17
=
(v21
+
+
&
1
)
=
=
0
;
v9
+
=
v17;
break
;
case
3
:
v12
=
(v21
+
+
&
1
) !
=
0
;
v9
-
=
v12;
break
;
case
4
:
-
-
v9;
break
;
case
5
:
v19
=
(v21
-
-
&
1
) !
=
0
;
v9
-
=
v19;
break
;
default:
v18
=
(v21
-
-
&
1
)
=
=
0
;
v9
+
=
v18;
break
;
}
if
( v9 >
9
)
/
/
v9大于
9
结束最外层循环
break
;
if
( v21 >
8
)
/
/
v21大于
8
结束最外层循环
break
;
v13
=
&byte_4B7080[
10
*
v21
+
v9];
if
(
*
v13 )
/
/
这里的v13必须
=
=
0
,否则直接转到输出Try again!
break
;
*
v13
=
1
;
/
/
修改byte_4B7080[
10
*
v21
+
v9]
=
1
,标志该地方已经走过
if
( i
=
=
1
)
{
+
+
v4;
/
/
最外层循环的控制变量
v22
=
v9;
v3
=
input
[v4];
/
/
依次取出
input
if
( v3 )
goto LABEL_4;
/
/
到循环首
goto LABEL_19;
/
/
到判定结果的起始位置
}
v10
=
v20;
}
}
else
{
while
( v24 !
=
+
+
v5 )
{
if
( byte_4B7040[v5]
=
=
v3 )
/
/
v3是
input
中的某个字符,该循环实际是取得v3字符在byte_4B7040中的下标位置
/
/
如果v3不存在byte_4B7040中,那么直接转到输出Try again
goto LABEL_11;
}
}
}
}
else
{
LABEL_19:
v14
=
byte_4B7080;
v15
=
0
;
do
{
v16
=
v14
+
10
;
do
v15
+
=
*
v14
+
+
=
=
0
;
while
( v16 !
=
v14 );
/
/
循环
10
次
}
/
/
内层循环表示v14[
0
:
10
]全为
1
while
( &dword_4B70DA !
=
(_UNKNOWN
*
)v16 );
/
/
一共循环
90
次
/
/
所以判定输入正确的条件为byte_4B7080[
0
:
90
]均为
1
!
if
( !v15 )
{
sub_4ABF30(&dword_4B8860,
"Good job!"
,
9
);
sub_4AD980(&dword_4B8860);
return
0
;
}
}
}
sub_4ABF30(&dword_4B8860,
"Try again..."
,
12
);
sub_4AD980(&dword_4B8860);
return
0
;
}
int
__cdecl main(
int
argc, const char
*
*
argv, const char
*
*
envp)
{
...
printf_0((
int
)&dword_4B8860,
"Input your code: "
);
scanf((
int
)&dword_4B8680,
input
);
/
/
接受用户输入
if
( strlen(
input
) <
=
0x30
)
/
/
长度不能超过
0x30
{
v3
=
input
[
0
];
if
(
input
[
0
] )
{
v4
=
0
;
v21
=
0
;
v22
=
0
;
v24
=
dword_4B7020;
/
/
0x24
v23
=
byte_4B7040[
0
];
LABEL_4:
if
( v24 >
0
)
{
v5
=
0
;
if
( v23
=
=
v3 )
{
LABEL_11:
/
/
这是一个循环结构的循环首,循环次数为
input
的长度
v7
=
(v4
+
v5
/
6
)
%
6
;
v8
=
v5
+
v4;
v9
=
v22;
v20
=
v7;
v10
=
5
-
v8
%
6
;
for
( i
=
0
; ; i
=
1
)
/
/
实际循环两次
{
switch ( v10 )
{
case
1
:
+
+
v9;
break
;
case
2
:
v17
=
(v21
+
+
&
1
)
=
=
0
;
v9
+
=
v17;
break
;
case
3
:
v12
=
(v21
+
+
&
1
) !
=
0
;
v9
-
=
v12;
break
;
case
4
:
-
-
v9;
break
;
case
5
:
v19
=
(v21
-
-
&
1
) !
=
0
;
v9
-
=
v19;
break
;
default:
v18
=
(v21
-
-
&
1
)
=
=
0
;
v9
+
=
v18;
break
;
}
if
( v9 >
9
)
/
/
v9大于
9
结束最外层循环
break
;
if
( v21 >
8
)
/
/
v21大于
8
结束最外层循环
break
;
v13
=
&byte_4B7080[
10
*
v21
+
v9];
if
(
*
v13 )
/
/
这里的v13必须
=
=
0
,否则直接转到输出Try again!
break
;
*
v13
=
1
;
/
/
修改byte_4B7080[
10
*
v21
+
v9]
=
1
,标志该地方已经走过
if
( i
=
=
1
)
{
+
+
v4;
/
/
最外层循环的控制变量
v22
=
v9;
v3
=
input
[v4];
/
/
依次取出
input
if
( v3 )
goto LABEL_4;
/
/
到循环首
goto LABEL_19;
/
/
到判定结果的起始位置
}
v10
=
v20;
}
}
else
{
while
( v24 !
=
+
+
v5 )
{
if
( byte_4B7040[v5]
=
=
v3 )
/
/
v3是
input
中的某个字符,该循环实际是取得v3字符在byte_4B7040中的下标位置
/
/
如果v3不存在byte_4B7040中,那么直接转到输出Try again
goto LABEL_11;
}
}
}
}
else
{
LABEL_19:
v14
=
byte_4B7080;
v15
=
0
;
do
{
v16
=
v14
+
10
;
do
[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课
最后于 2021-5-14 21:08
被kanxue编辑
,原因:
赞赏
他的文章
- [原创] KCTF2022——第二题 末日邀请之论如何掉坑里 8258
- [原创] KCTF2022——第三题 石像病毒题解 7474
- [原创]第二题 南冥神功 4921
- Win10Ntfs文件系统的FCB结构体 3204
看原图
赞赏
雪币:
留言: