寻找突破口
1.续上节课,此时看到标题,有基础的同学第一反应就是,老师用CE搜索血量,通过改变就能找到!
2.额,有这么简单吗!
3.既然写了这个帖子,肯定是有原因的
4.为了方便学习,我们就先按照同学们的思路来试一试,能不能找到最大属性,比如最大血!
5.首先老生常谈打开游戏,用CE附加游戏,搜索最大血!
6.4字节整数类型,血量470
7.发现结果有3205个,现在我们就要改变它,然后继续搜索
8.这里就等升级后,我们观察最大血的变化
9.再次搜索495
10.what!我的结果呢?没了?
11.这时候有的同学就说,老师!这肯定加密了!我们首次扫描然后变动和未变动来搜索肯定能找到
12.其实呢,这么想也没啥毛病,但是很麻烦,因为可能有很多结果,同学们可以下去试一试这个方法
13.但是为了写这个帖子,就是为了追求不同!
从正向找突破口
1.好了,这里我们换个思路,用一个别的方法
2.我们想一想,游戏要更新数据到界面上,那么肯定会访问内存数据然后格式化字符串更新到UI控件文本上!
3.把这个想清楚,今天的知识点就明白了大半了
4.这里为了让同学们了解的更加清楚,我这里用代码来阐述
5.首先定义2个函数,来模拟游戏格式化字符串显示当前血最大血并显示到UI上
6.接下来我们看看怎么格式化的
7.然后我这里又定义了一个类模拟我们的UI对象
8.当我们格式化字符串后,就会调用这个类对象的成员函数SetText()并设置文本字符串显示到UI上
9.从而我们就能在游戏界面上看到我们的字符串了!
10.好了这里基本原理搞清楚,不太明白的同学会问,老师将这个又啥关系吗?
11.这里细细道来,当我们访问当前血的时候,是不是紧接着访问了最大血!关键就在这里!
12.然后我们想一想,如果在当前血下访问断,是不是就能在断下的代码地方周围看到相关的接口调用并返回最大血呢?
13.起初我们这里只是设想,需要我们验证下!
进一步验证
1.在验证之前,我们用CE先把当前血找出来,通过精确搜索就能很快搜索出来,非常简单就不一一说明了
2.好我们继续,我们看到当前血周围确实没有最大血,而当前血在人物对象偏移+34的地方,类型为4字节整数
3.好了接下来我们就在当前血下访问!
4.在下访问之前,此时肯定有同学会问,为什么不是下写入呢?
5.其实很简单,通过上面代码不难看出,格式化字符串只是在访问而不是写入!明白了把!
6.现在下访问
7.断下来后,正如上面我们所说的,在访问当前血的周围可能有访问最大血,那么我们就在这个代码处的上下层看看接口CALL的返回值
8.果不其然通过下面紧接着的一个CALL的返回值确定是最大血,我们就找到了!是不是很简单呢?
如何调用CALL
1.上面我们找到了CALL返回最大血
2.我们其实可以直接调用CALL,但是发现这个CALL的参数涉及到了浮点数寄存器,可能不好调用
3.那么我们进入内层CALL看看呢
4.我们看到,这个CALL的参数很好调用,但是呢?看看返回值,发现最大血调用CALL后存在了xmm0中
5.是不是感觉也不太好调用
6.我们尝试看看是不能找到真正的内存数据呢?万一找到了刚才同学们说的加密值呢,那就赚大发了!
寻找内存数据
1.紧接着进入CALL内部看看是哪里给xmmo浮点数寄存器写入了最大值
2.最后仔细分析,发现原来人物对象+F0有一个属性数组,而且里面的值全是浮点数!这个浮点数就是把大家给坑住了
3.我们看看人物对象+F0的属性数据内存分布
4.进入就会看到一个4字节浮点数数组,这样看可能不太明显,那么我们显示浮点数看看
5.看见了吗,我们的最大血就在这个属性数组的索引为2的地方存着呢!!
6.哇居然是一个浮点数,其实我们在上面看到xmm0浮点数寄存器的时候,就应该想到可能是浮点数来表示血量的,只是我们的思维被固化的认为血量是整数存放在内存中
7.同时你还看到5080这个就是我们的战斗力存着呢
8.是不是还是很简单,好了今天的内容就讲到这里了,别忘了点个赞,粉粉老师哦
9.感谢大家对迪大学院的一路支持285530835
10.我们下一贴再见!