修改扫雷程序实现悬停显雷
2020-02-04 18:58:00 Author: mp.weixin.qq.com(查看原文) 阅读量:61 收藏

本文为看雪论坛优秀文章

看雪论坛作者ID:Caim Astraea

本人最近刚刚开始学习逆向分析,突发奇想想弄一个Windows XP扫雷的辅助。发帖前,在论坛上一搜,好多人都做过这个了,还有人做过Windows7 32位,64位的,突然感觉自己好低级……

于是我又认真地把windowsXP扫雷的几乎所有汇编代码都分析了一遍,最后做了一个修改扫雷内部代码而实现悬停显示雷的操作。

效果如下:

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

1. 找到回调函数
2. 找到并分析雷表
3. 找到存放时间的位置
4. 分析绘图代码

首先,用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。
之后是设置值, eax=x,ecx=y。
接下来的部分如图所示:

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为游戏的边界。
雷表元素的低四位:
  • 未翻开时,是0xF
  • 插旗子时,是0xE
  • 打问号时,是0xD
  • 翻开时(非雷),是它的数字,是雷则为0xA(不是点击到的)
  • 左键按下时,是0x0
  • 边界为0x1
雷表元素的高四位:
  • 未翻开时,是雷则为0x8,否则为0x0
  • 翻开时(非雷),是0x4,是雷则为0x8(不是点击到的)
  • 边界为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
接下来是InjectCode处代码:

然后其中UpdateBlockPaint中没有越界判断(其实是我不想写了,这段代码费了我4个小时,Ollydbg打汇编代码就是自闭啊,写到后面由于长度,要把一些短跳改成长跳,awsl)
所以,要把g_xPos和g_yPos直接初始化为0,就没有问题了
完成!
至于代码中UpdateBlockPaint的越界判断,以及执行前对游戏是否开始的判断,可以自行添加。
- End -

看雪ID:Caim Astraea

https://bbs.pediy.com/user-880853.htm 

*本文由看雪论坛 Caim Astraea 原创,转载请注明来自看雪社区。

推荐文章++++

CVE-2017-11882理论以及实战样本分析

恶意代码分析之 RC4 算法学习

CVE-2017-0101-Win32k提权分析笔记

ROPEmporium全解

实战栈溢出漏洞

好书推荐


公众号ID:ikanxue
官方微博:看雪安全
商务合作:[email protected]
“阅读原文”一起来充电吧!

文章来源: http://mp.weixin.qq.com/s?__biz=MjM5NTc2MDYxMw==&amp;mid=2458303164&amp;idx=1&amp;sn=14d5b324a308827f5d95314906ad44a5&amp;chksm=b1818a3686f603208c3c81b9edfb7bb951e94e046048f4fb83f51147cde367a207683862091d#rd
如有侵权请联系:admin#unsafe.sh