July 30, 2024
Views : 👀

Unity出题-逆向思路篇

本篇文章已上传至bilibili【第玖期 REVERSE 分享会】直播录屏,空降50分钟可以观看讲解视频,题目讲解过程就不放在博客文章中了

https://www.bilibili.com/video/BV1U7igeZE5u/?spm_id_from=333.999.0.0

前言——unity相关基础

unity引擎与游戏文件

unity是一款游戏引擎,可以开发多平台,多系统下的2D 3D游戏,游戏平台上的一些小游戏,或者像我们熟悉的手游王者荣耀,原神。。。都是基于unity开发的游戏。

img

我们去打开一个unity游戏的文件夹时,我们可能会遇到下面这两种形式的文件形式,.exe便是我们的游戏启动器,无论是左边还是右边,都有一个后缀为_Data的文件夹

img

继续跟进目录后 我们就会发现两者有点细微的差别,左边名为il2cpp,右边名为管理的managed文件,想要进一步了解unity内部的原理,了解这两种的区别,就要接着往下去认识这两种语言。

img

C#和Mono

C sharp以.net框架作为基础一种面向对象的语言。我们知道unity有强大的多平台部署能力,而支撑这一能力的关键,就是包含了c#编译器等其他工具的开源项目Mono

Mono:一个由 Xamarin公司主持的自由开放源代码项目,目标是创建一系列符合ECMA标准(Ecma- 334和Ecma-335)的.NET工具包括C#编译器和通用语言架构。与微软的.NET Framework(共通语言运行平台)不同Mono项目不仅可以运行于Windows系统上,还可以运行于 Linux,FreeBSD,Unix,OS X和Solaris,甚至一些游戏平台。Mono使得C#这门语言有了很好的跨平台能力。

上右文件夹中的MonoBleedingEdge文件夹便是包含运行Unity服务器所需的所有Mono运行时库和依赖项。

在2014年,Unity3D官方博客上发布了“The future of scripting in unity”的文章,引入了比mono更为安全的il2cpp技术

IL语言

上文的il,全称Intermediate Language (中间语言),如何更好地理解他呢,我们可以把它理解为.NET框架下的“汇编”(低阶的人类可读编程语言)。我们实际在dnspy中去看一看他的结构

1
2
3
4
5
6
7
8
9
10
11
public class PinHead : MonoBehaviour
{
// Token: 0x06000014 RID: 20 RVA: 0x0000221E File Offset: 0x0000041E
private void OnTriggerEnter2D(Collider2D collision)
{
if (collision.tag != "PinHead")
{
GameObject.Find("GameManager").GetComponent<GameManager>().GameOver();
}
}
}

img

可以看出一段Csharp代码的对应IL中,出现了call,ldstr等类似与汇编语言中的命令,

通过一张图片我们可以更加清楚的理解上文提到的C#,高级语言如C# vb unityscript等语言经过编译,会先转为IL,IL再通过后续的编译,转为机器码使计算机去执行相应的指令。

img

正篇——逆向中的unity

出题

相关出题内容请移步下面的两篇博客

素材设计篇 代码编写篇

借着为学校招新赛出题的机会,尝试去自己开发一下unity游戏,经过自己的实际开发,我发现一款游戏产生就只有简单的三步,设计构思-素材设计-代码编写,在强大的unity引擎帮助下,很多类似物理效果,动画效果的实现都是有unity中自带的一些模块库就可以轻松实现(Boxcollider 2D就可以实现一个实体 Rigitbody 2D就能实现2的游戏的物理效果)

img

而我们需要去做的就是编写出结合游戏设计思路的关键脚本(比如游戏玩法,规则,人物的移动,关卡的转换逻辑之类的)

在这一部分主要想和大家分享一下在写c#脚本时的关键点,我们了解了正向的过程,能更好的去理解逆向的过程。我们在unity中新建一个C#脚本时,他会默认生成两个方法名Start和update

img

start叫做生命周期函数,就是他会在启动脚本时第一个去执行他,我们比如在这里就是实现了,在每次执行玩家c#代码时,先定义一个animator变量,再去执行下面的update代码。

update顾名思义就是更新,他是游戏画面逻辑更新的关键代码,很多玩家的行为,都写在这个方法之中,比如这里写到的就是一个简单的控制玩家行走跳跃的代码,以及按键的设置功能。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
void Start()
{
//获取animator组件
animator = GetComponent<Animator>();
}

void Update()
{
//获取玩家的左右键按键 -1,0,1 (a和d)
float h = Input.GetAxis("Horizontal");

if (h != 0)
{
//移动.方向 * 上一帧花费的时间*玩家按键
transform.Translate(transform.right*Time.deltaTime*h);
//这里实现的是人物的方向,为了让人物行走更加真实,方向判断根据上面的h
if (h<0)
{
GetComponent<SpriteRenderer>().flipX = false;
}

if(h>0)
{
GetComponent<SpriteRenderer>().flipX = true;
}

animator.SetBool("run",true);
}
else
{
animator.SetBool("run",false);
}


if(isOnGround && Input.GetKeyDown(KeyCode.W))
{
GetComponent<Rigidbody2D>().AddForce(Vector2.up*180);
}

}
}

那么作为一名逆向的思路,我们在寻找函数时,如果遇到的类似的2d游戏,在想去查找一些关键的执行逻辑在哪些方法中实现,可以直接去寻找update方法名的关键词,从中去获取到一些信息。

做题经历

在市面上普遍有两种unity逆向,他们分别使用不同的编译方式,解决的思路也不同。

Mono编译

这是原始的编译方式,也是最容易攻破,不太安全的一种编译方式,生成的游戏文件夹中,游戏的关键代码文件会直接生成在 _Data\Managed\Assembly-CSharp.dll的文件之中,出题人一般会想让我们通过破解游戏逻辑,或者在c#中进行解密来获取到最后的flag。

是男人就来扎针

牢大我想你了

il2cpp编译

这串怎么去读呢? IL二cpp吗?按照英文的读法,应该是 IL two(to)cpp,也就是从IL中间语言转换为cpp的过程,这一过程是如何实现的呢。

在上文的基础中我们已经知道,unity的代码在执行时,会先将高级语言转换为相应的IL中间语言,中间语言再通过Mono VM编译为机器码。刚才提到了The future of scripting in unity,便是使用了IL2CPP技术将原先的过程变为了,在代码转换为IL之后,不会通过Mono编译,而是通过IL2cpp转变为c++代码,然后再使用本地的c++编译器编译为ASM汇编代码,通过IL2cpp VM转为机器码执行。

图片可以很直观的看到改变的步骤

img

AOT(Ahead Of Time)编译而非JIT(Just In Time)编译https://gwb.tencent.com/community/detail/126815

而通过出题我们也很明显的看到了这一过程,将编译选择为IL2cpp后,生成项目时编译会出现“编译为c”“编译为ASM”这样的提示

img

img

我们的文件夹中也是提示不要伴随你的游戏文件的文件夹中,有il2cpp相应的输出文件,看到里面便是.cpp代码。也就是说,我们发布游戏的话,只用打包data中的文件,而不用把c#的dll直接像mono一样暴露在外面,所以说这种方式也就更为安全。

img

img

打开data文件夹中,我们发现只有少的可怜的global-metadata(元数据)但是这其中就包含着C#中的类名、方法名、属性名、字符串等地址信息,程序启动时会按需从中读取。可以说是il2cpp的关键逆向入口点。

img

XYCTF babyunity

Il2CppDumper

1
Il2CppDumper.exe GameAssembly.dll global-metadata.dat output-out

将游戏文件中的

img

结语——后期的项目

这几次的unity经历更多还是从基础的原理或者简单的题目中去学习的,还没有真正去实战的角度去分析,在整理资料的时候发现了一位师傅实战某手游的文章,弄完下一个项目之后计划再去搞一下类似的项目。

才疏学浅,希望今天的分享能够起到抛砖引玉的效果,所讲内容中有误的地方也希望师傅们可以批评指正,同时也希望能与更多感兴趣的师傅们一起继续讨论unity逆向相关的内容。

本文参考

Unity之IL2CPP解析-腾讯游戏学堂

https://mrwq.github.io/aggregate-paper/butian/%E6%B5%85%E8%B0%88CTF%E4%B8%AD%E7%9A%84unity%E6%B8%B8%E6%88%8F%E9%80%86%E5%90%91/

[原创] XYCTF两道Unity IL2CPP题的出题思路与题解-CTF对抗-看雪-安全社区|安全招聘|kanxue.com

Unity逆向

https://bbs.kanxue.com/thread-278275.htm#msg_header_h2_0

微信
Thank U 🐟

About this Post

This post is written by xianyuuuan, licensed under CC BY-NC 4.0.