2023工业信息安全技能大赛—鹏城锦标赛复现-工控maze
这道所谓的工控题目其实就是一道CTF的流量分析+逆向的迷宫题。鉴于是第一次认真复现和总结流量分析和逆向的题目,感觉学到了不少东西,写篇博客记录一下。
题目附件
链接:https://pan.baidu.com/s/1RFHOLYmpAFbkPiR29dnA7g?pwd=c1cs
提取码:c1cs
流量分析
开始拿到流量包是这么一个情况
选择一个 TCP
包,追踪流
选择红框标注的这个箭头,可以往后翻找数据流
再往后翻一个流的时候,发现是 7z
字符串开头的,猜测这个流量里可能藏了一个 7z
文件
查看一下这个流对应的几个数据包,发现最后的包是 RST
标志位,这表明因为异常中断了这次的通信连接,所以这个流显示的并不是文件完整的数据。
因为之后会换个端口继续重传,结合这第一部分的信息可知,用 (ip.src == 192.168.40.199 && ip.dst == 192.168.40.41) && (tcp.flags.push == 1)
过滤出 192.168.40.199
与 192.168.40.41
通信时在应用层传输有效数据的报文(如下所示)
用命令 tshark -r maze.pcapng -Y "(ip.src == 192.168.40.199 && ip.dst == 192.168.40.41) && (tcp.flags.push == 1)" -T fields -e tcp.payload > 1.txt
将数据以文本形式导入到 1.txt
文件中,再用 010editor
打开是这个样子的
选择 010editor
里面的导入十六进制,导入的文件用的就是 1.txt
这样就拿到了这个 7z
文件的原始数据
将其保存后,就能正常解压里面的文件。拿到后发现是个 exe
文件,直接放到 IDA
里逆向分析
代码逆向
通过下面的关键代码能猜测出这是一个迷宫游戏(部分变量已将其重命名)
结合着运行程序和静态分析时的关键字符串,能够判断出走通迷宫的字符串,能输出 Congratulations!
,那么这个字符串就是 flag
结合着 IDA
动态调试,首先能够确定输入函数和输出函数。当输入完数据后,确定了两个变量,分别是输入的字符串 buf
和字符串长度 buf_length
(已经对其重命名)
迷宫题通常会用一个一维数组来表明一个图(团队里的逆向手说的 😋),因此上下移动的话,移动距离应该加一行的长度,而左右移动的话距离只加很短,由此能判断是横向移动还是纵向移动。
通过这个规律,最终能重命名出表示横、纵、单次移动距离、移动次数这些变量名称(具体逆向过程不再记录,下面给出我重命名变量后的代码)
switch ( buf[(_DWORD)v7] ) |
移动的规则明白后,就剩起点和终点的坐标,以及地图和地图边界问题了。
起点坐标就是变量 heng
zong
的初始值 (1,1)
终点坐标通过下面三行代码可以分析出来,输出 Congratulations!
的条件就是移动次数要小于等于 12
且 heng
和 zong
要为 8
,所以判断出终点坐标为 (8,8)
if ( step > 12 || zong != 8 || heng != 8 ) |
再看下输出 Congratulations!
的条件,每次执行任何一个操作(移动策略),都会到 LABEL_20
代码处进行判断,也就是每次移动后都要判断当前位置是否已经到达终点。
关键代码 if ( v9 && *((_DWORD *)v16 + heng + move_num) != 1 )
表面 heng
zong
都要小于等于 8
,且 (v16+heng+move_num)
不等于 1
才能往下走。第一个条件的 8
有可能就代表地图的边界,也就是一行只有八个可移动点,第二个条件则代表当前位置是否位于墙,也就是不可走的点位(众所周知,迷宫一定都是有墙的,这里的 1
能猜测到就是墙的意思)
如果说地图边界是 8
的话,就很难解释纵向移动 1
或者 2
时,为什么 move_num
这个变量(已被重命名)加减的是 10
或者 20
了。
经过分析后,只有一种解释。横向和纵向可移动的点位只有 8
个,但是横纵的边界是有墙的。而 move_num
每次加一行算的是所有可移动点位和不可移动点位。(大致轮廓确定如下,1
代表墙 0
代表可走的范围)
1 1 1 1 1 1 1 1 1 1 |
最后一步就是根据数组画出真正的图,根据上面分析,已知存在一百个点位。观察数组 v16
,一共有 25
个元素,每个元素占 16
个字节,总共是 400
字节。能猜测到 4
字节来表示一个点位。
以 v16[0]
为例,IDA
看到的数据是这样的,这样的显示误导我了很久(我一直以为这个直接看到的就是最终的点位图,但这和前面分析的不一样,连周围的墙都没有…)
实际上应该将其转为 dd
(双字型,Define Double Word
),这样看到的数据才是对的。把所有的数据全部转换出来,按照每十个点位一行来把图画出来
最终的地图如下
1, 1, 1, 1, 1, 1, 1, 1, 1, 1 |
按照这个走法,输入对应的字符即可
所以最后的 flag
为 flag{WMKMBHBVBMWM}