unity游戏dump 【游戏开发进阶】教你使用IL2CppDumper从Unity il2cpp的二进制文件中获取类型、方法、字段等(反编译)

【游戏开发进阶】教你使用IL2CppDumper从Unity il2cpp的二进制文件中获取类型、方法、字段等(反编译)

文章目录

一、前言

点关注不迷路,持续输出Unity干货文章。
嗨,大家好,我是新发。
Unity使用Mono方式打出来的apk,我们可以直接从包内拿到Assembly-CSharp.dll,如果开发者没有对Assembly-CSharp.dll进行加密处理,那么我们可以很方便地使用ILSpy.exe对其进行反编译
如果使用IL2CPP方式出包,则没有Assembly-CSharp.dll,不过,有一个IL2CppDumper工具,通过它,我们可以逆向得到Assembly-CSharp.dll,下面就教大家如何使用这个IL2CppDumper吧。

二、下载IL2CppDumper

IL2CppDumper是一个开源工具,在GitHub上可以直接下载到。
地址:https://github.com/Perfare/Il2CppDumper
点击右边的Releases下面的版本进行下载即可。
在这里插入图片描述
在这里插入图片描述
下载后解压,文件如下,可以看到Il2CppDumper.exe
在这里插入图片描述

三、Unity Demo工程

为了进行测试,我们创建个Unity Demo工程,创建两个脚本,如下:
在这里插入图片描述
Main.cs脚本:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Main : MonoBehaviour
{
enum TEST_ENUM
{
E1,
E2,
E3
}

<span class="token keyword">public</span> <span class="token class-name"><span class="token keyword">int</span></span> test_int <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span>
<span class="token keyword">protected</span> <span class="token class-name"><span class="token keyword">float</span></span> test_float <span class="token operator">=</span> <span class="token number">0.0f</span><span class="token punctuation">;</span>
<span class="token keyword">private</span> <span class="token class-name"><span class="token keyword">string</span></span> test_string <span class="token operator">=</span> <span class="token string">"hello world"</span><span class="token punctuation">;</span>
<span class="token keyword">public</span> <span class="token class-name"><span class="token keyword">int</span><span class="token punctuation">[</span><span class="token punctuation">]</span></span> test_int_array<span class="token punctuation">;</span>
<span class="token keyword">protected</span> <span class="token class-name">List<span class="token punctuation">&lt;</span><span class="token keyword">string</span><span class="token punctuation">&gt;</span></span> test_string_list<span class="token punctuation">;</span>
<span class="token keyword">private</span> <span class="token class-name">TEST_ENUM</span> test_enum<span class="token punctuation">;</span>
<span class="token keyword">private</span> <span class="token class-name">Hello</span> hello <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token constructor-invocation class-name">Hello</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

<span class="token keyword">private</span> <span class="token return-type class-name"><span class="token keyword">void</span></span> <span class="token function">Awake</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
<span class="token punctuation">{<!-- --></span>
    <span class="token function">Init</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>

<span class="token keyword">private</span> <span class="token return-type class-name"><span class="token keyword">void</span></span> <span class="token function">Init</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
<span class="token punctuation">{<!-- --></span>
    test_int <span class="token operator">=</span> <span class="token number">1</span><span class="token punctuation">;</span>
    test_float <span class="token operator">=</span> <span class="token number">2.0f</span><span class="token punctuation">;</span>
    test_int_array <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token constructor-invocation class-name"><span class="token keyword">int</span></span><span class="token punctuation">[</span><span class="token number">3</span><span class="token punctuation">]</span> <span class="token punctuation">{<!-- --></span> <span class="token number">4</span><span class="token punctuation">,</span> <span class="token number">5</span><span class="token punctuation">,</span> <span class="token number">6</span> <span class="token punctuation">}</span><span class="token punctuation">;</span>
    test_string_list <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token constructor-invocation class-name">List<span class="token punctuation">&lt;</span><span class="token keyword">string</span><span class="token punctuation">&gt;</span></span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span> <span class="token string">"il2cpp"</span><span class="token punctuation">,</span> <span class="token string">"test"</span> <span class="token punctuation">}</span><span class="token punctuation">;</span>
    test_enum <span class="token operator">=</span> TEST_ENUM<span class="token punctuation">.</span>E2<span class="token punctuation">;</span>
<span class="token punctuation">}</span>

<span class="token keyword">private</span> <span class="token return-type class-name"><span class="token keyword">void</span></span> <span class="token function">Start</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
<span class="token punctuation">{<!-- --></span>
    hello<span class="token punctuation">.</span><span class="token function">SayHello</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    test_string <span class="token operator">=</span> <span class="token string">"Hi, I am linxinfa"</span><span class="token punctuation">;</span>
    hello<span class="token punctuation">.</span><span class="token function">Say</span><span class="token punctuation">(</span>test_string<span class="token punctuation">)</span><span class="token punctuation">;</span>

    <span class="token function">StartCoroutine</span><span class="token punctuation">(</span><span class="token function">TestCoroutine</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>

<span class="token keyword">private</span> <span class="token return-type class-name">IEnumerator</span> <span class="token function">TestCoroutine</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
<span class="token punctuation">{<!-- --></span>
    <span class="token keyword">for</span> <span class="token punctuation">(</span><span class="token class-name"><span class="token keyword">int</span></span> i <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span> i <span class="token operator">&lt;</span> <span class="token number">100</span><span class="token punctuation">;</span> <span class="token operator">++</span>i<span class="token punctuation">)</span>
    <span class="token punctuation">{<!-- --></span>
        <span class="token operator">++</span>test_int<span class="token punctuation">;</span>
        Debug<span class="token punctuation">.</span><span class="token function">Log</span><span class="token punctuation">(</span><span class="token string">"TestCoroutine, test_int: "</span> <span class="token operator">+</span> test_int<span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token keyword">yield</span> <span class="token keyword">return</span> <span class="token keyword">new</span> <span class="token constructor-invocation class-name">WaitForSeconds</span><span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
<span class="token punctuation">}</span>

}

  • 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
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54

Hello.cs脚本

using UnityEngine;

public class Hello
{
public void SayHello()
{
Debug.Log(“Hello, IL2CPP”);
}

<span class="token keyword">public</span> <span class="token return-type class-name"><span class="token keyword">void</span></span> <span class="token function">Say</span><span class="token punctuation">(</span><span class="token class-name"><span class="token keyword">string</span></span> text<span class="token punctuation">)</span>
<span class="token punctuation">{<!-- --></span>
    Debug<span class="token punctuation">.</span><span class="token function">Log</span><span class="token punctuation">(</span>text<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>

}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

四、IL2CPP打包

使用IL2CPP方式,打出apk包。
在这里插入图片描述
打出的apk如下。
在这里插入图片描述

五、拿到libil2cpp.so与global-metadata.dat

test.apk改为test.zip,解压进入目录中,拿到libil2cpp.soglobal-metadata.dat
\lib\armeabi-v7a\libil2cpp.so
\assets\bin\Data\Managed\Metadata\global-metadata.dat
在这里插入图片描述

六、执行Il2CppDumper.exe

回到Il2CppDumper.exe所在的目录,创建input目录和output目录。
在这里插入图片描述
libil2cpp.soglobal-metadata.dat拷贝到input目录中。
在这里插入图片描述
创建一个il2cpp_decompilation.bat文件。
在这里插入图片描述
il2cpp_decompilation.bat文件内容如下:

..\Il2CppDumper.exe libil2cpp.so global-metadata.dat ..\output

 
 
  
  
  • 1

双击执行il2cpp_decompilation.bat,如下:
在这里插入图片描述
进入output目录,可以看到生成了如下文件:
在这里插入图片描述

七、查看反编译后的文件

1、dump.cs

这个文件会把C#dll代码的类、方法、字段列出来。比如我们写的Main.csHello.cs

// Namespace: 
public class Hello // TypeDefIndex: 1414
{
    
    
	// Methods
<span class="token comment">// RVA: 0x39CB58 Offset: 0x39CB58 VA: 0x39CB58</span>
<span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token punctuation">.</span><span class="token function">ctor</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span> <span class="token punctuation">}</span>

<span class="token comment">// RVA: 0x39CB60 Offset: 0x39CB60 VA: 0x39CB60</span>
<span class="token keyword">public</span> <span class="token return-type class-name"><span class="token keyword">void</span></span> <span class="token function">SayHello</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span> <span class="token punctuation">}</span>

<span class="token comment">// RVA: 0x39CBF0 Offset: 0x39CBF0 VA: 0x39CBF0</span>
<span class="token keyword">public</span> <span class="token return-type class-name"><span class="token keyword">void</span></span> <span class="token function">Say</span><span class="token punctuation">(</span><span class="token class-name"><span class="token keyword">string</span></span> text<span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span> <span class="token punctuation">}</span>

}

// Namespace:
public class Main : MonoBehaviour // TypeDefIndex: 1415
{
// Fields
public int test_int; // 0xC
protected float test_float; // 0x10
private string test_string; // 0x14
public int[] test_int_array; // 0x18
protected List<string> test_string_list; // 0x1C
private Main.TEST_ENUM test_enum; // 0x20
private Hello hello; // 0x24

<span class="token comment">// Methods</span>

<span class="token comment">// RVA: 0x39CC78 Offset: 0x39CC78 VA: 0x39CC78</span>
<span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token punctuation">.</span><span class="token function">ctor</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span> <span class="token punctuation">}</span>

<span class="token comment">// RVA: 0x39CD08 Offset: 0x39CD08 VA: 0x39CD08</span>
<span class="token keyword">private</span> <span class="token return-type class-name"><span class="token keyword">void</span></span> <span class="token function">Awake</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span> <span class="token punctuation">}</span>

<span class="token comment">// RVA: 0x39CD0C Offset: 0x39CD0C VA: 0x39CD0C</span>
<span class="token keyword">private</span> <span class="token return-type class-name"><span class="token keyword">void</span></span> <span class="token function">Init</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span> <span class="token punctuation">}</span>

<span class="token comment">// RVA: 0x39CE7C Offset: 0x39CE7C VA: 0x39CE7C</span>
<span class="token keyword">private</span> <span class="token return-type class-name"><span class="token keyword">void</span></span> <span class="token function">Start</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span> <span class="token punctuation">}</span>

<span class="token punctuation">[</span><span class="token attribute"><span class="token class-name">DebuggerHiddenAttribute</span></span><span class="token punctuation">]</span> <span class="token comment">// RVA: 0x348B00 Offset: 0x348B00 VA: 0x348B00</span>
<span class="token comment">// RVA: 0x39CF20 Offset: 0x39CF20 VA: 0x39CF20</span>
<span class="token keyword">private</span> <span class="token return-type class-name">IEnumerator</span> <span class="token function">TestCoroutine</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span> <span class="token punctuation">}</span>

}

  • 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
  • 42
  • 43
  • 44
  • 45

2、il2cpp.h

生成的cpp的头文件,从头文件里我们也可以看到相关的数据结构。

struct Hello_Fields {
    
    
};

struct Main_Fields : UnityEngine_MonoBehaviour_Fields {
int32_t test_int;
float test_float;
struct System_String_o test_string;
struct System_Int32_array test_int_array;
struct System_Collections_Generic_List_string__o test_string_list;
int32_t test_enum;
struct Hello_o hello;
};

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

3、script.json

json格式显示类的方法信息:

{
    
    
  "Address": 3787608,
  "Name": "Hello$$.ctor",
  "Signature": "void Hello___ctor (Hello_o* __this, const MethodInfo* method);"
},
{
    
    
  "Address": 3787616,
  "Name": "Hello$$SayHello",
  "Signature": "void Hello__SayHello (Hello_o* __this, const MethodInfo* method);"
},
{
    
    
  "Address": 3787760,
  "Name": "Hello$$Say",
  "Signature": "void Hello__Say (Hello_o* __this, System_String_o* text, const MethodInfo* method);"
},
{
    
    
  "Address": 3787896,
  "Name": "Main$$.ctor",
  "Signature": "void Main___ctor (Main_o* __this, const MethodInfo* method);"
},
{
    
    
  "Address": 3788040,
  "Name": "Main$$Awake",
  "Signature": "void Main__Awake (Main_o* __this, const MethodInfo* method);"
},
{
    
    
  "Address": 3788044,
  "Name": "Main$$Init",
  "Signature": "void Main__Init (Main_o* __this, const MethodInfo* method);"
},
{
    
    
  "Address": 3788412,
  "Name": "Main$$Start",
  "Signature": "void Main__Start (Main_o* __this, const MethodInfo* method);"
},
{
    
    
  "Address": 3788576,
  "Name": "Main$$TestCoroutine",
  "Signature": "System_Collections_IEnumerator_o* Main__TestCoroutine (Main_o* __this, const MethodInfo* method);"
},

 
 
  
  
  • 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

4、stringliteral.json

json的格式显示所有的字符串信息:

{
    
    
  "value": "Hello, IL2CPP",
  "address": "0x52A0AC"
},
{
    
    
  "value": "hello world",
  "address": "0x52A0B0"
},
{
    
    
  "value": "il2cpp",
  "address": "0x52A0B4"
},
{
    
    
  "value": "test",
  "address": "0x52A0B8"
},
{
    
    
  "value": "Hi, I am linxinfa",
  "address": "0x52A0BC"
},
{
    
    
  "value": "TestCoroutine, test_int: ",
  "address": "0x52A0C0"
},

 
 
  
  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24

5、DummyDll/Assembly-CSharp.dll

进入DummyDll目录,可以看到很多dll,其中就有Assembly-CSharp.dll,我们可以使用ILSpy.exe对其进行反编译。
可以看到,与刚刚的dump.cs文件内容是一致的。
在这里插入图片描述
在这里插入图片描述

八、拓展:使用IDA逆向il2cpp.so,得到函数体内部逻辑

从上面IL2CppDumper我们可以发现,逆向得到的函数体都是空的,看不了内部逻辑。有没有办法可以逆向得到函数体内部逻辑呢?
有,需要借助另一个反编译神器:IDA,全称交互式反汇编器(Interactive Disassembler)。
在这里插入图片描述在这里插入图片描述
关于IDA的使用,我之前写过一篇文章:《新发的日常学习——IDA的入门使用,反编译so/dll文件(反编译神器)》,感兴趣的同学可以看看。

IDA下载链接:https://pan.baidu.com/s/1NATDYzomBYiwrwdH6qBjUA
提取码:2dmy
IDA官网:https://www.hex-rays.com/

IDA32位的和64位两个exe,要根据你反编译的文件运行对应的exe
Unity使用IL2CPP打包时,选择的CPU架构可以选择ARMv7ARM64,由于我上面拿的libil2cpp.soarmeabi-v7a的,也就是32位的,所以我运行的32位IDA
IDA中载入libil2cpp.so,耐心等待它的解析。
假设我们要查看Main脚本的Awake方法的函数体,我们从刚刚的dump.cs可以看到对应的函数地址:

// RVA: 0x39CD08 Offset: 0x39CD08 VA: 0x39CD08
private void Awake() {
    
     }

 
 
  
  
  • 1
  • 2

地址是:0x39CD08,我们在IDA中按G键,输入地址:0x39CD08,点击OK
在这里插入图片描述
可以看到跳过来是这样的,这里对应的是汇编代码,这个sub_39CD08就是我们的Awake函数。
在这里插入图片描述
源代码中,Awake函数中调用了Init函数:

private void Awake()
{
    
    
    Init();
}

 
 
  
  
  • 1
  • 2
  • 3
  • 4

而在dump.cs中我们可以看到Init的函数地址是0x39CD0C:

// RVA: 0x39CD0C Offset: 0x39CD0C VA: 0x39CD0C
private void Init() {
    
     }

 
 
  
  
  • 1
  • 2

我们再回过头看IDA,我们就可以对应起来了。
在这里插入图片描述
我们可以直接按F5将汇编转成对应的c代码,这个sub_39CD08就是Awake函数,可以看到,这里代码被优化了,Awake函数内部实际上就是Init中的内容,不过看起来也是挺晦涩难懂的,感兴趣的同学可以深入研究研究。

signed int __fastcall sub_39CD08(_DWORD *a1)
{
    
    
  _DWORD *v1; // r4
  int v2; // r5
  int v3; // r5
  int v4; // r5
  int v5; // r0
  int v6; // r0
  signed int result; // r0

v1 = a1;
if ( !byte_52A52B )
{
sub_39688C(&elf_hash_chain[89]);
byte_52A52B = 1;
}
v1[3] = 1;
v1[4] = 0x40000000;
v2 = dword_524724;
sub_38CFC4(dword_524724);
v3 = il2cpp_array_new_specific_0(v2, 3);
sub_773C4(0, v3, dword_5277E8, 0);
v1[6] = v3;
v4 = sub_3CCA3C(dword_524EF4);
v5 = sub_303278(v4, dword_5262D8);
if ( v4 )
{
sub_304144(v4, dword_52A0B4, dword_5262E0);
}
else
{
((void (__fastcall )(int))loc_3BF764)(v5);
v6 = sub_304144(0, dword_52A0B4, dword_5262E0);
((void (__fastcall )(int))loc_3BF764)(v6);
}
sub_304144(v4, dword_52A0B8, dword_5262E0);
result = 1;
v1[7] = v4;
v1[8] = 1;
return result;
}

  • 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

九、拓展补充:IL2CppDumper原理

il2cpp将游戏 C#代码转换为C++代码,然后编译为各平台Native代码。
在这里插入图片描述

虽然游戏逻辑是以Native代码运行, 但依然要实现 C#某些语言特性(如GC、反射),il2cpp将所有的 C#中的类名、方法名、属性名、字符串等地址信息记录在 global-metadata.dat文件。il2cpp启动时会从这个文件读取所需要的类名、方法名、属性名、字符串等地址信息。
在这里插入图片描述
我们可以在Unity安装目录的Editor目录中找到il2cpp虚拟机的源码:vm目录。
在这里插入图片描述
在里面的GlobalMetadata.cpp中,就可以看到加载global-metadata.dat文件的逻辑。

注:如果开发者对global-metadata.dat文件做了加密,那么在GlobalMetadata.cpp中加载global-metadata.dat前需要实现对应的解密逻辑。

在这里插入图片描述
IL2CppDumper正是利用global-metadata.dat文件进行逆向的。

global-metadata.dat文件是一个二进制文件,是按照一定的数据结构进行写入的。
我们可以下载个010Editor查看global-metadata.dat文件。
010Editor下载地址:https://www.sweetscape.com/download/010editor/
在这里插入图片描述

运行010Editor,将global-metadata.dat文件拖入010Editor中,我们可以看到前四个字节是AF 1B B1 FA
在这里插入图片描述
AF 1B B1 FAglobal-metadata.dat文件的标识,如果你去看IL2CppDumper源码,你就会看到这个标识的判断:

注意,IL2CppDumper是使用C#写的,C#windows平台上是小端字节序,即数据的高字节保存在内存的高地址中,我们上面使用010Editor看二进制文件的时候,从左到右地址是升高的,所以上面的AF 1B B1 FA对应到C#代码中就是0xFAB11BAF,不要搞反了哦。

在这里插入图片描述
我们这样看global-metadata.dat文件是看不出啥东西的,我们需要告诉010Editor如何解析这个global-metadata.dat文件。
这个时候,就需要下载UnityMetadata.bt模板文件了。
UnityMetadata.bt模板文件下载:https://www.sweetscape.com/010editor/repository/files/UnityMetadata.bt
下载完之后,在010Editor中点击菜单Templates / Open Template...,选择刚刚下载的UnityMetadata.bt
在这里插入图片描述
然后点击这个三角形按钮运行模板。
在这里插入图片描述
运行成功,可以看到global-metadata.dat解析出数据来了。
在这里插入图片描述
不过我们光从global-metadata.dat是看不出具体的字符串的,需要依赖libil2cpp.so进行寻址才行。

我们可以在IL2CppDumper源码中看到执行Dump方法需要传入metadatail2Cpp
在这里插入图片描述
因为libil2cpp.soUNIX派系的二进制文件,所以它的前4个字节是7F 45 4C 46,对应到C#小端的十六进制表达就是0x464c457f
在这里插入图片描述
我们可以在Init方法中看到读取libil2cpp.so的逻辑,
在这里插入图片描述
再往里走,就是Elf格式文件的解析了,这里就不展开了。执行完Dump即可生成逆向文件了。
感兴趣的同学可以继续深入研究下。

十、结束语

完毕。
喜欢Unity的同学,不要忘记点击关注,如果有什么Unity相关的技术难题,也欢迎留言或私信~

PS
dump的数据只有方法名没有方法体,如果要获取到函数内容需要使用IDA
步骤如下
1.打开IDA 解析libil2cpp.so
2.按快捷键Alt+F7,执行脚本 ida_py3.py(这个脚本在 Il2CppDumper 里)
3.选择out文件夹中的 script.json
至此 符号导入成功

猜你喜欢

转载自blog.csdn.net/sanqiuai/article/details/128772603