Unity: Allow version selection from asset file

This commit is contained in:
Katy Coe
2021-01-11 02:30:26 +01:00
parent 074f13b2f4
commit 361f5179d5
5 changed files with 85 additions and 3 deletions

View File

@@ -109,6 +109,9 @@ namespace Il2CppInspector.CLI
[Option("unity-version", Required = false, HelpText = "Version of Unity used to create the input files, if known. Used to enhance Python, C++ and JSON output. If not specified, a close match will be inferred automatically.", Default = null)] [Option("unity-version", Required = false, HelpText = "Version of Unity used to create the input files, if known. Used to enhance Python, C++ and JSON output. If not specified, a close match will be inferred automatically.", Default = null)]
public UnityVersion UnityVersion { get; set; } public UnityVersion UnityVersion { get; set; }
[Option("unity-version-from-asset", Required = false, HelpText = "A Unity asset file used to determine the exact Unity version. Overrides --unity-version.", Default = null)]
public string UnityVersionAsset { get; set; }
[Option("plugins", Required = false, HelpText = "Specify options for plugins. Enclose each plugin's configuration in quotes as follows: --plugins \"pluginone --option1 value1 --option2 value2\" \"plugintwo --option...\". Use --plugins <name> to get help on a specific plugin")] [Option("plugins", Required = false, HelpText = "Specify options for plugins. Enclose each plugin's configuration in quotes as follows: --plugins \"pluginone --option1 value1 --option2 value2\" \"plugintwo --option...\". Use --plugins <name> to get help on a specific plugin")]
public IEnumerable<string> PluginOptions { get; set; } public IEnumerable<string> PluginOptions { get; set; }
} }
@@ -192,6 +195,21 @@ namespace Il2CppInspector.CLI
} }
} }
// Check Unity asset
if (options.UnityVersionAsset != null) {
try {
options.UnityVersion = UnityVersion.FromAssetFile(options.UnityVersionAsset);
Console.WriteLine("Unity asset file has version " + options.UnityVersion);
}
catch (FileNotFoundException) {
Console.Error.WriteLine($"Unity asset file {options.UnityVersionAsset} does not exist");
return 1;
} catch (ArgumentException) {
Console.Error.WriteLine("Could not determine Unity version from asset file - ignoring");
}
}
// Check excluded namespaces // Check excluded namespaces
if (options.ExcludedNamespaces.Count() == 1 && options.ExcludedNamespaces.First().ToLower() == "none") if (options.ExcludedNamespaces.Count() == 1 && options.ExcludedNamespaces.First().ToLower() == "none")
options.ExcludedNamespaces = new List<string>(); options.ExcludedNamespaces = new List<string>();

View File

@@ -6,8 +6,11 @@
*/ */
using System; using System;
using System.Collections.Generic;
using System.IO;
using System.Linq; using System.Linq;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
using NoisyCowStudios.Bin2Object;
namespace Il2CppInspector.Cpp.UnityHeaders namespace Il2CppInspector.Cpp.UnityHeaders
{ {
@@ -65,6 +68,26 @@ namespace Il2CppInspector.Cpp.UnityHeaders
BuildNumber = match.Groups[5].Success ? int.Parse(match.Groups[5].Value) : 0; BuildNumber = match.Groups[5].Success ? int.Parse(match.Groups[5].Value) : 0;
} }
// Get a Unity version from a Unity asset file
public static UnityVersion FromAssetFile(string filePath) {
// Don't use BinaryObjectStream because we'd have to read the entire file into memory
using var file = File.Open(filePath, FileMode.Open, FileAccess.Read, FileShare.Read);
using var reader = new BinaryReader(file, System.Text.Encoding.UTF8);
// Position of Unity version string in asset files
file.Position = 0x14;
// Read null-terminated string
var bytes = new List<byte>();
var maxLength = 15;
byte b;
while ((b = reader.ReadByte()) != 0 && bytes.Count < maxLength)
bytes.Add(b);
var unityString = System.Text.Encoding.UTF8.GetString(bytes.ToArray());
return new UnityVersion(unityString);
}
public static implicit operator UnityVersion(string versionString) => new UnityVersion(versionString); public static implicit operator UnityVersion(string versionString) => new UnityVersion(versionString);
public override string ToString() { public override string ToString() {

View File

@@ -113,6 +113,9 @@
<Label Grid.Row="8" Grid.Column="1" Content="{Binding Path=Binary.RegistrationFunctionPointer}" ContentStringFormat="0x{0:x8}"></Label> <Label Grid.Row="8" Grid.Column="1" Content="{Binding Path=Binary.RegistrationFunctionPointer}" ContentStringFormat="0x{0:x8}"></Label>
</Grid> </Grid>
<!-- Unity asset file button -->
<Button Name="btnUnityAsset" Click="BtnUnityAsset_Click" DockPanel.Dock="Top" Margin="10" Padding="5" HorizontalAlignment="Left" VerticalAlignment="Top" FontSize="14" Width="260" Content="Get Unity version from asset file..." Style="{StaticResource LightBoxButton}"/>
<!-- Save file buttons --> <!-- Save file buttons -->
<Button Name="btnSaveMetadata" Click="BtnSaveMetadata_OnClick" DockPanel.Dock="Top" Margin="10" Padding="5" HorizontalAlignment="Left" VerticalAlignment="Top" FontSize="14" Width="260" Content="Save extracted/decrypted metadata..."> <Button Name="btnSaveMetadata" Click="BtnSaveMetadata_OnClick" DockPanel.Dock="Top" Margin="10" Padding="5" HorizontalAlignment="Left" VerticalAlignment="Top" FontSize="14" Width="260" Content="Save extracted/decrypted metadata...">
<Button.Style> <Button.Style>

View File

@@ -212,6 +212,42 @@ namespace Il2CppInspectorGUI
((App) Application.Current).ResetLoadOptions(); ((App) Application.Current).ResetLoadOptions();
} }
/// <summary>
/// Select Unity version from asset file
/// </summary>
private void BtnUnityAsset_Click(object sender, RoutedEventArgs e) {
var openFileDialog = new OpenFileDialog {
Filter = "Unity asset files (*.*)|*.*",
CheckFileExists = true
};
if (openFileDialog.ShowDialog() != true)
return;
try {
var unityVersion = UnityVersion.FromAssetFile(openFileDialog.FileName);
var done = false;
foreach (UnityHeaders header in cboPyUnityVersion.Items) {
if (header.VersionRange.Contains(unityVersion)) {
cboPyUnityVersion.SelectedItem = header;
cboCppUnityVersion.SelectedItem = header;
cboJsonUnityVersion.SelectedItem = header;
done = true;
break;
}
}
if (done)
MessageBox.Show(this, $"Selected Unity version {unityVersion}", "Unity version detected", MessageBoxButton.OK, MessageBoxImage.Information);
else
MessageBox.Show(this, $"Asset file Unity version {unityVersion} is not compatible with the loaded IL2CPP application", "Incompatible Unity version", MessageBoxButton.OK, MessageBoxImage.Error);
}
catch (ArgumentException) {
MessageBox.Show(this, "Could not determine Unity version from this asset file", "Unity version could not be detected", MessageBoxButton.OK, MessageBoxImage.Error);
}
}
/// <summary> /// <summary>
/// User has selected an image /// User has selected an image
/// </summary> /// </summary>

View File

@@ -208,6 +208,8 @@ File format and architecture are automatically detected.
--unity-version Version of Unity used to create the input files, if known. Used to enhance Python, C++ and JSON output. If not specified, a close match will be inferred automatically. --unity-version Version of Unity used to create the input files, if known. Used to enhance Python, C++ and JSON output. If not specified, a close match will be inferred automatically.
--unity-version-from-asset A Unity asset file used to determine the exact Unity version. Overrides --unity-version.
--plugins Specify options for plugins. Enclose each plugin's configuration in quotes as follows: --plugins "pluginone --option1 value1 --option2 value2" "plugintwo --option...". Use --plugins <name> to get help on a specific plugin --plugins Specify options for plugins. Enclose each plugin's configuration in quotes as follows: --plugins "pluginone --option1 value1 --option2 value2" "plugintwo --option...". Use --plugins <name> to get help on a specific plugin
--help Display this help screen. --help Display this help screen.
@@ -280,7 +282,7 @@ Simply run Il2CppInspector with the `-p` switch to choose the IDA script output
Three files are generated by Il2CppInspector for IDAPython: the Python script itself, a JSON metadata file and a C++ type header file (this is `cpp/appdata/il2cpp-types.h` by default if you used the CLI, or `il2cpp.h` if you used the GUI). These files must be present for the script to run successfully. Three files are generated by Il2CppInspector for IDAPython: the Python script itself, a JSON metadata file and a C++ type header file (this is `cpp/appdata/il2cpp-types.h` by default if you used the CLI, or `il2cpp.h` if you used the GUI). These files must be present for the script to run successfully.
If you know which version of Unity the binary was compiled with, you can improve the output by specifying this with `--unity-version`, for example `--unity-version 2019.3.1f1`. Otherwise Il2CppInspector will make an educated guess based on the contents of the binary. If you know which version of Unity the binary was compiled with, you can improve the output by specifying this with `--unity-version`, for example `--unity-version 2019.3.1f1`. You can also supply any asset file from the application to detect the Unity version with `--unity-version-from-asset`. Otherwise Il2CppInspector will make an educated guess based on the contents of the binary.
Il2CppInspector generates the following data for IDA projects: Il2CppInspector generates the following data for IDA projects:
@@ -308,7 +310,7 @@ Run Il2CppInspector with the `-p` switch to choose the Ghidra script output file
Three files are generated by Il2CppInspector for Ghidra: the Python script itself, a JSON metadata file and a C++ type header file. These files must be present for the script to run successfully. Three files are generated by Il2CppInspector for Ghidra: the Python script itself, a JSON metadata file and a C++ type header file. These files must be present for the script to run successfully.
If you know which version of Unity the binary was compiled with, you can improve the output by specifying this with `--unity-version`, for example `--unity-version 2019.3.1f1`. Otherwise Il2CppInspector will make an educated guess based on the contents of the binary. If you know which version of Unity the binary was compiled with, you can improve the output by specifying this with `--unity-version`, for example `--unity-version 2019.3.1f1`. You can also supply any asset file from the application to detect the Unity version with `--unity-version-from-asset`. Otherwise Il2CppInspector will make an educated guess based on the contents of the binary.
**NOTE:** For best results, choose No when Ghidra asks if you would like to perform auto-analysis when the binary is first loaded. If you receive a `Conflicting data exists at address` error when running the script below, re-load the binary into the project and choose No at the auto-analysis prompt. **NOTE:** For best results, choose No when Ghidra asks if you would like to perform auto-analysis when the binary is first loaded. If you receive a `Conflicting data exists at address` error when running the script below, re-load the binary into the project and choose No at the auto-analysis prompt.
@@ -346,7 +348,7 @@ Il2CppInspector generates a series of C++ source files which you can use in a va
Run Il2CppInspector with the `-h` switch to choose the C++ output folder. Run Il2CppInspector with the `-h` switch to choose the C++ output folder.
If you know which version of Unity the binary was compiled with, you can improve the output by specifying this with `--unity-version`, for example `--unity-version 2019.3.1f1`. Otherwise Il2CppInspector will make an educated guess based on the contents of the binary. If you know which version of Unity the binary was compiled with, you can improve the output by specifying this with `--unity-version`, for example `--unity-version 2019.3.1f1`. You can also supply any asset file from the application to detect the Unity version with `--unity-version-from-asset`. Otherwise Il2CppInspector will make an educated guess based on the contents of the binary.
You can target which C++ compiler you wish to use the output files with: specify `--cpp-compiler MSVC` for Visual Studio and `--cpp-compiler GCC` for gcc or clang. You can target which C++ compiler you wish to use the output files with: specify `--cpp-compiler MSVC` for Visual Studio and `--cpp-compiler GCC` for gcc or clang.