比赛地址:FLARE-ON 2018
Ultimate Minesweeper
打开是个扫雷,点哪都死2333
IDA看一下发现是.NET,于是用dnspy打开
二话不说直接找success的窗口类
发现是由参数决定的flag
跟着交叉引用过去看参数
new SuccessPopup(this.GetKey(this.RevealedCells)).ShowDialog();
还调用了GetKey,继续看
由一个常数数组和以参数为种子的随机数生成
那么必须要搞出正确的种子才能得到flag啦,另一方面无数经验都证明随机数最好别自己复写了2333
继续去看种子是怎么来的
this.RevealedCells.Add(row * MainForm.VALLOC_NODE_LIMIT + column);
估计是把安全点的坐标都add进去了
那么最终还是转到寻找安全点的问题上了
我不怎么会C#的开发,所以尽量还是希望能够通过Patch来让程序主动调用
看了一下雷的是否存在是通过这里判断的
首先无敌,将中间的爆炸情况全部删去即可
然后一共30x30个格子,挨个点过去太累了
于是在Click事件中Patch上主动遍历所有按钮
然后试了一下,发现BombRevealed里判断了两个条件:
而后者MineVisible每次点击的时候会设置成True,而调试发现MinesPresent中存放的是雷和安全区
因此这里有两种解决方案,一种是遍历的时候顺道也设置一下MineVisible,另一种方案是只检查MinesPresent
我选择的是第二种
另外由于它是检查到剩余空数为0的时候才会判断成功,我们在已知无关的情况下可以强制遍历完以后直接调用成功弹窗方法
于是跑一下就能弹出flag了
另外可以看到左上角写着剩余雷数为897
那么可以再进一步逆向一下雷的生成方法
我们现在只到雷是存储在MinesPresent数组中的,于是继续跟着交叉引用向上翻
MinesPresent[]->this.minesPresent->GarbageCollect[]->AllocateMemory
而这个VALLOC_TYPE里正好有是三个值,对应三个点
于是可以通过自己遍历DeriveVallocType来找到三个安全点
24,28
28,7
7,20
于是可以手搓,反正就三个点(虽然会看瞎
也可以自己照着写一下随机数生成去正向运算
还可以强行Patch给定这三个点23333