吾爱破解 - LCG - LSG |安卓破解|病毒分析|www.52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 8977|回复: 45
收起左侧

[.NET逆向] 修改某Unity游戏实现飞行等功能

  [复制链接]
尼桑 发表于 2020-2-14 08:22
本帖最后由 尼桑 于 2020-2-15 09:51 编辑

此为新人教程,大佬请飘走,实在要看就别喷
(看不懂也评个分呗,情人节快乐!)
下一篇帖子: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位)的,具体看情况)
大概是这样:
image.png
右面会加载一大堆Unity的模块
点击Assembly-CSharp.dll
我们想让他飞行,我的思路是:把跳跃的代码修改一下,让它可以多段跳,就相当于飞行了。(就是无限地在空中跳)
既然是跳跃,就肯定要找关于跳跃的东西
(下面的内容需要面向对象级别的编程或是C#编程基础)
点击搜索,搜索“jump”方法
出来很多结果
其中有两个方法名是JumpAnimation(直译就是跳跃动画,但我感觉应该是跳跃动作)
先去第一个看看:
[C#] 纯文本查看 复制代码
        private Vector3 JumpAnimation()
        {
                float lift = 1f;
                return this.ApplyTorsoPose(1f, 1f, 0f, lift);
        }

这个方法是TorsoMuscles类的方法   (机翻:躯干肌肉)
太短了,肯定不是
而且跳跃是用腿,不是用躯干
再去下一个:
[C#] 纯文本查看 复制代码
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)试试
右键---编辑类
截图32.png
捕获33.PNG
开游戏试一下,不行。
为什么?因为这个JumpAnimation方法不是只要跳跃键按下就执行的,所以,我们要找其他思路
human.onGround有点可疑,因为游戏肯定会先判断玩家是否在地面上才会执行JumpAnimation这个方法
它是Human类里面的一个字段
我们在Human类搜索一下human.onGround
搜到了一个赋值操作
[C#] 纯文本查看 复制代码
this.onGround = (this.groundDelay <= 0f && this.groundManager.onGround);

在FixedUpdate()方法里面
把它后面的 (this.groundDelay <= 0f && this.groundManager.onGround);改成true试试
再开游戏,这次成功了:
新建位图图像 (4).gif
{你们应该知道这是什么游戏了)
直接飞到终点,很过瘾
0x0302 修改力量,重量,重力等属性
先搜索力量
搜索Force字段名:
捕获35.PNG
出来了好多结果。。。
先点maxPushForce吧
捕获36.PNG
这是HandMuscles类的字段   (机翻:手部肌肉)
所以有很多可以改的力量的参数
右键---修改类 就可以了
0x0303 设置飞行开关
这个游戏自带一个控制台
按“·”打开(ESC下面的按键)
那我们就搜索Command这个类
结果没有有用的结果
突然想起来这个游戏的控制台也可以叫作弊码输入
搜索CheatCode试试
搜到了
捕获37.PNG
果然,就是控制台的代码
在Start()方法里面有很多命令的注册
捕获38.PNG
我们也写一个
[C#] 纯文本查看 复制代码
Shell.RegisterCommand("fly",new Action(this.fly),null);

添加fly方法:
[C#] 纯文本查看 复制代码
private void fly()
{
//暂时留空
}

先留空,之后写
我们先再去到Human这个类
添加fly字段
[C#] 纯文本查看 复制代码
public static bool fly;      //注意必须是public static

在前面的onGround赋值操作中,改一下代码:
[C#] 纯文本查看 复制代码
this.onGround = (fly ? true : (this.groundDelay <= 0f && this.groundManager.onGround));

现在可以补全CheatCode.fly()方法了
[C#] 纯文本查看 复制代码
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方法
再贴上代码:
[C#] 纯文本查看 复制代码
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()这个方法就是执行跳跃的具体方法
再贴上它的代码:
[C#] 纯文本查看 复制代码
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[i]))
                        {
                                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
Assembly-CSharp.rar (649.7 KB, 下载次数: 29)
声明:您必须在下载后的24个小时之内,从您的电脑中彻底删除上述内容。如果您喜欢该程序,请支持正版软件,购买注册,得到更好的正版服务。

免费评分

参与人数 18吾爱币 +18 热心值 +14 收起 理由
行者悠然 + 1 谢谢@Thanks!
葫芦里的小姐姐 + 1 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
huilight + 1 + 1 我很赞同!
qianxian + 1 + 1 我很赞同!
wwr2128 + 1 + 1 用心讨论,共获提升!
一只小刀妹 + 1 很可以,666
15693461001 + 1 + 1 谢谢@Thanks!
我爱IU + 1 + 1 谢谢@Thanks!
CrazyNut + 2 + 1 欢迎分析讨论交流,吾爱破解论坛有你更精彩!
hc11259375 + 1 + 1 谢谢@Thanks!
15602366980 + 1 热心回复!
growuphappily + 1 + 1 我很赞同!
TzzOve + 1 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
oranges + 1 + 1 我记得当初我改的时候空格直接飞,好像是改了跳跃判断,如果自己开房间,一.
XhyEax + 1 我很赞同!
xyaxy0001 + 1 666
zncliving + 1 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
yzlovew + 1 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!

查看全部评分

本帖被以下淘专辑推荐:

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

 楼主| 尼桑 发表于 2020-2-14 09:44
评个分呗~~~~
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
感谢楼主分享。。。。
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则 警告:本版块禁止灌水或回复与主题无关内容,违者重罚!

快速回复 收藏帖子 返回列表 搜索

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-4-20 09:54

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

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