browser icon
You are using an insecure version of your web browser. Please update your browser!
Using an outdated browser makes your computer unsafe. For a safer, faster, more enjoyable user experience, please update your browser today or try a newer browser.

扫雷不死的秘密

Posted by on 2008 年 10 月 09 日

你可以任意转载本文,但请在转载后的文章中注明作者和原始链接。
媒体约稿请联系 titilima_AT_163.com(把“_AT_”换成“@”)。

Windows的扫雷游戏有这么一个秘密:在你第一次点击游戏区中的方块时,出现的绝对不会是地雷。
实践是检验真理的唯一标准,我用IDA拆了winmine.exe,版本是5.1.2600.0。下面我只简要介绍分析的结果,不再特别列出晦涩的汇编代码。
扫雷游戏的游戏区数据放在一个庞大的一维BYTE数组中,这个变量的名字是rgBlk。并且,用于获取指定坐标信息的公式是:

1
LPBYTE pbPos = &rgBlk[y * 32 + x];

注意,这里的x和y是以1为起始索引的;换句话说,rgBlk[0]~rgBlk[31]是不被使用的。另外,对于最大的游戏区(30*24)来说,rgBlk的大小是足够可以胜任的。
那么下面我们的实验开始,在调试器中检查rgBlk的内存。为了显示的简洁明了,我选择了初级9*9的区域。

在上图中我对db输出的结果做了处理,其中白色背景的被选定文本区域是游戏区的有效内存数据,灰色的文字也代表了无效(横坐标大于9)的数据。红色的8f代表随机生成的地雷,1f代表这个方块还未被翻开。
接下来我故意打开第2行第1列的方块,并继续检查游戏区的数据,如下图。

如你所见,这个方块并不是雷,它的数据变成了42。与此同时,第1行第1列的方块却变成了8f,也就是地雷的数据。
好了,下面再打开第1行第1列的方块,游戏结束。最后的结果表示,地雷的位置和内存中的数据是一样的。

最后当然是揭秘环节。在玩家点击了一个含有地雷的方块时,游戏会做出如下判断:

  1. 如果游戏已经进行(不是第一次点击),则引爆地雷,游戏结束。
  2. 如果本次点击为第一次点击,则从左上角开始依次搜索,直到找到一个不是地雷的方块,并将其修改为地雷。原有的地雷方块做无雷处理。

上面的逻辑是在StepSquare函数中实现的,有兴趣的可以详细了解一下逆向后的代码。

从用户体验的角度来讨论的话,这么做的原因很简单:如果不特殊处理的话,从概率学的角度上来讲,那种每次玩扫雷都会被第一个方块炸死的衰人还是会有的。

订阅本站

9 Comments

  • At 2008.10.10 00:03, vxib said:

    马哥,好强,能不能告诉我,你是怎样定位到这块内存区域的?
    谢谢。

    • At 2008.10.10 09:19, 李马 said:

      反汇编winmine.exe,查找rand的调用,顺藤摸瓜。

      • At 2008.10.11 00:36, vxib said:

        多谢马哥提醒,根据您的提示,我用OD也找到了,呵呵!
        感谢

        • At 2008.10.10 19:05, zaroty said:

          马哥,从第一次看了你的《城里城外看SSDT》之后,就对你有种相当的佩服。现在小弟我在学习Windows编程方面的东西,也感觉学得挺顺利,遇到问题大多都能解决,但是想着现在的系统编程不知道还有没有出路,很是迷茫啊。看到好多的招聘都是需求WEB开发的人才,而那些需要系统编程的人才的地方,要求都是那么的高,比如需要内核分析、加壳脱壳、汇编等等东西。现在一直怕的就是不知道自己能不能达到那个高度,感觉好远,好深,对自己一直没有信心,李马大哥能给指条路么?

          自从被一个高手骂为 “菜比” 之后,我一直想摆脱这个称呼。:-C

          • At 2008.10.13 09:41, 李马 said:

            勿在浮沙筑高台,先从基础做起。
            《Windows核心编程》和《深入解析Windows操作系统》是不错的两本,可以先从这里开始。

            • At 2009.01.02 11:49, zaroty said:

              谢谢了,马哥。

              • At 2008.10.10 20:07, 真千里 said:

                内存这东西,还需要研究

                • At 2008.10.14 14:08, Gohan said:

                  请问那个命令行的调试工具是什么?

                  • At 2008.10.14 14:13, 李马 said:

                    Debugging Tools for Windows 的 cdb.exe。

                    (Required)
                    (Required, will not be published)