From 24790b80567042934faab4fa17f46a3a0f9dfe14 Mon Sep 17 00:00:00 2001 From: suloku Date: Wed, 2 Mar 2016 19:49:40 +0100 Subject: [PATCH] Globalized block encryption/decryption. Only entralink forest can be decrypted for now until more encrypted data is found and added. --- BW_tool/Dumper.Designer.cs | 17 +++++++ BW_tool/Dumper.cs | 20 ++++++++ BW_tool/MainForm.Designer.cs | 22 ++++++++- BW_tool/MainForm.cs | 25 +++++++++- BW_tool/SAV/PKX5.cs | 2 +- BW_tool/SAV/SAV5.cs | 96 ++++++++++++++++++++++++++++-------- 6 files changed, 157 insertions(+), 25 deletions(-) diff --git a/BW_tool/Dumper.Designer.cs b/BW_tool/Dumper.Designer.cs index 94af06e..cf4fd47 100644 --- a/BW_tool/Dumper.Designer.cs +++ b/BW_tool/Dumper.Designer.cs @@ -19,6 +19,7 @@ namespace BW_tool private System.Windows.Forms.Button dump_dec_but; private System.Windows.Forms.Button inject_crypt_but; private System.Windows.Forms.ComboBox selectedblock; + private System.Windows.Forms.CheckBox crypt_check; /// /// Disposes resources used by the form. @@ -46,6 +47,7 @@ namespace BW_tool this.dump_dec_but = new System.Windows.Forms.Button(); this.inject_crypt_but = new System.Windows.Forms.Button(); this.selectedblock = new System.Windows.Forms.ComboBox(); + this.crypt_check = new System.Windows.Forms.CheckBox(); this.SuspendLayout(); // // dump_but @@ -70,6 +72,7 @@ namespace BW_tool // // dump_dec_but // + this.dump_dec_but.Enabled = false; this.dump_dec_but.Location = new System.Drawing.Point(204, 68); this.dump_dec_but.Name = "dump_dec_but"; this.dump_dec_but.Size = new System.Drawing.Size(125, 23); @@ -80,6 +83,7 @@ namespace BW_tool // // inject_crypt_but // + this.inject_crypt_but.Enabled = false; this.inject_crypt_but.Location = new System.Drawing.Point(353, 68); this.inject_crypt_but.Name = "inject_crypt_but"; this.inject_crypt_but.Size = new System.Drawing.Size(125, 23); @@ -173,12 +177,25 @@ namespace BW_tool this.selectedblock.Name = "selectedblock"; this.selectedblock.Size = new System.Drawing.Size(692, 21); this.selectedblock.TabIndex = 5; + this.selectedblock.SelectedIndexChanged += new System.EventHandler(this.SelectedblockSelectedIndexChanged); + // + // crypt_check + // + this.crypt_check.AutoCheck = false; + this.crypt_check.Location = new System.Drawing.Point(12, 38); + this.crypt_check.Name = "crypt_check"; + this.crypt_check.Size = new System.Drawing.Size(104, 24); + this.crypt_check.TabIndex = 6; + this.crypt_check.Text = "Encripted"; + this.crypt_check.UseVisualStyleBackColor = true; + this.crypt_check.CheckedChanged += new System.EventHandler(this.Crypt_checkCheckedChanged); // // Dumper // this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; this.ClientSize = new System.Drawing.Size(716, 103); + this.Controls.Add(this.crypt_check); this.Controls.Add(this.selectedblock); this.Controls.Add(this.inject_crypt_but); this.Controls.Add(this.dump_dec_but); diff --git a/BW_tool/Dumper.cs b/BW_tool/Dumper.cs index 9e75257..e034f13 100644 --- a/BW_tool/Dumper.cs +++ b/BW_tool/Dumper.cs @@ -82,5 +82,25 @@ namespace BW_tool MainForm.save.setBlockCrypt( injectfile, (int)selectedblock.SelectedIndex); //MessageBox.Show(injectfile.Length.ToString()); } + void Crypt_checkCheckedChanged(object sender, EventArgs e) + { + if (MainForm.save.blocks[selectedblock.SelectedIndex].encrypted) + { + dump_dec_but.Enabled = true; + inject_crypt_but.Enabled = true; + } + else + { + dump_dec_but.Enabled = false; + inject_crypt_but.Enabled = false; + } + } + void SelectedblockSelectedIndexChanged(object sender, EventArgs e) + { + if (MainForm.save.blocks[selectedblock.SelectedIndex].encrypted) + crypt_check.Checked = true; + else + crypt_check.Checked = false; + } } } diff --git a/BW_tool/MainForm.Designer.cs b/BW_tool/MainForm.Designer.cs index f5b006d..bc6a250 100644 --- a/BW_tool/MainForm.Designer.cs +++ b/BW_tool/MainForm.Designer.cs @@ -20,6 +20,7 @@ namespace BW_tool private System.Windows.Forms.Label versiontext; private System.Windows.Forms.Button dumper_but; private System.Windows.Forms.Button chk_but; + private System.Windows.Forms.Button chk_updt_but; /// /// Disposes resources used by the form. @@ -48,6 +49,7 @@ namespace BW_tool this.versiontext = new System.Windows.Forms.Label(); this.dumper_but = new System.Windows.Forms.Button(); this.chk_but = new System.Windows.Forms.Button(); + this.chk_updt_but = new System.Windows.Forms.Button(); this.SuspendLayout(); // // loadsave_but @@ -66,10 +68,12 @@ namespace BW_tool this.savegamename.Name = "savegamename"; this.savegamename.Size = new System.Drawing.Size(484, 20); this.savegamename.TabIndex = 1; + this.savegamename.TextChanged += new System.EventHandler(this.SavegamenameTextChanged); // // save_but // - this.save_but.Location = new System.Drawing.Point(421, 12); + this.save_but.Enabled = false; + this.save_but.Location = new System.Drawing.Point(421, 67); this.save_but.Name = "save_but"; this.save_but.Size = new System.Drawing.Size(75, 23); this.save_but.TabIndex = 2; @@ -86,6 +90,7 @@ namespace BW_tool // // dumper_but // + this.dumper_but.Enabled = false; this.dumper_but.Location = new System.Drawing.Point(12, 80); this.dumper_but.Name = "dumper_but"; this.dumper_but.Size = new System.Drawing.Size(92, 23); @@ -96,7 +101,8 @@ namespace BW_tool // // chk_but // - this.chk_but.Location = new System.Drawing.Point(316, 12); + this.chk_but.Enabled = false; + this.chk_but.Location = new System.Drawing.Point(274, 12); this.chk_but.Name = "chk_but"; this.chk_but.Size = new System.Drawing.Size(99, 23); this.chk_but.TabIndex = 5; @@ -104,11 +110,23 @@ namespace BW_tool this.chk_but.UseVisualStyleBackColor = true; this.chk_but.Click += new System.EventHandler(this.Chk_butClick); // + // chk_updt_but + // + this.chk_updt_but.Enabled = false; + this.chk_updt_but.Location = new System.Drawing.Point(379, 12); + this.chk_updt_but.Name = "chk_updt_but"; + this.chk_updt_but.Size = new System.Drawing.Size(117, 23); + this.chk_updt_but.TabIndex = 6; + this.chk_updt_but.Text = "Update Checksums"; + this.chk_updt_but.UseVisualStyleBackColor = true; + this.chk_updt_but.Click += new System.EventHandler(this.Chk_updt_butClick); + // // MainForm // this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; this.ClientSize = new System.Drawing.Size(503, 119); + this.Controls.Add(this.chk_updt_but); this.Controls.Add(this.chk_but); this.Controls.Add(this.dumper_but); this.Controls.Add(this.versiontext); diff --git a/BW_tool/MainForm.cs b/BW_tool/MainForm.cs index f11f7dc..1366fa7 100644 --- a/BW_tool/MainForm.cs +++ b/BW_tool/MainForm.cs @@ -64,11 +64,32 @@ namespace BW_tool void Dumper_butClick(object sender, EventArgs e) { Form dumper = new Dumper(); - dumper.Show(); + dumper.ShowDialog(); } void Chk_butClick(object sender, EventArgs e) { - save.chkCheck(); + save.chkCheck(false); //Only verify + } + void Chk_updt_butClick(object sender, EventArgs e) + { + save.chkCheck(true); //Recalculate checksums and set them to savefile + } + void SavegamenameTextChanged(object sender, EventArgs e) + { + if (savegamename.Text != "") + { + dumper_but.Enabled = true; + chk_but.Enabled = true; + chk_updt_but.Enabled = true; + save_but.Enabled = true; + } + else + { + dumper_but.Enabled = false; + chk_but.Enabled = false; + chk_updt_but.Enabled = false; + save_but.Enabled = false; + } } } } diff --git a/BW_tool/SAV/PKX5.cs b/BW_tool/SAV/PKX5.cs index 4f52c75..f2a5b53 100644 --- a/BW_tool/SAV/PKX5.cs +++ b/BW_tool/SAV/PKX5.cs @@ -62,7 +62,7 @@ namespace BW_tool UInt32 seed = pv; UInt16 tmp; - for (Int32 i = start_offset; i < length-4; i += 0x2) + for (Int32 i = start_offset; i < length; i += 0x2) { tmp = BitConverter.ToUInt16(buffer_dec, i); diff --git a/BW_tool/SAV/SAV5.cs b/BW_tool/SAV/SAV5.cs index 7d46ada..a816709 100644 --- a/BW_tool/SAV/SAV5.cs +++ b/BW_tool/SAV/SAV5.cs @@ -16,6 +16,12 @@ using System.IO; namespace BW_tool { + public class Crypto + { + public int start; + public int length; + public int seed; + } public class BlockInfo { public int Offset; @@ -24,7 +30,7 @@ namespace BW_tool public int updtcnt; public int Checksum; public bool encrypted; - public int seed; + public Crypto crypto; } public class SAV5 : PKX5 { @@ -93,6 +99,7 @@ namespace BW_tool for (i=0;i<74;i++) { blocks[i] = new BlockInfo(); + blocks[i].crypto = new Crypto(); blocks[i].Offset=BlockTableBW2[i]; blocks[i].Length=BlockTableLengthBW2[i]; blocks[i].ID= i; @@ -105,10 +112,18 @@ namespace BW_tool { blocks[i].Checksum=0x25FA2; } - - blocks[i].encrypted=false; - blocks[i].seed=blocks[i].Offset+blocks[i].Length-4; - + switch (i) + { + case 60: //Entralink forest + blocks[i].encrypted=true; + blocks[i].crypto.start = 0x00; + blocks[i].crypto.length = 0x84C; + blocks[i].crypto.seed = 0x84C; + break; + default: + blocks[i].encrypted=false; + break; + } } // Different Offsets for different games. @@ -153,7 +168,7 @@ namespace BW_tool { //MessageBox.Show(decrypt.Length.ToString()); //MessageBox.Show((blocks[index].Length-4).ToString()); - decrypt = PKX5.cryptoArray(Data.Skip(blocks[index].Offset).Take(blocks[index+1].Offset-blocks[index].Offset).ToArray(), 0, blocks[index].Length, blocks[index].Length-4); + decrypt = PKX5.cryptoArray(Data.Skip(blocks[index].Offset).Take(blocks[index+1].Offset-blocks[index].Offset).ToArray(), blocks[index].crypto.start, blocks[index].crypto.length, blocks[index].crypto.seed); //MessageBox.Show((blocks[index].Length-4).ToString()); return decrypt; } @@ -221,21 +236,23 @@ namespace BW_tool { if (index <74) { + //Encrypt + byte[] encrypt = new byte[getBlockLength(index)]; + encrypt = PKX5.cryptoArray(input, blocks[index].crypto.start, blocks[index].crypto.length, blocks[index].crypto.seed); + //Recalculate checksum before applying to savedata - ushort crc = ccitt16(input.Take(blocks[index].Length).ToArray()); - if (crc != BitConverter.ToUInt16(input, blocks[index].Checksum-blocks[index].Offset) ) + ushort crc = ccitt16(encrypt.Take(blocks[index].Length).ToArray()); + if (crc != BitConverter.ToUInt16(encrypt, blocks[index].Checksum-blocks[index].Offset) ) { - Array.Copy(BitConverter.GetBytes(crc), 0, input, blocks[index].Checksum-blocks[index].Offset, 2); + Array.Copy(BitConverter.GetBytes(crc), 0, encrypt, blocks[index].Checksum-blocks[index].Offset, 2); MessageBox.Show("Block's checksum updated"); }else { MessageBox.Show("Checksum doesn't need update"); } - - - input.CopyTo(Data, blocks[index].Offset); - input.CopyTo(Data, blocks[index].Offset+SIZE2); + encrypt.CopyTo(Data, blocks[index].Offset); + encrypt.CopyTo(Data, blocks[index].Offset+SIZE2); Edited = true; } else return; @@ -247,12 +264,15 @@ namespace BW_tool input.CopyTo(Data, Offset); Edited = true; } - public void chkCheck() + public void chkCheck(bool correct) { int i = 0; string badblocks; badblocks = "Found bad checksums in MAIN save at blocks: "; + string correctedblocks; + correctedblocks = "Corrected checksums in MAIN save at blocks: "; bool badcheck = false; + bool firstcorrect = false; if (B2W2) { //Main save checksums @@ -261,8 +281,20 @@ namespace BW_tool ushort crc = ccitt16(Data.Skip(blocks[i].Offset).Take(blocks[i].Length).ToArray()); if ( crc != BitConverter.ToUInt16(Data, blocks[i].Checksum) ) { - //Array.Copy(BitConverter.GetBytes(crc), 0, input, blocks[index].Checksum-blocks[index].Offset, 2); - //MessageBox.Show("Block's checksum is wrong " + i.ToString()); + if (correct) + { + Array.Copy(BitConverter.GetBytes(crc), 0, Data, blocks[i].Checksum, 2); + if (!firstcorrect) + { + firstcorrect = true; + correctedblocks = correctedblocks + i.ToString(); + }else + { + correctedblocks = correctedblocks + ", " + i.ToString(); + } + Edited = true; + } + //Build bad checksum message if (!badcheck) { badcheck = true; @@ -279,20 +311,39 @@ namespace BW_tool } if(badcheck) - MessageBox.Show(badblocks); + { + if (correct) + MessageBox.Show(correctedblocks); + else + MessageBox.Show(badblocks); + } else MessageBox.Show("All 74 checksums OK in MAIN save"); //Backup save checksums badcheck = false; badblocks = "Found bad checksums in BACKUP save at blocks: "; + firstcorrect = false; + correctedblocks = "Corrected checksums in BACKUP save at blocks: "; for(i=0; i<74; i++) { ushort crc = ccitt16(Data.Skip(blocks[i].Offset+SIZE2).Take(blocks[i].Length).ToArray()); if ( crc != BitConverter.ToUInt16(Data, blocks[i].Checksum+SIZE2) ) { - //Array.Copy(BitConverter.GetBytes(crc), 0, input, blocks[index].Checksum-blocks[index].Offset, 2); - //MessageBox.Show("Block's checksum is wrong " + i.ToString()); + if (correct) + { + Array.Copy(BitConverter.GetBytes(crc), 0, Data, blocks[i].Checksum+SIZE2, 2); + if (!firstcorrect) + { + firstcorrect = true; + correctedblocks = correctedblocks + i.ToString(); + }else + { + correctedblocks = correctedblocks + ", " + i.ToString(); + } + Edited = true; + } + //Build bad checksum message if (!badcheck) { badcheck = true; @@ -309,7 +360,12 @@ namespace BW_tool } if(badcheck) - MessageBox.Show(badblocks); + { + if (correct) + MessageBox.Show(correctedblocks); + else + MessageBox.Show(badblocks); + } else MessageBox.Show("All 74 checksums OK in BACKUP save");