开启辅助访问 切换到宽版

精易论坛

 找回密码
 注册

QQ登录

只需一步,快速开始

用微信号发送消息登录论坛

新人指南 邀请好友注册 - 我关注人的新帖 教你赚取精币 - 每日签到


求职/招聘- 论坛接单- 开发者大厅

论坛版规 总版规 - 建议/投诉 - 应聘版主 - 精华帖总集 积分说明 - 禁言标准 - 有奖举报

查看: 543|回复: 6
收起左侧

[技术文章] 《游戏逆向》大侠立志传逆向分析 人物篇

[复制链接]
发表于 2024-11-25 13:36:11 | 显示全部楼层 |阅读模式   湖北省随州市
本帖最后由 FerryMikey 于 2024-11-25 13:43 编辑

血量是否必存在于人物类中? 本篇文章将带来 il2cpp《大侠立志传》人物属性的逆向分析!





游戏简介:

《大侠立志传》是一款开放世界武侠RPG游戏,更是一款像素版江湖生存模拟器,站在一个初出茅庐的市井小人物视角,还原在江湖底层摸爬滚打最终脱颖而出的逆袭经历。
游戏平台:Steam
发行日期:2023 年 11 月 16 日
游戏价格:¥ 41.40
游戏引擎:Unity il2cpp





准备阶段:

所需工具:il2cppDumper 、CheatEngine、DnSpy

运行il2cppDumper(不需要启动游戏) 后通过对话框分别把游戏的两个文件载入

文件1:WulinSH\GameAssembly.dll

文件2:WulinSH\Wulin_Data\il2cpp_data\Metadata\global-metadata.dat

dump完成后 找到 Il2CppDumper\bin\Debug\net6.0\DummyDll\Assembly-CSharp.dll
把它拖到DnSpy中解析









实战开始:

默认程序集(-)中没看到太多有用的信息  并且游戏的进程名为 WuLin 所以我们开始探索(WuLin)程序集




我们起初肯定是搜索Player相关的类 然后发现了  (BattleActor) 里面有很多战斗相关的字段与函数,比如 UseItem这个函数(顺带看一下)他有三个参数 都很值得关注

参数 1:gameItemInstance 猜测为物品对象

参数 2:BattleActor  猜测为使用者 (caster施法者)

参数 3:count 猜测为使用数量或次数GameItemInstance 大概扫了一眼,确实应该是物品类但是我们留到后面再研究 物品相关

[C++] 纯文本查看 复制代码
public void UseItem(GameItemInstance gameItemInstance, BattleActor caster, int count = 1)
{

}


观察了一下BattleActor  类,其中有很多有意思的函数与变量总结到单独文档中数据_人物战斗属性

其中我们尤为关心的可能是血量 能量等基础常用的值,通过游览可以发现 有个函数引起了我的注意从娘胎里就开始逆游戏的我们一眼就可以看到这个函数 healhealth 是生命而heal是治疗的意思,很多游戏治疗函数都是用的这个名字

其中有三个参数

参数1:hp  猜测为治疗的血量值

参数2:ep  猜测为治疗的能量值

参数3:[Optional] BattleActor caster  猜测为治疗的对象 而且有 Optional 属性Optional :这是一个可选参数,可能为空(`null`)

第三个参数 为什么有个可空属性呢 我猜测可能是caster  ==null 则治疗本身

[C++] 纯文本查看 复制代码
public void Heal(int hp, int ep, [Optional] BattleActor caster)
{

}


现在问题又来了我们观察了BattleActor 类 但是我们并没能发现 hp相关的成员变量
而BattleActor 类中却有一个成员函数可以 增加血量!

猜测BattleActor 的基类中可能包含 人物基础属性,或者在hp可能被包含在复合对象中
(attleActor 类可能通过组合其他类或结构来管理健康值)

基类中包含基础属性
[C++] 纯文本查看 复制代码
public class Actor
{
  int hp;
  int ep;
  int lv;
  //..........
}

public class BattleActor : Actor
{

}


通过组合其他类或结构来管理基础属性
[C++] 纯文本查看 复制代码
public class Attribute
{
  int hp;
  int ep;
  int lv;
  //..........
}

public class BattleActor
{

  Attribute ActorAttribute;

}


经过对BattleActor 的分析我们不难看出,BattleActor 没有继承其他复杂的类所以第一种情况排除
然后我们在BattleActor 中看到了一个类BattleActorProp 这个类直译是战斗演员的道具,

但是很多时候这个类表示属性合集所以我们仔细观察这个BattleActorProp类中是否有我们想要的字段!
其中也没有我们关心的血量能量等字段,那BattleActor 中的heal函数到底是如何实现的呢?

绝对还是有说法的!再仔细观察 我们发现其中有几个函数比较可疑

Getprop 获取属性

Setprop 设置属性

他传进来的参数是 BattleActorPropTypes的枚举类型 从而进行 Get 与Set
其中Get返回 Int ,Set无返回值

猜测可能是类似字典的结构中存储的这些字段,通过Key 获取 或者设置 而 BattleActorPropTypes
就是对应的Key


我们找到枚举 BattleActorPropTypes 确实有很多人物基础属性的枚举

原版
[C++] 纯文本查看 复制代码
public enum BattleActorPropTypes
{
  Hp = 1,
  HpMax,
  Ep,
  EpMax,
  NegPoison = 100,
  NegInjure,
  NegSeal,
  NegBleed,
  NegBlind,
  AccuDef = 200,
  AccuAtk,
  AccuDefMax = 203,
  BattleWine = 300,
  BattleMedicine
}


标注版
[C++] 纯文本查看 复制代码
public enum BattleActorPropTypes
{
    Hp = 1,               // 生命值 (Health Points)
    HpMax = 2,            // 最大生命值 (Maximum Health Points)
    Ep = 3,               // 能量值 (Energy Points)
    EpMax = 4,            // 最大能量值 (Maximum Energy Points)
    NegPoison = 100,      // 毒抗性 (Poison Resistance)
    NegInjure = 101,      // 伤害抗性 (Injury Resistance)
    NegSeal = 102,        // 封印抗性 (Seal Resistance)
    NegBleed = 103,       // 流血抗性 (Bleeding Resistance)
    NegBlind = 104,       // 失明抗性 (Blindness Resistance)
    AccuDef = 200,        // 防御精确度 (Accuracy for Defense)
    AccuAtk = 201,        // 攻击精确度 (Accuracy for Attack)
    AccuDefMax = 203,     // 最大防御精确度 (Maximum Defense Accuracy)
    BattleWine = 300,     // 战斗酒状态 (Battle Wine Status)
    BattleMedicine = 301  // 战斗药品状态 (Battle Medicine Status)
}



那我们怎么验证呢?我们先找到 SetProp的函数地址(这里可以通过DnSpy 或者 Mono插件去定位)

然后我们在SetProp函数地址处下断!

这里我们思考一下什么动作可能会导致SetProp断下,其实很简单改变以上所有属性都很有可能通过SetProp 函数去执行,由于他封装了这样的函数所以battleProps[key] += value; 直接通过这种方式改变某属性的值就很不科学,我们通过吃药增加血量发现无法再改函数处断下。

后面考虑BattleActor 应该是战斗对象 ,所以我们在战斗中吃药确实断下了

并且当我们攻击怪物,或者受到怪物攻击 也都断下了

这里我们可以获取到的信息是战斗中的怪物对象也都是BattleActor 类型的。

甚至我们后期可以对这里HOOK 判断如果是怪物受到攻击 让他的血量-9999999 这样的话就可以实现秒杀效果了


这里我们在战斗中吃药(增加生命的),然后来分析函数参数

[C++] 纯文本查看 复制代码
public void SetProp(BattleActor.BattleActorPropTypes key, int value)


基于函数原型的话

RDX应该是传入的Key

R8   应该是更新的Value

断下后RDX==0x1 (对应枚举表应该是Hp的索引) R8==0xAA(170)

断点放开后确实生命值变成了170



由于怪物的血量较少 正常攻击也是一击致命 所以我们测试通过怪物攻击我们  让SetSetProp 实现怪物秒杀玩家的效果。

RDX==1  R8==0x21C 这里我们直接把R8改成0然后运行 可以发现玩家直接被怪物秒杀

相反我们也可以利用此手段直接去秒杀怪物









总结:


游戏整体逻辑相对简单,但是也需要大家有一定的分析经验。其中需要我们对C#语法、 il2cppDumper 、Dnspy Mono插件等 熟练掌握。很多时候我们关心的并不仅仅是某个单一的数据,而是基于某个数据的发散联系与拓展,更是对整个游戏逻辑的理解与分析。
其中人物的战斗属性通过隐式字典存储,这是本篇文章的唯一难点!

后面有机会可以教大家,如何使用类似Mono注入的方式编写il2cpp的游戏插件与Mod!

如果对此类游戏感兴趣,请点赞评论!后面我们会针对评论区留言,发布相关游戏的逆向文章!





本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x
结帖率:100% (1/1)

签到天数: 18 天

发表于 2024-12-14 21:54:38 | 显示全部楼层   河北省张家口市
感谢分享,很给力!~
回复 支持 反对

使用道具 举报

结帖率:100% (1/1)

签到天数: 18 天

发表于 2024-12-14 02:01:23 | 显示全部楼层   河北省张家口市
支持~!感谢分享
回复 支持 反对

使用道具 举报

 楼主| 发表于 2024-11-25 19:40:55 高大上手机用户 | 显示全部楼层   吉林省长春市
本帖最后由 FerryMikey 于 2024-11-25 19:56 编辑
无极超哥 发表于 2024-11-25 14:13
这是不是共用代码,怎么判断是玩家还是敌人呢?
问题1:这是不是共用代码?
注意看我写的这句话
"并且当我们攻击怪物,或者收到怪物攻击 也都断下了
这里我们可以获取到的信息是战斗中的怪物对象也都是BattleActor 类型的。"
这里可以很明显的确定是公共代码!

问题2:怎么判断是玩家还是敌人呢?
虽然是相同的类,但是在类中必然存在区分不同实例的字段,因为游戏本身在很多情况下也需要区分!
玩家与敌人虽然是相同的类,但是其属性或特点一定在某些方面有区别。
当我在总结BattleActor类成员的时候发现了,isAI 这个成员变量,也许可以通过它来判断,但是我并未进行测试!
当然你也可以利用CheatEngine进行动态的数据的比对!


回复 支持 反对

使用道具 举报

结帖率:93% (223/240)

签到天数: 14 天

发表于 2024-11-25 16:13:07 | 显示全部楼层   上海市上海市
无极超哥 发表于 2024-11-25 14:13
这是不是共用代码,怎么判断是玩家还是敌人呢?

这种搬运工,你问他   他懂个毛
回复 支持 反对

使用道具 举报

结帖率:98% (39/40)

签到天数: 17 天

发表于 2024-11-25 14:13:23 | 显示全部楼层   广东省佛山市
这是不是共用代码,怎么判断是玩家还是敌人呢?
回复 支持 反对

使用道具 举报

结帖率:100% (3/3)

签到天数: 16 天

发表于 2024-11-25 13:47:01 | 显示全部楼层   河南省驻马店市
厉害了
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则 致发广告者

发布主题 收藏帖子 返回列表

sitemap| 易语言源码| 易语言教程| 易语言论坛| 易语言模块| 手机版| 广告投放| 精易论坛
拒绝任何人以任何形式在本论坛发表与中华人民共和国法律相抵触的言论,本站内容均为会员发表,并不代表精易立场!
论坛帖子内容仅用于技术交流学习和研究的目的,严禁用于非法目的,否则造成一切后果自负!如帖子内容侵害到你的权益,请联系我们!
防范网络诈骗,远离网络犯罪 违法和不良信息举报电话0663-3422125,QQ: 793400750,邮箱:wp@125.la
网站简介:精易论坛成立于2009年,是一个程序设计学习交流技术论坛,隶属于揭阳市揭东区精易科技有限公司所有。
Powered by Discuz! X3.4 揭阳市揭东区精易科技有限公司 ( 粤ICP备12094385号-1) 粤公网安备 44522102000125 增值电信业务经营许可证 粤B2-20192173

快速回复 返回顶部 返回列表