原题地址:https://adworld.xctf.org.cn/challenges/details?hash=0d75f9ba-1c77-11ed-abf3-fa163e4fa609&task_category_id=4


下载文件拖入IDA查看
根据以前做迷宫题的经验,F12+shift,无果,遂观察源代码,发现可疑长字符串。

一开始我没意识到它的长,所以选择手打,打到一半打不下去了,选择写脚本收集。
下面的代码实现文件每行最后一个字符(换行符除外)的收集:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import sys

if len(sys.argv) != 1:
file1 = open(sys.argv[1])
string = file1.readlines()
file1.close()
else:
path = input("请输入文件路径:\n")
file1 = open(path)
string = file1.readlines()
file1.close()

for i in range(len(string)):
print(string[i][-2],end="")

input()

print(string[i][-2],end="")中的[-2]换成[0]可实现第一个字符的收集,下面会用到。

其实我感觉这个功能的实现应该用EOF指针的,奈何学不来时间又不够,凑合用一下罢。

复制IDA汇编代码到记事本后拖入脚本,得长字符串:10001000100010001000000000000000000000000000000000000000000010001000100010001000000030001000100000000000000000000000000010001000100010001000000000000000100000000000000000000000000010001000100010001000000000000000100000000000000000000000000010001000100010001000000000000000100010001000100010000000000010001000100010001000000000000000000000000000000010000000000010001000100010001000000000000000000000000000000010000000000010001000100010001000000000000000000000000000000010001000000010001000100010001000000000000000000000000000000000001000000010001000100010001000000000000000000000000000000000004000000010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000000000000000000000000000000000000000000000000000000010001000000030001000100010001000100000000000000000000000000010001000000010001000000000000000100000000000000000000000000010001000000000000000000000000000100000000000000000000000000010001000000010001000000000000000100010001000100010000000000010001000000010001000000000000000000000000000000010000000000010001000000010001000000000000000000000000000000010000000000010001000000010001000000000000000000000001000100010001000000010001000000010001000000000000000000000001000000000001000000010001000000010001000000000000000000000001000000000000000000010001000000010001000100010001000100000001000000010001000000010001000000010001000100010001000100010001000100010001000000010001000000000000000000000000000000000000000000000004000000010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100000000000000000000000000000000000000000000000000000000000000000003000100010000000000000000000000000000000000000000000000000000000000010000000100010001000000000000000000000000000000000000000000010001000100000001000000000000000000000000000000000000000000000001000000000001000000000000000000000000000000000001000100000001000000000001000000000000000000000000000000000000000100010001000000000001000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000001000100010001000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000001000100010001000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000004000000
统计一下有2699个字符。

然后我傻乎乎地去对2699因式分解了,殊不知这串字符串是dword类型,每4个为一组,只有第一个值是有效值。

知识盲区了属于是。
于是接下来每四个为一组取第一个,用到分行脚本,结合上面的“收集每行第一个字符”的脚本,可以实现每四个取一个。
分行脚本如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import sys

if len(sys.argv) != 1:
file1 = open(sys.argv[1])
string = file1.read()
file1.close()
else:
path = input("请输入文件路径:\n")
file1 = open(path)
string = file1.read()
file1.close()

n = int(input("请输入每行字符个数:\n"))

for i in range(len(string)//n):
for j in range(n):
print(string[j+i*n],end="")
print("")
if len(string)%n!=0:
for j in range(len(string)%n):
print(string[j+(i+1)*n],end="")

input()

当然这里完全没必要分行,因为后面也要用到这个脚本,懒得写一个新的罢了。

四取一后得字符串:111110000000000111110311000000111110001000000111110001000000111110001111100111110000000100111110000000100111110000000110111110000000010111110000000040111111111111111111111111111111111111111111111111111111111111111111111111111110000000000000110311111000000110110001000000110000001000000110110001111100110110000000100110110000000100110110000011110110110000010010110110000010000110111111010110110111111111110110000000000040111111111111111111111111111111000000000000000031100000000000000101110000000000111010000000000010010000000011010010000000001110010000000000000010000000000000011110000000000000010000000000000010000000000000010000000000000011110000000000000010000000000000040
675个字符。
675=3*3*3*5*5
逐个尝试分行得675=15行*45列
分行如下:

可见有三个迷宫,3为起点,4为终点,1可走,0不可走,寻找最短路径得ddsssddddsssdssdddddsssddddsssaassssdddsddssddwddssssssdddssssdddss
md5加密得Flag。


主要被坑的点就是不知道dword类型的特性。