一直对逆向感兴趣,就拿最简单的扫雷开始,对于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 之前应该有如下类似操作:
[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课