CLI/GUI: Add support for saving processed metadata and binary

This commit is contained in:
Katy Coe
2020-12-09 19:44:19 +01:00
parent f6eed36284
commit 34819a114d
4 changed files with 145 additions and 2 deletions

View File

@@ -3,8 +3,10 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.IO;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Threading.Tasks;
using System.Windows;
using Il2CppInspector;
@@ -17,10 +19,21 @@ namespace Il2CppInspectorGUI
/// <summary>
/// Interaction logic for App.xaml
/// </summary>
public partial class App : Application
public partial class App : Application, INotifyPropertyChanged
{
private Metadata metadata;
// True if we extracted from an APK, IPA, zip file etc.
private bool isExtractedFromPackage;
public bool IsExtractedFromPackage {
get => isExtractedFromPackage;
set {
if (value == isExtractedFromPackage) return;
isExtractedFromPackage = value;
OnPropertyChanged();
}
}
public List<AppModel> AppModels { get; } = new List<AppModel>();
public Exception LastException { get; private set; }
@@ -32,6 +45,8 @@ namespace Il2CppInspectorGUI
// Attempt to load an IL2CPP application package (APK or IPA)
public async Task<bool> LoadPackageAsync(IEnumerable<string> packageFiles) {
IsExtractedFromPackage = false;
try {
OnStatusUpdate?.Invoke(this, "Extracting package");
@@ -39,7 +54,8 @@ namespace Il2CppInspectorGUI
if (streams == null)
throw new InvalidOperationException("The supplied package is not an APK or IPA file, or does not contain a complete IL2CPP application");
return await LoadMetadataAsync(streams.Value.Metadata) && await LoadBinaryAsync(streams.Value.Binary);
IsExtractedFromPackage = await LoadMetadataAsync(streams.Value.Metadata) && await LoadBinaryAsync(streams.Value.Binary);
return IsExtractedFromPackage;
}
catch (Exception ex) {
LastException = ex;
@@ -49,6 +65,7 @@ namespace Il2CppInspectorGUI
// Attempt to load an IL2CPP metadata file
public async Task<bool> LoadMetadataAsync(string metadataFile) {
IsExtractedFromPackage = false;
var stream = new MemoryStream(await File.ReadAllBytesAsync(metadataFile));
return await LoadMetadataAsync(stream);
}
@@ -120,5 +137,11 @@ namespace Il2CppInspectorGUI
return false;
}
});
// Property change notifier for IsExtractedFromPackage binding
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null) {
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
}

View File

@@ -175,6 +175,45 @@
<Label Grid.Row="8" Grid.Column="0" Content="Il2CppCodeRegistration function"></Label>
<Label Grid.Row="8" Grid.Column="1" Content="{Binding Path=Binary.RegistrationFunctionPointer}" ContentStringFormat="0x{0:x8}"></Label>
</Grid>
<!-- 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.Style>
<Style BasedOn="{StaticResource LightBoxButton}" TargetType="{x:Type Button}">
<Style.Triggers>
<DataTrigger Binding="{Binding ElementName=areaBusyIndicator, Path=Visibility}" Value="Visible">
<Setter Property="Button.IsEnabled" Value="False"/>
</DataTrigger>
<MultiDataTrigger>
<MultiDataTrigger.Conditions>
<Condition Binding="{Binding ElementName=lstImages, Path=SelectedItem.Package.Metadata.IsModified}" Value="False" />
<Condition Binding="{Binding Path=IsExtractedFromPackage}" Value="False" />
</MultiDataTrigger.Conditions>
<Setter Property="Button.IsEnabled" Value="False"/>
</MultiDataTrigger>
</Style.Triggers>
</Style>
</Button.Style>
</Button>
<Button Name="btnSaveBinary" Click="BtnSaveBinary_OnClick" DockPanel.Dock="Top" Margin="10,2,10,10" Padding="5" HorizontalAlignment="Left" VerticalAlignment="Top" FontSize="14" Width="260" Content="Save extracted/decrypted binary...">
<Button.Style>
<Style BasedOn="{StaticResource LightBoxButton}" TargetType="{x:Type Button}">
<Style.Triggers>
<DataTrigger Binding="{Binding ElementName=areaBusyIndicator, Path=Visibility}" Value="Visible">
<Setter Property="Button.IsEnabled" Value="False"/>
</DataTrigger>
<MultiDataTrigger>
<MultiDataTrigger.Conditions>
<Condition Binding="{Binding ElementName=lstImages, Path=SelectedItem.Package.Binary.IsModified}" Value="False" />
<Condition Binding="{Binding Path=IsExtractedFromPackage}" Value="False" />
</MultiDataTrigger.Conditions>
<Setter Property="Button.IsEnabled" Value="False"/>
</MultiDataTrigger>
</Style.Triggers>
</Style>
</Button.Style>
</Button>
</DockPanel>
<Separator Grid.Row="0" Grid.Column="1" Grid.RowSpan="2" Margin="5,5,10,5">
<Separator.LayoutTransform>

View File

@@ -31,6 +31,7 @@ using Il2CppInspector.Reflection;
using Ookii.Dialogs.Wpf;
using Path = System.IO.Path;
using Il2CppInspector.Cpp.UnityHeaders;
using System.IO.Packaging;
namespace Il2CppInspectorGUI
{
@@ -42,6 +43,9 @@ namespace Il2CppInspectorGUI
public MainWindow() {
InitializeComponent();
// Allow XAML to access properties in the App class
DataContext = ((App) Application.Current);
// Subscribe to status update events
((App) Application.Current).OnStatusUpdate += OnStatusUpdate;
@@ -314,6 +318,43 @@ namespace Il2CppInspectorGUI
return false;
}
/// <summary>
/// Save extracted or decrypted files
/// </summary>
private async void BtnSaveMetadata_OnClick(object sender, RoutedEventArgs e) {
var package = ((AppModel) lstImages.SelectedItem).TypeModel.Package;
var saveFileDialog = new SaveFileDialog {
Filter = "IL2CPP metadata files (*.dat)|*.dat|All files (*.*)|*.*",
FileName = "global-metadata.dat",
CheckFileExists = false,
OverwritePrompt = true
};
if (saveFileDialog.ShowDialog() == false)
return;
var outPath = saveFileDialog.FileName;
await Task.Run(() => package.SaveMetadataToFile(outPath));
}
private async void BtnSaveBinary_OnClick(object sender, RoutedEventArgs e) {
var package = ((AppModel) lstImages.SelectedItem).TypeModel.Package;
var binaryName = package.BinaryImage.DefaultFilename;
var saveFileDialog = new SaveFileDialog {
Filter = "All files (*.*)|*.*",
FileName = binaryName,
CheckFileExists = false,
OverwritePrompt = true
};
if (saveFileDialog.ShowDialog() == false)
return;
var outPath = saveFileDialog.FileName;
await Task.Run(() => package.SaveBinaryToFile(outPath));
}
/// <summary>
/// Perform export
/// </summary>