首页
社区
课程
招聘
[原创]连连看逆向
发表于: 2019-11-14 15:17 8217

[原创]连连看逆向

2019-11-14 15:17
8217

连连看

MFC DLL

使用MFC DLL,方便之处在于不需要自己写DLLMaincase了,直接写在InitInstance函数中即可,且调试时使用Cstring比较方便。

SetWindowLong

修改窗口回调函数,在自己的窗口回调函数中处理快捷键响应

CallWindowProc

调用指定窗口回调函数

多线程

_beginthreadex创建线程便于弹窗

1.我们先运行程序,会弹出下面的对话框

2.用PCHunter查看运行中的进程,此时只有一个进程,就是我们打开的exe

3.点击开始游戏,又会弹出下面的对话框,再用PCHunter查看运行中的进程,此时多了一个新的进程qqllk.ocx

4.先不管它,我们点击继续,终于来到我们游戏主体,再用PCHunter查看,发现qqllk.ocx退出,多出一个kyodai.exe,


5.由于最终运行的是kyodai.exe,我们可以假设kyodai.exe就是我们要找的游戏原进程,我们回去双击kyodai.exe,发现点击它又运行不了。但是通过其它程序又能运行它,由此猜想其它程序在打开kyodai.exe之时先对kyodai.exe的内存进行了修改,然后使其能正常运行。那是哪个程序修改的它呢,前面分析有一个进程qqllk.ocxkyodai.exe运行后就退出了,我们大胆假设就是这个打开的我们游戏主体进程,并对其进行修改

,下面用OD对其进行分析

6.重新打开游戏,到这一步,通过上面我们知道,此时我们产生了一个新进程qqllk.ocx,现在我们用OD附加这个进程,猜想它可能使用了CreateProcessA/W函数打开进程,由于不知道到底是A还是W版,我们在两个函数上面都设置上断点

7.运行之后发现在CreateProcessA函数上断下,并且kyodai.exe程序被它以挂起的方式打开了,很多恶意程序都是这样的套路,那么就容易猜想了,挂起了程序之后就可能修改内存数据,之后恢复程序,那么我们就在修改内存数据函数WriteProcessMemory下断点,运行。

8.发现果然断在了我们下的WriteProcessMemory函数上,并且观察堆栈,会发现该函数是在kyodai.exe程序中的0x43817A地址处修改了1个字节的数据。数据窗口跟随可以看出是修改后的数据是0

9.然后在唤醒线程函数ResumeThread下断点,运行之后果然走到了这里。

10.那么我们现在就已经分析处理其运行机制,它首先运行qqllk.ocx,然后再由qqllk.ocx执行CreateProcessA以挂起的方式打开kyodai.exe,再执行WriteProcessMemory修改kyodai.exe内的0x43817A地址处的一个字节,将其改为0,再执行ResumeThread恢复kyodai.exe进程。

11.那么我们现在可以直接使用010Editor打开kyodai.exe直接找到3817A(因为默认加载基址0x400000,需要减去它得到文件偏移)地址,把里面的数据改为00,如果文件是只读的情况,改不了,可以将文件复制一份,修改复制后的文件,保存,运行复制后的文件。

12.运行我们修改后的kyodai.exe,发现直接就来到了游戏主体,到此,我们找到了游戏的原程序并且去掉了广告。接下来就是分析游戏关键功能了

13.点击练习的时候地图会随机刷新,那么肯定会用到rand这个随机函数,我们用OD附加我们原程序,再在rand函数下断点,点击游戏中的练习按钮,就会断在我们rand函数处,然后在点击OD工具栏上的K进行栈回溯分析。

14.观察发现有2个上层调用(带程序名字的2个),它们的关系是0x41A085处的函数调用0x41CAF2的函数,0x41CAF2再调用rand函数。在K中越靠下就越是外层的函数。

15.双击分别进入上面两个地址,并在它们上面设置断点,然后把之前rand的断点删除

16.F9运行后再次在游戏中点击练习会在第一个断点0x41A085处断下,这是一个函数CALL,要重点关注一下它上面一行代码MOV ECA,EDI,由于这是C++所写的程序,它都会使用ECX这个寄存器传递this指针也就是传递一个对象。之后进入函数要留意一下ECX寄存器。按F7进入这个函数,先Ctrl+A分析一下该模块,发现一开始就把ECX的值传给了ESI,先不管继续单步,没几步就看见了字符串start.wav,结合下面的 %sSound\%s分析这可能是个音乐文件,我们在音乐文件夹中去找找看,发现真的是,这里就差不多可以证明这个函数就是初始化游戏的哈桑函数。

17.然后再快速单步很快就能发现刚才所下的第二个断点,发现rand下面有一个memcpy拷贝内存的函数,走一遍注意观察OD中右上角寄存器的变化,我们刚刚看到这个函数里面,是将ECX传递给了ESI,而0x41CAFC地址处对ESI进行了访问,走一步之后我们发现EAX的值是0x12BB50,那么选中它,右键->数据窗口跟随 ,查看0x13BB50地址里面有些什么数据。

18.然后单步走到memcpy下一步处,观察0x12BB50地址里的数据,多来几次,发现除了前8个字节没变,后面都被填充成某种规律的010100...猜测0x12BB50可能是游戏的地图数组基地址,先不管,继续单步,当走到0x41CB15时,0x12BB50处数据又被刷新了。所以0x12BB50极有可能是我们要找的地图数组基地址。

19.为了验证是否正确,按F9让游戏运行起来,观察地图与该内存数据是否有联系,多来几次,发现地图和OD中的内存非常相似。

20.为了再次确认,我们把游戏中的物品点击消除掉在观察内存发现被清0了,那么我们就可以确定0x12BB50就是地图数组基地址了,并且得到了0x12BB58就是地图数据的起始位置了。

21.现在,我们来捋一捋思路,先将地图数组变成有规律的0与1,然后再将1上的位置随机分配各种代表图案的数值,而前一步并没有循环随机函数,只随机了一次,大胆假设它应该存在一个保存各个地图基本形状的数组,随机函数是随机使用那个地图,经过分析我在rand函数上面最近的一个CALL证实了我这个假设

22.localkyodaimap.map就保存着我们所有地图的基本形状(有图案还是没有图案),至于是什么图案,是在0x41CB15地址处的CALL里面随机分配的,这里就不细说了

23.接下来就是分析道具了,先从指南针开始。指南针道具是帮助玩家找到可以消除的2个相同图案,而要实现其功能必须要访问地图数组,所以我们可以在0x12BB58地址处下一个内存访问断点。

24.先在OD中按ALT+B来到断点模块,把其它断点禁止或者删掉,然后运行游戏,点击指南针,程序就会停下来,点击K进行栈回溯分析。发现有5个上层调用,在5个位置处都设置上断点,把刚刚设置的内存访问断点删除掉。

25.再按F9运行OD发现运行多次都停在0x4292A5处,那么这肯定不是我们要找的函数,去掉其断点。再运行,发现只要点击游戏界面,就会在0x40CACA处断下,所以这个也不是我们要找的,去掉其断点,继续运行,同样的0x41AF11只要点击游戏界面,就会在该地址处断下,pass掉,再按F9运行起来。

剩下的0x41E76C0x41DE5C处的函数可能是我们要找的关键函数,现在想要写代码完成指南针的功能,只需要找到这两处地址的函数调用时所需要的参数,那就可以模拟出指南针的功能。

重新运行起来,点击指南针,会在0x41DE5C处断下,选中这一行按Enter键进入这个函数一直往下拉找到末尾RETN观察发现RETN 0xC也就是说0x41DE5C处的函数调用需要3个参数(当然这里不考虑通过ECX寄存器传递的this指针),通过观察堆栈得出参数是00F0

26.为了确认这3个参数是不是可变的,多操作几次,发现参数没有改变,那现在就只要确认ECX的值,就可以用这个函数模拟指南针功能了。暂时先不管它,那么我们再次运行,使其段在0x41E76C处,按照上面分析方法,这个函数有2个参数,是两个地址,数据窗口跟随,然后单步,看看两处地址的数据有啥变化。

27.指南针的作用是找出两个可以相消除的图案,也就是要找到这两个图案的坐标,通过观察发现这个CALL有可能是获取两个可以相消除的图案的坐标。然后我们多次将内存中的数值与找到的两个图案相比较,证实了此猜想成立。

28.所以现在只剩下我们刚刚找到的处于0x41DE5CCALL,只要找到ECX的值就可以了。往上找ECX的值,需要往上层函数分析,这里我们换一种方法分析,使用CE附加程序,搜索ESI的值,发现有几个绿色的基址。

29.我们把这几个基址在OD反汇编窗口右键->查找->所有常量,排除后还剩下0x45DEBC0x7793CDD8,这里先用0x45DEBC试试。

30.相同的原理我们找出其它道具的调用CALL,这里就不细说了。我们发现,都会调用0x41DE5C处的CALL,只是参数不同,对比下面参数

调用指南针:00F0

调用炸弹:00F4

调用重列:00F1

得出结论第3个参数是道具类型,而0x41DE5C处的函数功能应该是使用道具。

31.找消除CALL,要消除,肯定要对地图数组改写,所以我们可以在相应位置设置内存写入断点,然后点击这两个位置消除,OD就会断下,取消内存写入断点,然后通过栈回溯分析。

32.通过工具栏上的K跳转到栈回溯窗口,发现有5个,按照之前的套路进行分析。最后还有3个CALL有可能是我们要找的,通过分析,发现第一个CALL有7个参数,有点多,而且其中有参数的值不确定,pass,第三个CALL没有传坐标,应该不是,也pass,那么我们就只剩下第2个CALL了,它有6个参数,经过分析,第一个参数为0,第二个参数为地图数组基址(这个前面已经找到),第3,4个参数为两个坐标,我们可以通过上面指南针中找到的获取两个可以消除的点的函数获得。

33.往上找到(这里需要往上一层找,第5,6参数是上层函数的参数),第5,6个参数的值是在这赋值的,ECXESI+0x1E84的值,而ESI和上面我们找到的ESI一样,这就不说了。

下面就是编写辅助了,单消只需要调用获取两个能相消的坐标的函数,再调用消除CALL就可以了,当然使用炸弹道具也可以完成,秒杀就是循环使用单消就行,这里有点,就是如果没有能够相消除的两个点的话,是会返回两个(0,0)坐标,所以,可以根据此退出循环。

1.用VS2017首先创建一个MFCDLL程序,选择在静态库中使用MFC,这样兼容性更好,这个选项也可以在属性->常规->MFC的使用里面更改。

2.通过Spy++获得游戏的窗口名与类名,用于FindWindow函数获取游戏窗口句柄。

3.使用__asm内联汇编调用我们找到的关键函数,说明下,消息采用自定义消息。

4.最后上图

游戏链接:

链接:https://pan.baidu.com/s/1kP4-mthdA8-0LIa7Oo0CVw
提取码:h2ea

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

收藏
免费 11
支持
分享
最新回复 (27)
雪    币: 180
活跃值: (1313)
能力值: ( LV4,RANK:40 )
在线值:
发帖
回帖
粉丝
2
很好的基础外挂教程
2019-11-14 15:30
0
雪    币: 38
活跃值: (185)
能力值: ( LV2,RANK:15 )
在线值:
发帖
回帖
粉丝
3
36踩楼来了
2019-11-14 16:38
0
雪    币: 6102
活跃值: (5520)
能力值: ( LV5,RANK:65 )
在线值:
发帖
回帖
粉丝
4
虽然是个老游戏了,但是分析的很详细,支持一波!
2019-11-14 18:00
0
雪    币: 6832
活跃值: (1637)
能力值: ( LV5,RANK:67 )
在线值:
发帖
回帖
粉丝
5
谢谢分享
最后于 2019-11-15 09:12 被晴雯晴雯编辑 ,原因:
2019-11-15 09:12
0
雪    币: 9218
活跃值: (1640)
能力值: ( LV2,RANK:15 )
在线值:
发帖
回帖
粉丝
6
我是不是很菜,勉强看懂了
2019-11-16 09:06
0
雪    币: 2255
活跃值: (238)
能力值: ( LV6,RANK:85 )
在线值:
发帖
回帖
粉丝
7
可能是我语言表达能力不好,见谅了
2019-11-16 10:01
0
雪    币: 385
活跃值: (15)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
8
学习了,感谢分享
2019-11-17 13:43
0
雪    币: 1088
活跃值: (158)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
9
感谢分享
2019-11-19 17:44
0
雪    币: 204
活跃值: (80)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
10
非常感谢大佬分享.谢谢.
2019-11-20 13:02
0
雪    币: 5
活跃值: (208)
能力值: ( LV2,RANK:15 )
在线值:
发帖
回帖
粉丝
11
2019-11-20 19:34
0
雪    币: 8519
活跃值: (9122)
能力值: ( LV12,RANK:360 )
在线值:
发帖
回帖
粉丝
12
666,感谢分享
2019-11-20 19:57
0
雪    币: 8
活跃值: (263)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
13
在执行第14步的时候调用堆栈的列表不一致,然后后面的完全对不上了。有遇到和我一样的问题的吗
2019-11-24 03:18
0
雪    币: 2255
活跃值: (238)
能力值: ( LV6,RANK:85 )
在线值:
发帖
回帖
粉丝
14
wx_x_931870 在执行第14步的时候调用堆栈的列表不一致,然后后面的完全对不上了。有遇到和我一样的问题的吗
没有啊,有图吗
2019-11-24 17:23
0
雪    币: 8
活跃值: (263)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
15
好像知道了,断下来后,再F9一次就对了
最后于 2019-11-25 00:35 被wx_x_931870编辑 ,原因:
2019-11-24 23:57
0
雪    币: 3
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
16
谢谢大佬分享
2019-11-25 09:57
0
雪    币: 2038
活跃值: (4096)
能力值: ( LV7,RANK:100 )
在线值:
发帖
回帖
粉丝
17
感谢分享
2019-11-25 22:32
0
雪    币: 8
活跃值: (263)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
18
执行27步的时候怎么感觉数据不对呢。。。。
2019-11-26 00:06
0
雪    币: 2255
活跃值: (238)
能力值: ( LV6,RANK:85 )
在线值:
发帖
回帖
粉丝
19
wx_x_931870 执行27步的时候怎么感觉数据不对呢。。。。
是对的啊,C是12,从0开始数,F是15
2019-11-26 08:17
1
雪    币: 162
活跃值: (63)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
20
这样的分析和教程真是太好了!支持一个。
2019-11-26 11:52
1
雪    币: 8
活跃值: (263)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
21
请教一下 为啥是这个地址呢,不应该是41C6C3吗
最后于 2019-11-29 00:20 被wx_x_931870编辑 ,原因:
2019-11-28 23:15
1
雪    币: 2255
活跃值: (238)
能力值: ( LV6,RANK:85 )
在线值:
发帖
回帖
粉丝
22
wx_x_931870 请教一下 为啥是这个地址呢,不应该是41C6C3吗
我上面(32)说过这个CALL参数没有坐标,如果有坐标也是可以的。
2019-11-29 08:14
0
雪    币: 1237
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
23
徐佬是你吗?
2019-11-29 09:18
0
雪    币: 2106
活跃值: (2639)
能力值: ( LV4,RANK:55 )
在线值:
发帖
回帖
粉丝
24
很详细
2020-2-6 03:51
0
雪    币: 7309
活跃值: (3788)
能力值: (RANK:1130 )
在线值:
发帖
回帖
粉丝
25
应该写个自动玩的算法,自动点击完成
2020-2-6 16:55
0
游客
登录 | 注册 方可回帖
返回
//