首页
社区
课程
招聘
[原创]修改扫雷程序实现悬停显雷
发表于: 2020-1-20 18:21 6755

[原创]修改扫雷程序实现悬停显雷

2020-1-20 18:21
6755

本人最近刚刚开始学习逆向分析,突发奇想想弄一个Windows XP扫雷的辅助。发帖前,在论坛上一搜,好多人都做过这个了,还有人做过Windows7 32位,64位的,突然感觉自己好低级……于是我又认真地把windowsXP扫雷的几乎所有汇编代码都分析了一遍,最后做了一个修改扫雷内部代码而实现悬停显示雷的操作。

效果如下:


进入正题,这是我的预计任务

1.     找到回调函数

2.     找到并分析雷表

        找到存放时间的位置

3.     分析绘图代码


首先,用OllyDbg打开windows xp的扫雷程序。

一开始如下图所示

显然,是属于程序的入口部分代码,包含有初始化SHE,获取ImageBase,测试PE文件的有效性等等等等。

一:找窗口回调函数

为了实现找到回调函数这一个目标,首先需要知道获取来源。

首先想到WNDCLASSA(或WNDCLASSW)和WNDCLASSEX这两个结构体,WNDCLASSW定义如下

这两个结构体都是用来初始化窗口类的,在RegisterClass中被引用,根据该结构体的定义,在此结构的(+0x04)位置处,就是窗口回调函数的地址。所以,从设置WNDCLASS成员时指定的地址或者从RegisterClass调用时的栈窗口,可以找到WNDCLASS的地址,进而找到lpfnWndProc的值。

RegisterClass一般在主线程的WinMain中被调用,我向下跟踪,来到此处

目前窗口并没有创建,而接下来的第二个函数是exit的调用,标志着程序的退出,因此可以确认,下面的第一个函数,就是程序的WinMain函数。

跟踪进去

在第一个CALL处我进行了查看,发现是设置随机数种子,接下来明显地看到调用了LoadIconW,LoadCursorW,和GetStockObject三个API函数对WNDCLASSW进行设置,往下翻,立刻可以看见RegisterClassW。事实上,hIcon的位置在lpfnWndProc(+0x10)的位置,从LoadIcon的返回值的设置位置(2个地方)

一开始我以为是这里,结果发现1005B18没有写入的代码,接着向下看:

可知ebp-38-10=ebp-48就是回调函数的地址,接下来看到

可以确认,01001BC9就是回调函数的地址了,添加标签为lpfnWndProc

二:

进入窗口回调函数,马上看到一个switch

根据对回调函数的整体浏览,发现对WM_LBUTTONDOWN的处理部分,有将(记住这个地址)1005144处的数据设为0这估计是为了实现左键按下时显示格子0的效果,添加标签为bLButtonUp(Down的非是Up (`へ´*)ノ)

接着对WM_LBUTTONDOWN和WM_LBUTTONUP这两个消息的处理部分下断

在扫雷点击一个格子,在WM_LBUTTONDOWN断下,继续运行,WM_LBUTTONUP自然不会断下,而游戏界面无变化,说明WM_LBUTTONDOWN不进行点击格子的操作

现在大概可以判断,是左键弹起表示了对一个块的点击。

取消WM_LBUTTONDOWN的断点,继续点击,跟踪WM_LBUTTONUP,来到此处

开始是四个判断,根据对数据的分析,1005118应该保存一个POINT结构体,是当前点击的单位坐标,而1005334保存了扫雷区域的单位长度,1005338则是单位宽度。于是添加标签g_xPos,g_yPos,Length,Height

那么此处的作用应该是,判断点击坐标是否在范围之内,否则函数跳到末尾。

接下来则是这部分

一开始,判断了两个位置的数据,不为0则设置间隔为1s的定时器,于是我大胆猜测,这是第一次点击时会调用的代码,设置定时器,进行计时。那么,10057A4和100579C就可能:一个是时间的数据,一个是游戏是否开始的BOOL型数据。

然后让扫雷运行,再分别对10057A4和100579C下硬件写入断点,发现10057A4是每点开一个格子都会断下,并且计数+1,100579C是每秒都会断下,计数+1。那么,10057A4应该是翻开的格子数目,标签其为PressNum,10057C9应该是时间,标签其为Time

接下来的部分如图所示

1003872的跳转一般不会实现,100388B的跳转一般一定实现,第一个跳转是判断1005000处的数据是否为零,通过对此地址设置硬件断点,可以发现,当“新游戏”时,此处的值被设置为1,而游戏结束后,此处的值被设置为16。

第二个跳转发现访问了bLButtonDown这个地址,为0则跳转。这个地址前面见到过,在左键按下的时候被设置成了0,而左键弹起前一定会有按下操作,因此,这个地方一般也会跳过。(也可以写监测程序查看值的变化)

从前三行可以知道读取雷表的方法

例如有雷表BYTE arMine[..],需要读取第r行第c列

第一行将ecx:也就是r,赋给edx

shl相当于<<,第二行是将edx左移五位,五个二进制位就是乘以2^5(=32)

第三行读取

那么可以知道,1005340是雷表的头地址,标签其为arMine,读取方式为arMine[r*32+c]


通过不断地对数据进行更新和检查,可以知道储存规律:

雷表是一个以1个字节为元素长度的数组,0x10为游戏的边界

雷表元素的低四位:

i.              未翻开时,是0xF

ii.             插旗子时,是0xE

iii.            打问号时,是0xD

iv.            翻开时(非雷),是它的数字,是雷则为0xA(不是点击到的)

v.             左键按下时,是0x0

vi.            边界为0x1

雷表元素的高四位:

i.              未翻开时,是雷则为0x8,否则为0x0

ii.             翻开时(非雷),是0x4,是雷则为0x8(不是点击到的)

iii.            边界为0x0

雷表元素是点击到的雷,数据则为0xCC

上面的基本说的都没用(众所周知),接下来才是重头戏,如何实现,把鼠标悬停在一个格子上,如果那个格子有雷,就把雷显示出来(透视的感觉有木有)

首先,需要寻找一个可以安心写代码并能保存到文件的位置,将代码向下翻,找到1004A60的位置,下面都是0数据,可以使用,不过要先判断这个区域是否在扫雷文件内(不然保存不到文件里),RVA=4A60,转为文件FileOffset=3E60,而文件中.text节区是到4000,那么把它标签为InjectCode,于是在此处就可以放心地写入代码了。

首先我在扫雷窗口生成后对WM_PAINT下断,然后在扫雷点开一格,并没有断下,说明重绘函数不会处理左键单击,格子变化之类的游戏进行中的小调整,在这里写入代码就没有用了(我一开始莽,直接在这里写,然并卵)。为了知道贴图的怎么变化的,我在BitBlt下了断,点击一下,来到此处:

发现两个参数分别是我点下的x,y坐标,那么这个函数就是根据一个格的数值来绘图。标签其为UpdateBlockPaint,观察栈,发现:把雷表中的相应元素&0x1F后,作为8字节为元素长度的数组1005A20的索引值,就可以得到相应贴图的HDC,那么,显示的雷是0x8A,&0x1F得0xA,于是位置就是4*0xA+0x1005A20=1005A48,这个地址之后BitBlt中会用到哦~

这个函数的调用最终是起源于回调函数中的:

触发WM_MOUSEMOVE一定来到此处,左中右键按下也可能来到此处,一开始就判断左键是否按下,关于1005140的值,我用监测程序判断了一下

左键按下为1,弹起后为0

接下来是10031D4函数的部分

是为了实现,格子按下的效果,如果说左键按下情况下这次悬停在的格子和上次不同,就更改上次格子为不按下,这次格子为按下,关于PressOn和PressOff两个函数,还原后代码如下(我对IDA结果的类型表示不满意):

测试一下即知效果。

在回调函数中,WM_MOUSEMOVE时左键没按下,跳到此处

刚好可以在这里修改代码(字节刚好为5,强迫症福利),把前面写代码的位置标签为InjectCode,把10020C1处改为

并把10020C6标签为CodeReturn


[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)

上传的附件:
收藏
免费 7
支持
分享
最新回复 (6)
雪    币: 12502
活跃值: (3053)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
2
玩了玩,很不错。你很有想法,和我学做菜吧。
2020-1-20 21:43
0
雪    币: 9024
活跃值: (6245)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
3
跟我一起去蓝翔吧
2020-1-21 18:47
0
雪    币: 8447
活跃值: (5041)
能力值: ( LV4,RANK:45 )
在线值:
发帖
回帖
粉丝
4
思路太强了
2020-1-29 16:20
0
雪    币: 44
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5
学习了
最后于 2020-2-5 13:44 被tbobo编辑 ,原因:
2020-2-5 13:26
0
雪    币: 223
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
6
搞个Win10的那种啊
2020-10-24 16:03
0
雪    币:
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
7
学习了
2020-10-26 10:11
0
游客
登录 | 注册 方可回帖
返回
//