GUI: Show progress messages in busy indicator
This commit is contained in:
@@ -125,6 +125,8 @@ namespace Il2CppInspector
|
|||||||
|
|
||||||
public override int Bits => (elf_header.m_arch == (uint) Elf.ELFCLASS64) ? 64 : 32;
|
public override int Bits => (elf_header.m_arch == (uint) Elf.ELFCLASS64) ? 64 : 32;
|
||||||
|
|
||||||
|
//public override event EventHandler<string> OnStatusUpdate;
|
||||||
|
|
||||||
private elf_shdr<TWord> getSection(Elf sectionIndex) => section_header_table.FirstOrDefault(x => x.sh_type == (uint) sectionIndex);
|
private elf_shdr<TWord> getSection(Elf sectionIndex) => section_header_table.FirstOrDefault(x => x.sh_type == (uint) sectionIndex);
|
||||||
private IEnumerable<elf_shdr<TWord>> getSections(Elf sectionIndex) => section_header_table.Where(x => x.sh_type == (uint) sectionIndex);
|
private IEnumerable<elf_shdr<TWord>> getSections(Elf sectionIndex) => section_header_table.Where(x => x.sh_type == (uint) sectionIndex);
|
||||||
private TPHdr getProgramHeader(Elf programIndex) => program_header_table.FirstOrDefault(x => x.p_type == (uint) programIndex);
|
private TPHdr getProgramHeader(Elf programIndex) => program_header_table.FirstOrDefault(x => x.p_type == (uint) programIndex);
|
||||||
@@ -167,6 +169,8 @@ namespace Il2CppInspector
|
|||||||
// Find all relocations; target address => (rela header (rels are converted to rela), symbol table base address, is rela?)
|
// Find all relocations; target address => (rela header (rels are converted to rela), symbol table base address, is rela?)
|
||||||
var rels = new HashSet<ElfReloc>();
|
var rels = new HashSet<ElfReloc>();
|
||||||
|
|
||||||
|
StatusUpdate("Processing relocations");
|
||||||
|
|
||||||
// Two types: add value from offset in image, and add value from specified addend
|
// Two types: add value from offset in image, and add value from specified addend
|
||||||
foreach (var relSection in getSections(Elf.SHT_REL))
|
foreach (var relSection in getSections(Elf.SHT_REL))
|
||||||
rels.UnionWith(
|
rels.UnionWith(
|
||||||
@@ -253,6 +257,7 @@ namespace Il2CppInspector
|
|||||||
var xorKey = rodataFirstBytes.GroupBy(b => b).OrderByDescending(f => f.Count()).First().Key;
|
var xorKey = rodataFirstBytes.GroupBy(b => b).OrderByDescending(f => f.Count()).First().Key;
|
||||||
|
|
||||||
if (xorKey != 0x00) {
|
if (xorKey != 0x00) {
|
||||||
|
StatusUpdate("Decrypting");
|
||||||
Console.WriteLine($"Performing trivial XOR decryption (key: 0x{xorKey:X2})");
|
Console.WriteLine($"Performing trivial XOR decryption (key: 0x{xorKey:X2})");
|
||||||
|
|
||||||
xorSection(".text", xorKey);
|
xorSection(".text", xorKey);
|
||||||
|
|||||||
@@ -47,28 +47,29 @@ namespace Il2CppInspector
|
|||||||
U ReadObject<U>() where U : new();
|
U ReadObject<U>() where U : new();
|
||||||
string ReadMappedNullTerminatedString(ulong uiAddr);
|
string ReadMappedNullTerminatedString(ulong uiAddr);
|
||||||
List<U> ReadMappedObjectPointerArray<U>(ulong uiAddr, int count) where U : new();
|
List<U> ReadMappedObjectPointerArray<U>(ulong uiAddr, int count) where U : new();
|
||||||
|
event EventHandler<string> OnStatusUpdate;
|
||||||
}
|
}
|
||||||
|
|
||||||
public class FileFormatReader
|
public class FileFormatReader
|
||||||
{
|
{
|
||||||
// Helper method to try all defined file formats when the contents of the binary is unknown
|
// Helper method to try all defined file formats when the contents of the binary is unknown
|
||||||
public static IFileFormatReader Load(string filename) => Load(new FileStream(filename, FileMode.Open, FileAccess.Read));
|
public static IFileFormatReader Load(string filename, EventHandler<string> statusCallback = null) => Load(new FileStream(filename, FileMode.Open, FileAccess.Read), statusCallback);
|
||||||
|
|
||||||
public static IFileFormatReader Load(Stream stream) {
|
public static IFileFormatReader Load(Stream stream, EventHandler<string> statusCallback = null) {
|
||||||
var types = Assembly.GetExecutingAssembly().DefinedTypes
|
var types = Assembly.GetExecutingAssembly().DefinedTypes
|
||||||
.Where(x => x.ImplementedInterfaces.Contains(typeof(IFileFormatReader)) && !x.IsGenericTypeDefinition);
|
.Where(x => x.ImplementedInterfaces.Contains(typeof(IFileFormatReader)) && !x.IsGenericTypeDefinition);
|
||||||
|
|
||||||
foreach (var type in types) {
|
foreach (var type in types) {
|
||||||
if (type.GetMethod("Load", BindingFlags.FlattenHierarchy | BindingFlags.Static | BindingFlags.Public,
|
if (type.GetMethod("Load", BindingFlags.FlattenHierarchy | BindingFlags.Static | BindingFlags.Public,
|
||||||
null, new [] {typeof(Stream)}, null)
|
null, new [] {typeof(Stream), typeof(EventHandler<string>)}, null)
|
||||||
.Invoke(null, new object[] { stream }) is IFileFormatReader loaded)
|
.Invoke(null, new object[] { stream, statusCallback }) is IFileFormatReader loaded)
|
||||||
return loaded;
|
return loaded;
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class FileFormatReader<T> : BinaryObjectReader, IFileFormatReader where T : FileFormatReader<T>
|
public abstract class FileFormatReader<T> : BinaryObjectReader, IFileFormatReader where T : FileFormatReader<T>
|
||||||
{
|
{
|
||||||
public FileFormatReader(Stream stream) : base(stream) { }
|
public FileFormatReader(Stream stream) : base(stream) { }
|
||||||
|
|
||||||
@@ -86,6 +87,10 @@ namespace Il2CppInspector
|
|||||||
|
|
||||||
public virtual int Bits => throw new NotImplementedException();
|
public virtual int Bits => throw new NotImplementedException();
|
||||||
|
|
||||||
|
public event EventHandler<string> OnStatusUpdate;
|
||||||
|
|
||||||
|
protected void StatusUpdate(string status) => OnStatusUpdate?.Invoke(this, status);
|
||||||
|
|
||||||
public IEnumerable<IFileFormatReader> Images {
|
public IEnumerable<IFileFormatReader> Images {
|
||||||
get {
|
get {
|
||||||
for (uint i = 0; i < NumImages; i++)
|
for (uint i = 0; i < NumImages; i++)
|
||||||
@@ -93,12 +98,12 @@ namespace Il2CppInspector
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static T Load(string filename) {
|
public static T Load(string filename, EventHandler<string> statusCallback = null) {
|
||||||
using var stream = new FileStream(filename, FileMode.Open, FileAccess.Read);
|
using var stream = new FileStream(filename, FileMode.Open, FileAccess.Read);
|
||||||
return Load(stream);
|
return Load(stream, statusCallback);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static T Load(Stream stream) {
|
public static T Load(Stream stream, EventHandler<string> statusCallback = null) {
|
||||||
// Copy the original stream in case we modify it
|
// Copy the original stream in case we modify it
|
||||||
var ms = new MemoryStream();
|
var ms = new MemoryStream();
|
||||||
stream.Position = 0;
|
stream.Position = 0;
|
||||||
@@ -106,7 +111,12 @@ namespace Il2CppInspector
|
|||||||
|
|
||||||
ms.Position = 0;
|
ms.Position = 0;
|
||||||
var pe = (T) Activator.CreateInstance(typeof(T), ms);
|
var pe = (T) Activator.CreateInstance(typeof(T), ms);
|
||||||
return pe.Init() ? pe : null;
|
return pe.InitImpl(statusCallback) ? pe : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool InitImpl(EventHandler<string> statusCallback = null) {
|
||||||
|
OnStatusUpdate += statusCallback;
|
||||||
|
return Init();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Confirm file is valid and set up RVA mappings
|
// Confirm file is valid and set up RVA mappings
|
||||||
|
|||||||
@@ -21,6 +21,11 @@ namespace Il2CppInspectorGUI
|
|||||||
|
|
||||||
public Exception LastException { get; private set; }
|
public Exception LastException { get; private set; }
|
||||||
|
|
||||||
|
// Event to indicate current work status
|
||||||
|
public event EventHandler<string> OnStatusUpdate;
|
||||||
|
|
||||||
|
private void StatusUpdate(object sender, string status) => OnStatusUpdate?.Invoke(sender, status);
|
||||||
|
|
||||||
// Attempt to load an IL2CPP metadata file
|
// Attempt to load an IL2CPP metadata file
|
||||||
public Task<bool> LoadMetadataAsync(string metadataFile) =>
|
public Task<bool> LoadMetadataAsync(string metadataFile) =>
|
||||||
Task.Run(() => {
|
Task.Run(() => {
|
||||||
@@ -38,7 +43,7 @@ namespace Il2CppInspectorGUI
|
|||||||
Task.Run(() => {
|
Task.Run(() => {
|
||||||
try {
|
try {
|
||||||
// This may throw other exceptions from the individual loaders as well
|
// This may throw other exceptions from the individual loaders as well
|
||||||
IFileFormatReader stream = FileFormatReader.Load(binaryFile);
|
IFileFormatReader stream = FileFormatReader.Load(binaryFile, StatusUpdate);
|
||||||
if (stream == null) {
|
if (stream == null) {
|
||||||
throw new InvalidOperationException("Could not determine the binary file format");
|
throw new InvalidOperationException("Could not determine the binary file format");
|
||||||
}
|
}
|
||||||
@@ -49,6 +54,8 @@ namespace Il2CppInspectorGUI
|
|||||||
// Multi-image binaries may contain more than one Il2Cpp image
|
// Multi-image binaries may contain more than one Il2Cpp image
|
||||||
Il2CppModels.Clear();
|
Il2CppModels.Clear();
|
||||||
foreach (var image in stream.Images) {
|
foreach (var image in stream.Images) {
|
||||||
|
OnStatusUpdate?.Invoke(this, "Analyzing IL2CPP data");
|
||||||
|
|
||||||
// Architecture-agnostic load attempt
|
// Architecture-agnostic load attempt
|
||||||
try {
|
try {
|
||||||
// If we can't load the IL2CPP data here, it's probably packed or obfuscated; ignore it
|
// If we can't load the IL2CPP data here, it's probably packed or obfuscated; ignore it
|
||||||
@@ -56,6 +63,7 @@ namespace Il2CppInspectorGUI
|
|||||||
var inspector = new Inspector(binary, metadata);
|
var inspector = new Inspector(binary, metadata);
|
||||||
|
|
||||||
// Build type model
|
// Build type model
|
||||||
|
OnStatusUpdate?.Invoke(this, "Building type model");
|
||||||
Il2CppModels.Add(new Il2CppModel(inspector));
|
Il2CppModels.Add(new Il2CppModel(inspector));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -152,9 +152,9 @@
|
|||||||
<Button Name="btnBack" Margin="5" HorizontalAlignment="Left" VerticalAlignment="Bottom" Style="{StaticResource LightBoxButton}" FontSize="18" Width="120" Click="BtnBack_OnClick" Visibility="Hidden"><< Back</Button>
|
<Button Name="btnBack" Margin="5" HorizontalAlignment="Left" VerticalAlignment="Bottom" Style="{StaticResource LightBoxButton}" FontSize="18" Width="120" Click="BtnBack_OnClick" Visibility="Hidden"><< Back</Button>
|
||||||
|
|
||||||
<!-- Busy indicator -->
|
<!-- Busy indicator -->
|
||||||
<Border Name="areaBusyIndicator" BorderThickness="1" CornerRadius="2" BorderBrush="Gray" HorizontalAlignment="Center" VerticalAlignment="Center" Background="#F8F8F8" SnapsToDevicePixels="True" Visibility="Hidden">
|
<Border Name="areaBusyIndicator" Width="400" BorderThickness="1" CornerRadius="2" BorderBrush="Gray" HorizontalAlignment="Center" VerticalAlignment="Center" Background="White" SnapsToDevicePixels="True" Visibility="Hidden">
|
||||||
<StackPanel Margin="60,40,60,40">
|
<StackPanel Margin="60,40,60,40">
|
||||||
<TextBlock Name="txtBusyStatus" Foreground="{StaticResource WindowsBlue}" FontSize="24">Getting things ready...</TextBlock>
|
<TextBlock Name="txtBusyStatus" Foreground="{StaticResource WindowsBlue}" FontSize="24" HorizontalAlignment="Center">Getting things ready...</TextBlock>
|
||||||
<Image gif:AnimationBehavior.SourceUri="Resources/pizza.gif" Width="100" Margin="0,20,0,0" RenderOptions.BitmapScalingMode="Fant" />
|
<Image gif:AnimationBehavior.SourceUri="Resources/pizza.gif" Width="100" Margin="0,20,0,0" RenderOptions.BitmapScalingMode="Fant" />
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
</Border>
|
</Border>
|
||||||
|
|||||||
@@ -26,8 +26,13 @@ namespace Il2CppInspectorGUI
|
|||||||
{
|
{
|
||||||
public MainWindow() {
|
public MainWindow() {
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
|
|
||||||
|
// Subscribe to status update events
|
||||||
|
((App) Application.Current).OnStatusUpdate += OnStatusUpdate;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void OnStatusUpdate(object sender, string e) => txtBusyStatus.Dispatcher.Invoke(() => txtBusyStatus.Text = e + "...");
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Select global metadata file
|
/// Select global metadata file
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
Reference in New Issue
Block a user