查看原文
其他

利用OD通过Call调用实现扫雷(win7旗舰版32位)

2017-07-22 Thvoifar 看雪学院

一直对逆向感兴趣,就拿最简单的扫雷开始,对于XP系统中的扫雷,雷的数目以及雷区的地址都是固定的,可以直接通过Cheat Engine搜索出来,然后在OD中直接下内存访问断点,找到扫雷整个区域,获得行数和列数,再顺藤摸瓜找到左键点击的处理函数和右键点击的处理函数,读取雷区数据,一一比较如果是雷就右键标记,如果不是可以直接左键点开,即可完成秒杀。

经过了大概半个月的时间,终于在查阅各种帖子和不断的摸索下,实现了Win7 32位系统扫雷的秒杀,哈哈,太开心了!

因为XP系统的扫雷中雷区的地址是固定的,可以通过CE进行搜索出来,但Win7系统的扫雷是用C++写的,雷区不再是固定的,而是在鼠标第一次点击之后再产生雷的位置。对win7扫雷一开始没有一点思路,后来看了很多牛人写的帖子,在他们的基础上才能慢慢的入手。可以参考:

《Vista的扫雷》:http://bbs.pediy.com/thread-40295.htm

《Win7自动扫雷》:http://bbs.pediy.com/thread-120152.htm

这2篇文章里的思路都是通过对rand函数下断,分析找到雷存放的地址,每个格子里存放0或1,如果是1则是雷,是0则不是雷,发送消息模拟鼠标的单机,进行自动扫雷。其中,在《Vista的扫雷》提到了重定位的处理,解决方案2对于Win7 32位下的扫雷并不适用,这篇文章中提到:

“假设扫雷入口地址设为dwCodeAddress,则[3931B8] 这个地址得到的方法是: ( dwCodeAddress & 0xFFFF0000 ) + 0x531B8”

但是在Win7 32位的扫雷中,并不是这样的,用PEiD打开扫雷

可以看到,扫雷的入口点是0x0002e08f,用OD打开扫雷,停在了入口点,代码是

001CE08F > $  E8 B5050000   call MineSwee.001CE649

001CE094   .^ E9 4DFDFFFF   jmp MineSwee.001CDDE6

所以扫雷中地址的计算方法是:扫雷模块地址+偏移

入口点地址0x1ce08f = 扫雷模块地址+0x2e08f,所以此次加载扫雷模块地址为

MineSweeper.exe = 0x1A0000

在此我找到了一种可以去除重定位的方法,PE头中的文件头的Characteristics字段指定了文件的类型,占用2字节,其第0比特为1,即表示文件中不存在重定位信息,用C32Asm打开扫雷,找到该字段

该字段为0x0102,其第0比特为0,即存在重定位信息,将其修改为1,将会给我们分析带来很大的方便(地址固定),即将该字段修改为0x0103,在下面的分析中我就用修改后的文件进行分析,该修改并不影响分析结果,同样适用于没修改的扫雷(因为偏移是固定的)。分析前面的过程在《Vista的扫雷》和《Win7自动扫雷》中讲得很详细,在此不做赘述,简单走一遍,看过的可以直接跳过。

首先,用OD加载扫雷,对rand函数下断:bp rand,然后先将该断点禁止,按F9运行起来,启动该断点,扫雷断下

一看便知该模块不是扫雷的模块,而是msvcrt。在堆栈窗口中看到,

在第1行处反汇编跟随(按Enter),到

鼠标点到该函数第一行,OD在反汇编窗口下方会有提示

“本地调用来自 01020176, 01023169, 01023177, 01023BB3, 01027466, 010275B9, 01027E86, 01027E98”

对这8个call都进行下断,F9,会发现一直断在

删除这个断点,继续F9,回到游戏,不会中断了,开始游戏并点击一个格子,断在如下位置

往上看,则如《Vista的扫雷》中一样,是根据第一次点击的格子产生序号并保存序号的代码,在此列举一下,看过的可以跳过

按Ctrl+F9 2次执行到返回,或在堆栈窗口中找到第2个“返回到”,跟随到上上一层:

其中,call MineSwee.01021418中的代码及注释如下(看过的可以跳过)

到此得到了地址0x10868b4,查看入口点代码

扫雷模块地址为0x1000000,所以

方块数据=[[[[[[[minesweeper.exe+0x868B4]+0x10]+0x40]+0x0C]+4*X坐标]+0x0C]+4*Y坐标];分析一下取值有 1~8数字 9未开 10旗 11问号 12空

雷地址  =[[[[[[[minesweeper.exe+0x868b4]+0x10]+0x44]+0x0c]+4*X坐标]+0x0c]+Y坐标]  1表示有雷 0表示没雷

esi=[[minesweeper.exe+0x868B4]+0x10];minesweeper.exe表示扫雷模块地址

[esi+0x4] => 雷数

[esi+0x8] => 行数

[esi+0xc] => 列数

[esi+0x18] => 鼠标左键单击次数

第一次点击  列号:[esi+0x24]

行号:[esi+0x28]


然后找左键单击打开格子Call,既然是左键单击,该Call中的参数应该是点击格子的X坐标和Y坐标,所以在该Call之前应该有如下类似操作:

push X坐标

push Y坐标

Call 0x……

在我们之前的分析中寻找,发现有2个地方可疑

第一处:

第二处:

对于第二处,有个跳转,不是第一次点击格子的话会跳过,因此排除。怀疑第一处是我们要找的Call,用CE加载扫雷,在自动汇编中写入测试脚本:

执行,得到myscript=某个地址,记住该地址,打开创建线程,输入该地址,确定,看扫雷打开了一大片,哈哈!这就是我们要找的左键单击打开一个格子的Call。现在便可以实现一键自动扫雷了,但是为了能够把雷标记出来,我们还可以找右键单击的Call。

右键单击格子会改变格子的状态,10为旗,11为问号,在第一颗方块数据处下硬件断点,即X=0 Y=0处,[[[[[[[minesweeper.exe+0x868B4]+0x10]+0x40]+0x0C]+4*0]+0x0C]+4*0],右键单击第一个格子,扫雷断下,进行回溯跟踪,在第二次返回后,找到了可疑的地方

和左键单击一样,也是压入Y坐标和X坐标为参数,然后调用一个Call,但是调用之前给ecx进行了赋值,来源于esi,又要找esi,但是在上层中寻找,并没有发现esi来源于什么地址。不如跟进该Call看看

是不是很熟悉,原来ecx就是之前的那个指针,即[[minesweeper.exe+0x868b4]+0x10],在CE中写脚本进行测试:

执行后,发现扫雷并没有什么反应,有点失望!但是在扫雷中其他格子右键单击一下,发现第一个格子也变成被标记状态了,哈哈,这就是我们要找的右键单击格子Call,分析终于完成了!花了2周多时间,最后还是有点小激动,\(^o^)/

最后进行编程实现:


界面如上,首先点击注入会获得共有几颗雷,并安装键盘钩子,按Home键进行一键扫雷,按F12进行全部标记。

最后,附一张扫雷自定义中难度最大时进行一键扫雷的截图,如下,24*30,共668颗雷。


主程序代码:

GetProcessBase.h代码:

该函数是获得扫雷模块地址的函数,相比《Vista的扫雷》中寻找程序入口点,该函数效率更高一些。

DLL钩子程序如下:

有不足之处,希望大家提出,欢迎讨论!


本文由看雪论坛 Thvoifar 原创,转载请注明来自看雪社区



热门阅读


点击阅读原文/read,还有更多干货等着你~

您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存