尼桑 发表于 2020-2-14 08:22

修改某Unity游戏实现飞行等功能

本帖最后由 尼桑 于 2020-2-15 09:51 编辑

此为新人教程,大佬请飘走,实在要看就别喷{:301_999:}
(看不懂也评个分呗,情人节快乐!)
下一篇帖子:https://www.52pojie.cn/thread-1105080-1-1.html
0x00 前言----------------------------------------------
最近在Stexx上发现了一个好玩的游戏,但我这种手残党实在是玩不下去,于是就准备修改一下。看了一看它的游戏目录,明显就是Unity写的游戏(不知道Unity的自行百度)
Unity的游戏代码其实并不在软件里面,而是在 xxxxxxUnity游戏/xxx_data/Managed/Assembly-CSharp.dll和Assembly-CSharp-firstpass.dll里面
但是Assembly-CSharp-firstpass.dll基本不用,所以就只修改Assembly-CSharp.dll就可以了
0x01 工具----------------------------------------------
游戏 X 1
DnSpy 6.0.1 X 1
0x02 DnSpy简单介绍----------------------------------------------
DnSpy是一款.net程序反编译工具,可以对net程序进行反编译,还有替代库文档的功能,如果遇到了代码丢失或者损坏的情况,可以直接恢复。(摘自百度)
我说它是神器完全不为过,因为它可以反编译.NET代码,而且可以修改,这对我们这种不懂IL指令的小白来说是一个巨大的福利!
(唯一有点不好的地方就是它比较吃内存,要占500~800MB内存,但即使这样,利还是远远大于弊的)
DnSpy可以通过爱盘下载,不大,就20多MB
链接:https://down.52pojie.cn/Tools/NET/dnSpy.zip
0x03 修改过程----------------------------------------------
0x0301 飞行
打开DnSpy,把游戏的Assembly-CSharp.dll拖进DnSpy(有的要用x64位的,有的要用x32位(x86位)的,具体看情况)
大概是这样:

右面会加载一大堆Unity的模块
点击Assembly-CSharp.dll
我们想让他飞行,我的思路是:把跳跃的代码修改一下,让它可以多段跳,就相当于飞行了。(就是无限地在空中跳)
既然是跳跃,就肯定要找关于跳跃的东西
(下面的内容需要面向对象级别的编程或是C#编程基础)
点击搜索,搜索“jump”方法
出来很多结果
其中有两个方法名是JumpAnimation(直译就是跳跃动画,但我感觉应该是跳跃动作)
先去第一个看看:
      private Vector3 JumpAnimation()
      {
                float lift = 1f;
                return this.ApplyTorsoPose(1f, 1f, 0f, lift);
      }
这个方法是TorsoMuscles类的方法   (机翻:躯干肌肉)
太短了,肯定不是
而且跳跃是用腿,不是用躯干
再去下一个:
private void JumpAnimation(Vector3 torsoFeedback)
      {
                this.ragdoll.partHips.rigidbody.SafeAddForce(torsoFeedback, ForceMode.Force);
                if (this.human.jump)
                {
                        float num = 0.75f;
                        int num2 = 2;
                        float num3 = Mathf.Sqrt(2f * num / Physics.gravity.magnitude);
                        float num4 = Mathf.Clamp(this.human.groundManager.groudSpeed.y, 0f, 100f);
                        num4 = Mathf.Pow(num4, 1.2f);
                        num3 += num4 / Physics.gravity.magnitude;
                        float num5 = num3 * this.human.weight;
                        float num6 = this.human.controls.unsmoothedWalkSpeed * ((float)num2 + num4 / 2f) * this.human.mass;
                        Vector3 momentum = this.human.momentum;
                        float num7 = Vector3.Dot(this.human.controls.walkDirection.normalized, momentum);
                        if (num7 < 0f)
                        {
                              num7 = 0f;
                        }
                        this.upImpulse = num5 - momentum.y;
                        if (this.upImpulse < 0f)
                        {
                              this.upImpulse = 0f;
                        }
                        this.forwardImpulse = num6 - num7;
                        if (this.forwardImpulse < 0f)
                        {
                              this.forwardImpulse = 0f;
                        }
                        this.framesToApplyJumpImpulse = 1;
                        if (this.human.onGround || Time.time - this.human.GetComponent<Ball>().timeSinceLastNonzeroImpulse < 0.2f)   //这是判断人是否在地面上,以及延时是否够
                        {
                              this.upImpulse /= (float)this.framesToApplyJumpImpulse;                               //if块里面的应该就是执行跳跃的代码了
                              this.forwardImpulse /= (float)this.framesToApplyJumpImpulse;
                              this.ApplyJumpImpulses();
                              this.framesToApplyJumpImpulse--;
                        }
                        this.human.skipLimiting = true;
                        this.human.jump = false;
                }
                else
                {
                        if (this.framesToApplyJumpImpulse-- > 0)
                        {
                              this.ApplyJumpImpulses();
                        }
                        int num8 = 3;
                        int num9 = 500;
                        float num10 = this.human.controls.unsmoothedWalkSpeed * (float)num8 * this.human.mass;
                        Vector3 momentum2 = this.human.momentum;
                        float num11 = Vector3.Dot(this.human.controls.walkDirection.normalized, momentum2);
                        float num12 = num10 - num11;
                        float d = Mathf.Clamp(num12 / Time.fixedDeltaTime, 0f, (float)num9);
                        this.ragdoll.partChest.rigidbody.SafeAddForce(d * this.human.controls.walkDirection.normalized, ForceMode.Force);
                }
      }
这个应该是了
它是LegMuscles类的一个方法(机翻:腿部肌肉)
可以看出有一个if判断人是否在地上,以及跳跃延迟是否够
我们把它改成if(true)试试
右键---编辑类


开游戏试一下,不行。
为什么?因为这个JumpAnimation方法不是只要跳跃键按下就执行的,所以,我们要找其他思路
human.onGround有点可疑,因为游戏肯定会先判断玩家是否在地面上才会执行JumpAnimation这个方法
它是Human类里面的一个字段
我们在Human类搜索一下human.onGround
搜到了一个赋值操作
this.onGround = (this.groundDelay <= 0f && this.groundManager.onGround);
在FixedUpdate()方法里面
把它后面的 (this.groundDelay <= 0f && this.groundManager.onGround);改成true试试
再开游戏,这次成功了:

{你们应该知道这是什么游戏了)
直接飞到终点,很过瘾
0x0302 修改力量,重量,重力等属性
先搜索力量
搜索Force字段名:

出来了好多结果。。。
先点maxPushForce吧

这是HandMuscles类的字段   (机翻:手部肌肉)
所以有很多可以改的力量的参数
右键---修改类 就可以了
0x0303 设置飞行开关
这个游戏自带一个控制台
按“·”打开(ESC下面的按键)
那我们就搜索Command这个类
结果没有有用的结果
突然想起来这个游戏的控制台也可以叫作弊码输入
搜索CheatCode试试
搜到了

果然,就是控制台的代码
在Start()方法里面有很多命令的注册

我们也写一个
Shell.RegisterCommand("fly",new Action(this.fly),null);
添加fly方法:
private void fly()
{
//暂时留空
}
先留空,之后写
我们先再去到Human这个类
添加fly字段
public static bool fly;      //注意必须是public static
在前面的onGround赋值操作中,改一下代码:
this.onGround = (fly ? true : (this.groundDelay <= 0f && this.groundManager.onGround));
现在可以补全CheatCode.fly()方法了
private void fly()
{
    Human.fly = ! Human.fly;
    if (Human.fly)
    {
      Shell.Print("fly mode on");
    }
    else
    {
      Shell.Print("fly mode off");
    }
}
在游戏内打开控制台,输入fly就可以开关飞行模式(不是你手机上的那个飞行模式....)
0x0304 修改跳跃高度
既然是跳跃高度,那就要回到LegMuscles类的JumpAnimation方法
再贴上代码:
private void JumpAnimation(Vector3 torsoFeedback)
      {
                this.ragdoll.partHips.rigidbody.SafeAddForce(torsoFeedback, ForceMode.Force);
                if (this.human.jump)
                {
                        float num = 0.75f;
                        int num2 = 2;
                        float num3 = Mathf.Sqrt(2f * num / Physics.gravity.magnitude);
                        float num4 = Mathf.Clamp(this.human.groundManager.groudSpeed.y, 0f, 100f);
                        num4 = Mathf.Pow(num4, 1.2f);
                        num3 += num4 / Physics.gravity.magnitude;
                        float num5 = num3 * this.human.weight;
                        float num6 = this.human.controls.unsmoothedWalkSpeed * ((float)num2 + num4 / 2f) * this.human.mass;
                        Vector3 momentum = this.human.momentum;
                        float num7 = Vector3.Dot(this.human.controls.walkDirection.normalized, momentum);
                        if (num7 < 0f)
                        {
                              num7 = 0f;
                        }
                        this.upImpulse = num5 - momentum.y;
                        if (this.upImpulse < 0f)
                        {
                              this.upImpulse = 0f;
                        }
                        this.forwardImpulse = num6 - num7;
                        if (this.forwardImpulse < 0f)
                        {
                              this.forwardImpulse = 0f;
                        }
                        this.framesToApplyJumpImpulse = 1;
                        if (this.human.onGround || Time.time - this.human.GetComponent<Ball>().timeSinceLastNonzeroImpulse < 0.2f)   //这是判断人是否在地面上,以及延时是否够
                        {
                              this.upImpulse /= (float)this.framesToApplyJumpImpulse;                               //if块里面的应该就是执行跳跃的代码了
                              this.forwardImpulse /= (float)this.framesToApplyJumpImpulse;
                              this.ApplyJumpImpulses();
                              this.framesToApplyJumpImpulse--;
                        }
                        this.human.skipLimiting = true;
                        this.human.jump = false;
                }
                else
                {
                        if (this.framesToApplyJumpImpulse-- > 0)
                        {
                              this.ApplyJumpImpulses();
                        }
                        int num8 = 3;
                        int num9 = 500;
                        float num10 = this.human.controls.unsmoothedWalkSpeed * (float)num8 * this.human.mass;
                        Vector3 momentum2 = this.human.momentum;
                        float num11 = Vector3.Dot(this.human.controls.walkDirection.normalized, momentum2);
                        float num12 = num10 - num11;
                        float d = Mathf.Clamp(num12 / Time.fixedDeltaTime, 0f, (float)num9);
                        this.ragdoll.partChest.rigidbody.SafeAddForce(d * this.human.controls.walkDirection.normalized, ForceMode.Force);
                }
      }
经过简单的分析,可以看出ApplyJumpImpulses()这个方法就是执行跳跃的具体方法
再贴上它的代码:
private void ApplyJumpImpulses()
      {
                float d = 1f;
                for (int i = 0; i < this.human.groundManager.groundObjects.Count; i++)
                {
                        if (this.human.grabManager.IsGrabbed(this.human.groundManager.groundObjects))
                        {
                              d = 0.75f;
                        }
                }
                Vector3 a = Vector3.up * this.upImpulse * d;
                Vector3 a2 = this.human.controls.walkDirection.normalized * this.forwardImpulse * d;
                this.ragdoll.partHead.rigidbody.SafeAddForce(a * 0.1f + a2 * 0.1f, ForceMode.Impulse);
                this.ragdoll.partChest.rigidbody.SafeAddForce(a * 0.1f + a2 * 0.1f, ForceMode.Impulse);
                this.ragdoll.partWaist.rigidbody.SafeAddForce(a * 0.1f + a2 * 0.1f, ForceMode.Impulse);
                this.ragdoll.partHips.rigidbody.SafeAddForce(a * 0.1f + a2 * 0.1f, ForceMode.Impulse);
                this.ragdoll.partBall.rigidbody.SafeAddForce(a * 0.1f + a2 * 0.1f, ForceMode.Impulse);
                this.ragdoll.partLeftThigh.rigidbody.SafeAddForce(a * 0.05f + a2 * 0.05f, ForceMode.Impulse);
                this.ragdoll.partRightThigh.rigidbody.SafeAddForce(a * 0.05f + a2 * 0.05f, ForceMode.Impulse);
                this.ragdoll.partLeftLeg.rigidbody.SafeAddForce(a * 0.05f + a2 * 0.05f, ForceMode.Impulse);
                this.ragdoll.partRightLeg.rigidbody.SafeAddForce(a * 0.05f + a2 * 0.05f, ForceMode.Impulse);
                this.ragdoll.partLeftFoot.rigidbody.SafeAddForce(a * 0.05f + a2 * 0.05f, ForceMode.Impulse);
                this.ragdoll.partRightFoot.rigidbody.SafeAddForce(a * 0.05f + a2 * 0.05f, ForceMode.Impulse);
                this.ragdoll.partLeftArm.rigidbody.SafeAddForce(a * 0.05f + a2 * 0.05f, ForceMode.Impulse);
                this.ragdoll.partRightArm.rigidbody.SafeAddForce(a * 0.05f + a2 * 0.05f, ForceMode.Impulse);
                this.ragdoll.partLeftForearm.rigidbody.SafeAddForce(a * 0.05f + a2 * 0.05f, ForceMode.Impulse);
                this.ragdoll.partRightForearm.rigidbody.SafeAddForce(a * 0.05f + a2 * 0.05f, ForceMode.Impulse);
                this.human.groundManager.DistributeForce(-a / Time.fixedDeltaTime, this.ragdoll.partBall.rigidbody.position);
      }
d这个变量很可疑,我们把它改成100f试试
再进游戏
结果跳一下直接上天了
所以只要修改d就行了,这里不再详细说了
0x0305 保存
点击DnSpy左上角文件---保存模块就行了

0x04 DnSpy的一些坑

-----------------------1.占内存太大了。。。。2.有的时候加入一个int i = 0;都会报错,还需要导入模块才行3.自动补全不太好用,有时候你明明在另一个类里定义了public static int i = 0;,但在另一个类里 "一个类.i = 1" 会报错,要保存模块才行4.代码分析有点奇怪,应该是编译器的问题,比如说写 "if(a == b){}" DnSpy反编译出来是"a == b;"虽然是这样,但这都是小问题,我还是强烈推荐小白下载!

0x05 小结
-----------------------
.NET程序修改破解小白首推DnSpy,IL指令大佬就用其他工具吧
用DnSpy修改破解只要会一点Java或者C#就能比较轻松地修改破解
(Java和C#基本一样,但也有不同的地方)用DnSpy破解修改主要思路就是:找关键方法或者字符串,静态分析,注册码这一类的可以动态分析然后就用DnSpy的修改类或者是修改方法功能修改代码但前提是dll没被加壳加壳就麻烦了0x06 最后----------------------------------------------我这个其实修改的不全,只修改了一部分,还有很多可以修改的地方,大家有兴趣可以自己修改最后给那些找不到Assembly-CSharp.dll或不想下载游戏的人奉上Assembly-CSharp.dll原版解压密码:www.52pojie.cn声明:您必须在下载后的24个小时之内,从您的电脑中彻底删除上述内容。如果您喜欢该程序,请支持正版软件,购买注册,得到更好的正版服务。

尼桑 发表于 2020-2-14 09:44

评个分呗~~~~{:301_997:}

Aurelion 发表于 2020-2-14 11:14

这游戏我以前也搞过弄了一个高跳发现很奇怪 只有我自己开的房间才可以生效   而且开了之后房间内所有成员都可以跟我一样 蹦的很高至今仍然有效

尼桑 发表于 2020-2-14 09:59

本帖最后由 尼桑 于 2020-2-14 10:03 编辑

楞枷山人 发表于 2020-2-14 09:57
请问一下楼主 对软件进行爆破反编译 使用的是什么技术 更改完之后是编译一个dll文件直接覆盖就行了吗?
哦,这部分忘记写了,更改完之后点击DnSpy左上角文件---保存模块就行了

已经补上了

致yue 发表于 2020-2-14 08:43

沙发   标识看不懂略过

lyw8614505 发表于 2020-2-14 08:45

谢谢分享教程

秋海明月 发表于 2020-2-14 08:46

不错,谢谢分享

hbwazxf 发表于 2020-2-14 08:50

不错,谢谢分享

縈默A 发表于 2020-2-14 08:52

看了一下截图,没有认出这是什么游戏。。所以说这是什么游戏?

tjk518 发表于 2020-2-14 08:52

牛逼,感谢分享。这还是小白,大佬玩笑了

尼桑 发表于 2020-2-14 08:55

縈默A 发表于 2020-2-14 08:52
看了一下截图,没有认出这是什么游戏。。所以说这是什么游戏?

SHVtYW4lMjBGYWxsJTIwRmxhdA==(base64解密,自己百度)

雨夜故园 发表于 2020-2-14 08:57

hmlhao 发表于 2020-2-14 09:08

感谢楼主分享。。。。
页: [1] 2 3 4 5
查看完整版本: 修改某Unity游戏实现飞行等功能