006 技能数组分析和代码编写

本文详细介绍了如何通过内存遍历和调试来获取游戏中的技能数据,包括技能ID、对象、等级和名字。通过数据整理和代码编写,实现了技能的自动化遍历,为自动打怪功能提供了基础。最后展示了实际效果并预告了下一篇文章的内容。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


现在我们已经有了人物的数据和周围对象的数据,还差一个技能数据和释放技能call,就可以完成自动打怪的功能。

接着我们来找技能遍历的数据

技能遍历

以技能的当前经验为突破口

在这里插入图片描述

直接搜索当前经验值

在这里插入图片描述

筛选得到唯一的一个数值

在这里插入图片描述

下访问断点,让断点断下,此时[rax]就是我们要追的数值

[rax]

rax来源于上面的call

在这里插入图片描述

这个call传入了一个技能ID和一个基地址作为参数,我们进入call内追rax的来源

在这里插入图片描述

经过这三个步骤rax变成了

[rax*10+rdx+4]

这里我们要追一个rdx

技能名字

在这里插入图片描述

直接搜索技能名字,把没有后缀的拿下来

在这里插入图片描述

然后确定唯一的一个地址

在这里插入图片描述

下访问断点,重新打开技能栏

在这里插入图片描述

返回上层,这里要追的是[r15+0x38C]

[r15+0x38C]

在这里插入图片描述

r15来源于rax,来源于[r12]

[[r12]+0x38C]

在这里插入图片描述

r12来源于rcx+0x4

[[rcx+0x4]+0x38C]

在这里插入图片描述

rcx来源于r8+rax*4

[[r8+rax*4+0x4]+0x38C]

继续追r8

在这里插入图片描述

r8来源于[rbp+0x130]

在这里插入图片描述

[rbp+0x130]是一个数组,我们来追踪这个数组的来源

在这里插入图片描述

往上找引用[rbp+0x130]的位置,发现这里会往这个地址循环写入值

在这里插入图片描述

每一次进来都会写入一个,进入call内单步跟踪,看他什么时候往里面写值

在这里插入图片描述

当代码执行到这里将对象写入到数组,这里要追rax来源,rax来源于[rbp+0x4]

在这里插入图片描述

rbp来源于r8

在这里插入图片描述

r8是上层call的参数,也就是eax和rdx

在这里插入图片描述

然后根据这一段代码整理

ID=r8+14*n

在这里插入图片描述

r8来源于[rax],来源于[rsp+0x28],而rax此时是一个基地址,继续往上找到来源

在这里插入图片描述

[rsp+0x28]来源于rbx

在这里插入图片描述

rbx来源于rax

在这里插入图片描述

rax来源于rcx+0x1E8

在这里插入图片描述

rcx来源于基地址

数据整理

偏移:0x2F783A4
[0x00007FF7035083A4+0x1E8]+n*14 技能ID
[0x00007FF7035083A4+0x1E8]+n*14+4 技能对象
[[[0x00007FF7035083A4+0x1E8]+n*14+4]+0x38C]+0 技能名字
[[0x00007FF7035083A4+0x1E8]+n*14+4]+0x74 技能等级 DWORD
[[0x00007FF7035083A4+0x1E8]+n*14+4]+0x3E0 技能最大等级 DWORD

代码编写

接着来编写技能遍历的代码,同样在stu.h中新增技能对象相关的字段

	//--------------------------------技能------------------------------------------------
	BOOL  m_Skill_Level;		//技能等级
	BOOL  m_Skill_MaxLevel;		//最大等级

接着在GameData.h中新增一个函数

//技能遍历
_stuObjs GetSkillData();

数组的遍历相对来说比较简单,只需要一个函数即可。

//技能遍历
_stuObjs GetSkillData()
{
	_stuObjs skilllist;

	//技能数组首地址
	QWORD qSkillArr = ReadQword(g_GameAddr + SkillArray + 0x1E8);

	//数组大小
	DWORD dwSize = ReadDword(g_GameAddr + SkillArray + 0x1E8 + 0x8);

	//开始遍历
	for (unsigned int i = 0; i < dwSize; i++)
	{
		_stuObj skill;
		skill.m_StuType = Em_Skill;

		//ID
		skill.m_ID = ReadDword(qSkillArr + i * 0x14);

		//对象
		skill.m_Obj = ReadDword(qSkillArr + i * 0x14 + 0x4);

		//等级
		skill.m_Skill_Level = ReadDword(skill.m_Obj + 0x74);

		//最大等级
		skill.m_Skill_MaxLevel = ReadDword(skill.m_Obj + 0x3E0);

		//名字
		DWORD  nameaddr = ReadDword(skill.m_Obj + 0x38C);
		skill.m_Name = ReadWChar(nameaddr);

		//保存
		skilllist.m_data.push_back(skill);
	}

	return skilllist;
}

然后输出技能相关的信息

		//输出技能信息
		case Em_Skill:
		{
			__OutputDebugStringW(L"对象:%x ID:%x 名字:%s 等级:%d 最大等级:%d"
				, m_Obj, m_ID, m_Name.c_str(), m_Skill_Level, m_Skill_MaxLevel);
		}
		break;

实际效果如图:
在这里插入图片描述

下一篇文章我们来找明文封包call。

Github:https://github.com/TonyChen56/GameReverseNote

完整代码:https://download.csdn.net/download/qq_38474570/79498815

【课程简介】本课程为任鸟飞逆向C++高级篇,注重在逆向中运用的技巧思维逻辑,掌握后相关工具与手法可以熟练运用,在反汇编的世界里如鱼得水。 本套课程不只是一套深入学习C++的课程,更是一套深入学习汇编逆向课程、外挂与反外挂、软件安全的课程。 逆向思路技术随笔,请关注我的CSDN博客:https://blog.csdn.net/qq_36553941 欢迎大家来学习交流,活动折扣咨询等请在博客私聊我。 PS: 课程中工具包、源码、课件请关注第一章的第一节的随课课件,工欲望善其事,必先利其器! 【学前预备知识】任鸟飞逆向C++系列课程是一条精心安排为掌握汇编逆向、外挂与反外挂、软件安全以及软件编程的学习路线,包括但不限于 基础篇、进阶篇、高级篇(本篇)、实战篇等,所以为保证您能学有所成请在学习本篇之前务必掌握基础篇与进阶篇!!! 基础篇CSDN学院链接:https://edu.csdn.net/course/detail/30509进阶篇CSDN学院链接:https://edu.csdn.net/course/detail/30680 【学员学成收获】认真学习并练习后将掌握:1、熟练游戏逆向思想与技巧。2、熟练通用辅助程序设计。3、熟练诸多逆向工具使用。4、熟练常见数据结构逆向分析。5、熟悉智能主线脚本编写。 
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

鬼手56

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值