From 2da5ed19612df46d1c3a76b399ae9a517093ea38 Mon Sep 17 00:00:00 2001 From: morkt Date: Thu, 4 Jun 2015 01:13:25 +0400 Subject: [PATCH] implemented Marble scripts decryption. --- ArcFormats/ArcFormats.csproj | 7 ++ ArcFormats/ArcMBL.cs | 87 ++++++++++++++++++++-- ArcFormats/Properties/Settings.Designer.cs | 12 +++ ArcFormats/Properties/Settings.settings | 3 + ArcFormats/Strings/arcStrings.Designer.cs | 9 +++ ArcFormats/Strings/arcStrings.resx | 6 +- ArcFormats/Strings/arcStrings.ru-RU.resx | 4 + ArcFormats/WidgetMBL.xaml | 17 +++++ ArcFormats/WidgetMBL.xaml.cs | 15 ++++ ArcFormats/app.config | 3 + 10 files changed, 155 insertions(+), 8 deletions(-) create mode 100644 ArcFormats/WidgetMBL.xaml create mode 100644 ArcFormats/WidgetMBL.xaml.cs diff --git a/ArcFormats/ArcFormats.csproj b/ArcFormats/ArcFormats.csproj index 7794eb1b..7e7fdf44 100644 --- a/ArcFormats/ArcFormats.csproj +++ b/ArcFormats/ArcFormats.csproj @@ -216,6 +216,9 @@ Code WidgetLPK.xaml + + WidgetMBL.xaml + WidgetNOA.xaml @@ -320,6 +323,10 @@ MSBuild:Compile Designer + + Designer + MSBuild:Compile + Designer MSBuild:Compile diff --git a/ArcFormats/ArcMBL.cs b/ArcFormats/ArcMBL.cs index fb6e1119..4e394a6b 100644 --- a/ArcFormats/ArcMBL.cs +++ b/ArcFormats/ArcMBL.cs @@ -28,10 +28,28 @@ using System.Collections.Generic; using System.ComponentModel.Composition; using System.IO; using System.Linq; +using GameRes.Formats.Properties; +using GameRes.Formats.Strings; using GameRes.Utility; namespace GameRes.Formats.Marble { + public class MblOptions : ResourceOptions + { + public string PassPhrase; + } + + public class MblArchive : ArcFile + { + public readonly byte[] Key; + + public MblArchive (ArcView arc, ArchiveFormat impl, ICollection dir, string password) + : base (arc, impl, dir) + { + Key = Encodings.cp932.GetBytes (password); + } + } + [Export(typeof(ArchiveFormat))] public class MblOpener : ArchiveFormat { @@ -64,6 +82,7 @@ namespace GameRes.Formats.Marble return null; try { + bool contains_scripts = false; var dir = new List (count); for (int i = 0; i < count; ++i) { @@ -79,13 +98,22 @@ namespace GameRes.Formats.Marble name = name.ToLowerInvariant(); index_offset += (uint)filename_len; uint offset = file.View.ReadUInt32 (index_offset); - var entry = new AutoEntry (name, () => { - uint signature = file.View.ReadUInt32 (offset); - var res = FormatCatalog.Instance.LookupSignature (signature); - if (!res.Any() && 0x4259 == (0xffff & signature)) - res = FormatCatalog.Instance.ImageFormats.Where (x => x.Tag == "PRS"); - return res.FirstOrDefault(); - }); + Entry entry; + if (name.EndsWith (".s")) + { + entry = new Entry { Name = name, Type = "script" }; + contains_scripts = true; + } + else + { + entry = new AutoEntry (name, () => { + uint signature = file.View.ReadUInt32 (offset); + var res = FormatCatalog.Instance.LookupSignature (signature); + if (!res.Any() && 0x4259 == (0xffff & signature)) + res = FormatCatalog.Instance.ImageFormats.Where (x => x.Tag == "PRS"); + return res.FirstOrDefault(); + }); + } entry.Offset = offset; entry.Size = file.View.ReadUInt32 (index_offset+4); if (offset < index_size || !entry.CheckPlacement (file.MaxOffset)) @@ -95,6 +123,12 @@ namespace GameRes.Formats.Marble } if (0 == dir.Count) return null; + if (contains_scripts) + { + var options = Query ("Archive contains encrypted scripts.\nChoose encryption scheme or enter a passphrase."); + if (options.PassPhrase.Length > 0) + return new MblArchive (file, this, dir, options.PassPhrase); + } return new ArcFile (file, this, dir); } catch @@ -102,5 +136,44 @@ namespace GameRes.Formats.Marble return null; } } + + public static Dictionary KnownKeys = new Dictionary { + { arcStrings.ArcDefault, "" }, + { "Chikatetsu Fuusa Jiken", "naze" } + }; + + public override Stream OpenEntry (ArcFile arc, Entry entry) + { + if (entry.Type != "script" || !entry.Name.EndsWith (".s")) + return arc.File.CreateStream (entry.Offset, entry.Size); + var marc = arc as MblArchive; + var data = new byte[entry.Size]; + arc.File.View.Read (entry.Offset, data, 0, entry.Size); + if (null == marc || null == marc.Key) + { + for (int i = 0; i < data.Length; ++i) + { + data[i] = (byte)-data[i]; + } + } + else + { + for (int i = 0; i < data.Length; ++i) + { + data[i] ^= marc.Key[i % marc.Key.Length]; + } + } + return new MemoryStream (data); + } + + public override ResourceOptions GetDefaultOptions () + { + return new MblOptions { PassPhrase = Settings.Default.MBLPassPhrase }; + } + + public override object GetAccessWidget () + { + return new GUI.WidgetMBL(); + } } } diff --git a/ArcFormats/Properties/Settings.Designer.cs b/ArcFormats/Properties/Settings.Designer.cs index 10de39ac..75a85724 100644 --- a/ArcFormats/Properties/Settings.Designer.cs +++ b/ArcFormats/Properties/Settings.Designer.cs @@ -357,5 +357,17 @@ namespace GameRes.Formats.Properties { this["DPKLastScheme"] = value; } } + + [global::System.Configuration.UserScopedSettingAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Configuration.DefaultSettingValueAttribute("")] + public string MBLPassPhrase { + get { + return ((string)(this["MBLPassPhrase"])); + } + set { + this["MBLPassPhrase"] = value; + } + } } } diff --git a/ArcFormats/Properties/Settings.settings b/ArcFormats/Properties/Settings.settings index 5cdab448..eaf3d888 100644 --- a/ArcFormats/Properties/Settings.settings +++ b/ArcFormats/Properties/Settings.settings @@ -86,5 +86,8 @@ + + + \ No newline at end of file diff --git a/ArcFormats/Strings/arcStrings.Designer.cs b/ArcFormats/Strings/arcStrings.Designer.cs index 4ba844ff..244899de 100644 --- a/ArcFormats/Strings/arcStrings.Designer.cs +++ b/ArcFormats/Strings/arcStrings.Designer.cs @@ -279,6 +279,15 @@ namespace GameRes.Formats.Strings { } } + /// + /// Looks up a localized string similar to Archive contains encrypted scripts.Choose encryption scheme or enter a passphrase.. + /// + public static string MBLNotice { + get { + return ResourceManager.GetString("MBLNotice", resourceCulture); + } + } + /// /// Looks up a localized string similar to Adding file. /// diff --git a/ArcFormats/Strings/arcStrings.resx b/ArcFormats/Strings/arcStrings.resx index 1d26a4d3..75b2b4b9 100644 --- a/ArcFormats/Strings/arcStrings.resx +++ b/ArcFormats/Strings/arcStrings.resx @@ -318,4 +318,8 @@ Enter archive encryption key. Default - \ No newline at end of file + + Archive contains encrypted scripts. +Choose encryption scheme or enter a passphrase. + + diff --git a/ArcFormats/Strings/arcStrings.ru-RU.resx b/ArcFormats/Strings/arcStrings.ru-RU.resx index 02a5194c..02393dd6 100644 --- a/ArcFormats/Strings/arcStrings.ru-RU.resx +++ b/ArcFormats/Strings/arcStrings.ru-RU.resx @@ -174,6 +174,10 @@ Вариант + + Архив содержит зашифрованные скрипты. +Выберите способ шифрования или введите текстовый пароль. + Добавляется файл diff --git a/ArcFormats/WidgetMBL.xaml b/ArcFormats/WidgetMBL.xaml new file mode 100644 index 00000000..1ca9e3b3 --- /dev/null +++ b/ArcFormats/WidgetMBL.xaml @@ -0,0 +1,17 @@ + + + + + + + + diff --git a/ArcFormats/WidgetMBL.xaml.cs b/ArcFormats/WidgetMBL.xaml.cs new file mode 100644 index 00000000..46c8be9f --- /dev/null +++ b/ArcFormats/WidgetMBL.xaml.cs @@ -0,0 +1,15 @@ +using System.Windows.Controls; + +namespace GameRes.Formats.GUI +{ + /// + /// Interaction logic for WidgetMBL.xaml + /// + public partial class WidgetMBL : Grid + { + public WidgetMBL () + { + InitializeComponent (); + } + } +} diff --git a/ArcFormats/app.config b/ArcFormats/app.config index 390df4ea..dddbbe5b 100644 --- a/ArcFormats/app.config +++ b/ArcFormats/app.config @@ -88,6 +88,9 @@ + + +