# 逆向作业 —— 扫雷 0 秒破解
这学期的逆向期末大作业是破解扫雷,由于我不是逆向这个方向的,所以对逆向破解了解不多,正好一直不知道写些啥进博客,干脆把作业写进来吧。内容不是很多,很短,但是破解这玩意儿真挺有意思的。
扫雷想做到 0 秒通关,可以在某种意义上进行 0 秒通关,第一点就是让时间永恒为 0,不增加;第二点就是让在游戏开始的一瞬间直接通关。
但显然,这个游戏好像有点不太可能用到第二种手法了,因为游戏在开始的一瞬间,时间就变成了 1。
那就只有在时间上动手脚了。
用 CE 查看时间所对应的变量所在地址:

之后让游戏运行这,看看哪些汇编指令写入了这个地址:

这里存在一个自增指令,地址在 0x01002FF5。
在反汇编页面看到了程序大概的逻辑,就是检查时间是否为 999,如果不是,就自增 1。

直接 nop 掉即可。

点击笑脸之后,发现多了一条对这一内存进行操作的指令,地址为 0x0100371A:

推测这一条指令在初始化相关的函数里。
而在游戏开始的时候,也就是第一次点击格子的时候,又多出来了一条新的指令写入了这一内存,地址在 0x01003830:

直接 nop 掉:

另外,关于计时器,右上角那个时间会根据游戏是否进行而动,推测游戏开始的时候计时器启动状态为 1,结束的或初始化之后状态为 0:

发现了两条,但是,在踩雷之后,发现这里:

Winmine.exe+5164 这个地址变成了 0,所以这个肯定就是计时器了,那么在初始化的时候看看有没有地址访问它:

有,进入动调页面看看,在这里打个断点,然后进行调试:

程序在这一段内进行了循环,lea eax, ds:[eax+esi*1+0x1005340],这里,对 0x1005340 这个地址的寻址方式是一个二维数组的寻址方式,所以这个地方应该是个二维数组,应该是雷区。
、
确实是雷区,并且经过游玩,雷区内数据如下:
- 0x8X 是雷区
- 0x0X 是未翻开的安全格
- 0x4X 是翻开的安全格
- 0xXE 是插上旗子的格子
现在的想法就是,让其在初始化的时候就让其给旗子插上,在游戏每次经过这个指令的时候,雷区就会多出一个雷。

所以修改这个即可,让其在初始化的时候就将雷置为 0x8E:

这么修改就行了。

当游戏胜利的时候,游戏状态进行了一次更新,这条指令被执行了:

然后就是在这里打个断点,进行动调,当执行到这里的时候,出现了弹窗:

执行到这里的时候,游戏的图标发生了变化。
执行到这里的时候发生了弹窗。


从栈帧回溯可以看到,100347C 被 35B0 这里调用:


在这里,给上面的 cmp 加上断点,重开一把游戏后,第一次点击非地雷的时候,发生了一次判定,之后每一次点击都进行了一次判定,且只有当游戏胜利时候,才会运行这里:

所以,估计这个判定跟游戏是否胜利有关系:

直接修改,让他自己跟自己比较:

只点击一次非地雷之后,游戏胜利,实现完全的 0 秒完成游戏。