From 104f38fb30b61fec6ff4b47787b11ca1f5520f40 Mon Sep 17 00:00:00 2001 From: Kurt Date: Fri, 27 Mar 2020 19:19:20 -0700 Subject: [PATCH] Add hash validation --- NHSE.Core/Hashing/FileHashRegion.cs | 2 ++ NHSE.Core/Hashing/Murmur3.cs | 3 ++- NHSE.Core/Save/Meta/EncryptedFilePair.cs | 17 +++++++++++++++++ NHSE.Core/Save/Meta/HorizonSave.cs | 10 +++++++++- NHSE.Core/Save/Meta/Player.cs | 12 +++++++++++- NHSE.WinForms/Editor.Designer.cs | 16 +++++++++++++--- NHSE.WinForms/Editor.cs | 16 ++++++++++++++++ 7 files changed, 70 insertions(+), 6 deletions(-) diff --git a/NHSE.Core/Hashing/FileHashRegion.cs b/NHSE.Core/Hashing/FileHashRegion.cs index b149d07..654cea3 100644 --- a/NHSE.Core/Hashing/FileHashRegion.cs +++ b/NHSE.Core/Hashing/FileHashRegion.cs @@ -25,6 +25,8 @@ /// public int EndOffset => BeginOffset + Size; + public override string ToString() => $"{HashOffset:X}: ({BeginOffset:X}-{EndOffset})"; + public FileHashRegion(int hashOfs, int begOfs, int size) { HashOffset = hashOfs; diff --git a/NHSE.Core/Hashing/Murmur3.cs b/NHSE.Core/Hashing/Murmur3.cs index 591812d..1c85a6c 100644 --- a/NHSE.Core/Hashing/Murmur3.cs +++ b/NHSE.Core/Hashing/Murmur3.cs @@ -66,7 +66,8 @@ public static uint GetMurmur3Hash(byte[] data, int offset, uint size, uint seed public static uint UpdateMurmur32(byte[] data, int hashOffset, int readOffset, uint readSize) { var newHash = GetMurmur3Hash(data, readOffset, readSize); - Array.Copy(BitConverter.GetBytes(newHash), 0, data, hashOffset, 4); + var hashBytes = BitConverter.GetBytes(newHash); + hashBytes.CopyTo(data, hashOffset); return newHash; } diff --git a/NHSE.Core/Save/Meta/EncryptedFilePair.cs b/NHSE.Core/Save/Meta/EncryptedFilePair.cs index f666763..cc1891e 100644 --- a/NHSE.Core/Save/Meta/EncryptedFilePair.cs +++ b/NHSE.Core/Save/Meta/EncryptedFilePair.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using System.IO; using System.Text; @@ -54,6 +55,22 @@ public void Hash() Murmur3.UpdateMurmur32(Data, h.HashOffset, h.BeginOffset, (uint)h.Size); } + public IEnumerable InvalidHashes() + { + var ver = Info.GetKnownRevisionIndex(); + var hash = RevisionChecker.HashInfo[ver]; + var details = hash.GetFile(NameData); + if (details == null) + throw new ArgumentNullException(nameof(NameData)); + foreach (var h in details.HashRegions) + { + var current = Murmur3.GetMurmur3Hash(Data, h.BeginOffset, (uint)h.Size); + var saved = BitConverter.ToUInt32(Data, h.HashOffset); + if (current != saved) + yield return h; + } + } + public string GetString(int offset, int maxLength) { var str = Encoding.Unicode.GetString(Data, offset, maxLength * 2); diff --git a/NHSE.Core/Save/Meta/HorizonSave.cs b/NHSE.Core/Save/Meta/HorizonSave.cs index cb33428..a9e23fd 100644 --- a/NHSE.Core/Save/Meta/HorizonSave.cs +++ b/NHSE.Core/Save/Meta/HorizonSave.cs @@ -1,4 +1,7 @@ -namespace NHSE.Core +using System.Collections.Generic; +using System.Linq; + +namespace NHSE.Core { public class HorizonSave { @@ -22,5 +25,10 @@ public void Save(uint seed) player.Save(seed); } } + + public IEnumerable GetInvalidHashes() + { + return Main.InvalidHashes().Concat(Players.SelectMany(z => z.InvalidHashes())); + } } } diff --git a/NHSE.Core/Save/Meta/Player.cs b/NHSE.Core/Save/Meta/Player.cs index 33bccc9..9542b8a 100644 --- a/NHSE.Core/Save/Meta/Player.cs +++ b/NHSE.Core/Save/Meta/Player.cs @@ -1,4 +1,6 @@ -using System.IO; +using System.Collections.Generic; +using System.IO; +using System.Linq; namespace NHSE.Core { @@ -49,5 +51,13 @@ public void Hash() PostBox.Hash(); Profile.Hash(); } + + public IEnumerable InvalidHashes() + { + return Personal.InvalidHashes() + .Concat(Photo.InvalidHashes()) + .Concat(PostBox.InvalidHashes()) + .Concat(Profile.InvalidHashes()); + } } } \ No newline at end of file diff --git a/NHSE.WinForms/Editor.Designer.cs b/NHSE.WinForms/Editor.Designer.cs index 0e17a42..0d626c6 100644 --- a/NHSE.WinForms/Editor.Designer.cs +++ b/NHSE.WinForms/Editor.Designer.cs @@ -66,6 +66,7 @@ private void InitializeComponent() this.PB_Villager = new System.Windows.Forms.PictureBox(); this.L_VillagerID = new System.Windows.Forms.Label(); this.NUD_Villager = new System.Windows.Forms.NumericUpDown(); + this.Menu_VerifyHashes = new System.Windows.Forms.ToolStripMenuItem(); this.Menu_Editor.SuspendLayout(); this.TC_Editors.SuspendLayout(); this.Tab_Players.SuspendLayout(); @@ -119,7 +120,8 @@ private void InitializeComponent() // Menu_Tools // this.Menu_Tools.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { - this.Menu_DumpDecrypted}); + this.Menu_DumpDecrypted, + this.Menu_VerifyHashes}); this.Menu_Tools.Name = "Menu_Tools"; this.Menu_Tools.Size = new System.Drawing.Size(46, 20); this.Menu_Tools.Text = "Tools"; @@ -127,7 +129,7 @@ private void InitializeComponent() // Menu_DumpDecrypted // this.Menu_DumpDecrypted.Name = "Menu_DumpDecrypted"; - this.Menu_DumpDecrypted.Size = new System.Drawing.Size(164, 22); + this.Menu_DumpDecrypted.Size = new System.Drawing.Size(180, 22); this.Menu_DumpDecrypted.Text = "Dump Decrypted"; this.Menu_DumpDecrypted.Click += new System.EventHandler(this.Menu_DumpDecrypted_Click); // @@ -160,7 +162,7 @@ private void InitializeComponent() this.Tab_Players.Location = new System.Drawing.Point(4, 22); this.Tab_Players.Name = "Tab_Players"; this.Tab_Players.Padding = new System.Windows.Forms.Padding(3); - this.Tab_Players.Size = new System.Drawing.Size(476, 211); + this.Tab_Players.Size = new System.Drawing.Size(396, 211); this.Tab_Players.TabIndex = 1; this.Tab_Players.Text = "Players"; this.Tab_Players.UseVisualStyleBackColor = true; @@ -469,6 +471,13 @@ private void InitializeComponent() 0}); this.NUD_Villager.ValueChanged += new System.EventHandler(this.LoadVillager); // + // Menu_VerifyHashes + // + this.Menu_VerifyHashes.Name = "Menu_VerifyHashes"; + this.Menu_VerifyHashes.Size = new System.Drawing.Size(180, 22); + this.Menu_VerifyHashes.Text = "Verify Hashes"; + this.Menu_VerifyHashes.Click += new System.EventHandler(this.Menu_VerifyHashes_Click); + // // Editor // this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); @@ -542,6 +551,7 @@ private void InitializeComponent() private System.Windows.Forms.Label L_ExternalName; private System.Windows.Forms.ContextMenuStrip CM_Picture; private System.Windows.Forms.ToolStripMenuItem Menu_SavePNG; + private System.Windows.Forms.ToolStripMenuItem Menu_VerifyHashes; } } diff --git a/NHSE.WinForms/Editor.cs b/NHSE.WinForms/Editor.cs index 2a00b44..1f3dfd6 100644 --- a/NHSE.WinForms/Editor.cs +++ b/NHSE.WinForms/Editor.cs @@ -41,6 +41,22 @@ private void Menu_DumpDecrypted_Click(object sender, EventArgs e) System.Media.SystemSounds.Asterisk.Play(); } + private void Menu_VerifyHashes_Click(object sender, EventArgs e) + { + var result = SAV.GetInvalidHashes().ToArray(); + if (result.Length == 0) + { + WinFormsUtil.Alert("Hashes are valid."); + return; + } + + if (WinFormsUtil.Prompt(MessageBoxButtons.YesNo, "Export results to clipboard?") != DialogResult.Yes) + return; + + var lines = result.Select(z => z.ToString()); + Clipboard.SetText(string.Join(Environment.NewLine, lines)); + } + private void LoadAll() { LoadPlayers();