/
Plugin.cs
92 lines (73 loc) · 3.54 KB
/
Plugin.cs
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
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
/*
Copyright 2021 Katy Coe - http://www.djkaty.com - https://github.com/djkaty
FOR EDUCATIONAL PURPOSES ONLY
All rights reserved.
*/
using System;
using System.Collections.Generic;
using System.Linq;
using NoisyCowStudios.Bin2Object;
using Il2CppInspector;
using Il2CppInspector.PluginAPI;
using Il2CppInspector.PluginAPI.V100;
using System.Text;
namespace Loader
{
public class Plugin : IPlugin, ILoadPipeline {
public string Id => "guigubahuang";
public string Name => "Tale of Immortal (鬼谷八荒 / Guigubahuang) Loader";
public string Author => "Katy";
public string Version => "1.0";
public string Description => "Enables loading of Tale of Immortal (鬼谷八荒 / Guigubahuang)\nNOTE: Metadata file is guigubahuang_Data/resources.resource.resdata";
private PluginOptionChoice<string> presetKey = new PluginOptionChoice<string> {
Name = "key-select",
Description = "Preset decryption key for selected version",
Required = true,
Value = "0.8.1012",
Choices = new Dictionary<string, string> {
["0.8.1010"] = "0.8.1010",
["0.8.1012"] = "0.8.1012",
["custom"] = "Other version"
}
};
private PluginOptionText customKey = new PluginOptionText {
Name = "key",
Description = "Metadata decryption key",
Required = false
};
public List<IPluginOption> Options => new List<IPluginOption> { presetKey, customKey };
// Update list of keys here
private Dictionary<string, string> PresetKeys = new Dictionary<string, string> {
["0.8.1010"] = "@F_Gs<>_+**-%322asAS*]!%637473794040990947",
["0.8.1012"] = "@F_Gs<>_+**-%322asAS*]!%637474491508757063",
};
public Plugin() {
customKey.If = () => presetKey.Value == "custom";
}
// This executes as soon as the raw global-metadata.dat has been read from storage,
// before any attempt is made to analyze its contents
public void PreProcessMetadata(BinaryObjectStream stream, PluginPreProcessMetadataEventInfo info) {
stream.Position = 21;
var key = presetKey.Value == "custom"? customKey.Value : PresetKeys[presetKey.Value];
if (string.IsNullOrEmpty(key))
throw new ArgumentException("Game version or decryption key must be specified");
var sig = stream.ReadBytes(4);
sig = sig.Select((b, i) => (byte) (b - key[i % key.Length])).ToArray();
if (BitConverter.ToUInt32(sig) != Il2CppConstants.MetadataSignature)
return;
PluginServices.For(this).StatusUpdate("Decrypting metadata");
// Subtract key bytes from metadata bytes, skipping the first bytes,
// and cycling through the key bytes repeatedly
var bytesToSkipAtStart = 21;
var length = stream.Length;
var bytes = stream.ToArray();
var keyBytes = Encoding.ASCII.GetBytes(key);
for (int index = 0, pos = bytesToSkipAtStart; pos < length; index = (index + 1) % key.Length, pos++)
bytes[pos] -= keyBytes[index];
// We replace the loaded global-metadata.dat with the newly decrypted version,
// allowing Il2CppInspector to analyze it as normal
stream.Write(0, bytes.Skip(bytesToSkipAtStart).ToArray());
info.IsStreamModified = true;
}
}
}