private void cmdPatch_Click(object sender, EventArgs e) { ClearLog(); StorePaths(); ScriptEngine.ExecuteScript(txtVisualStudioPath.Text.Trim(), txtScriptFile.Text.Trim(), txtInputFolder.Text.Trim(), PatchEngine, txtOutputFolder.Text.Trim(), txtBackupFolder.Text.Trim().Length == 0 ? null : txtBackupFolder.Text.Trim(), WriteLog); PatchEngine.WriteDefinitions(txtPatchDefinitionsFile.Text); WriteLog("Patch-definitions written to: " + txtPatchDefinitionsFile.Text); }
// TargetFilePath is relative to the root of the PatchDefinition // OutputFilePath can be null public static void AddPatch(string InputFilePath, string OutputFilePath, string PatchDefinitionName, string TargetVersionDescription, string TargetFilePath, string PathToVisualStudioWithWP8SDK, UInt32 VirtualAddress, CodeType CodeType, string ArmCodeFragment, string PatchDefintionsXmlPath) { SHA1Managed SHA = new SHA1Managed(); // Compile ARM code byte[] CompiledCode = null; if (VirtualAddress != 0) { CompiledCode = ArmCompiler.Compile(PathToVisualStudioWithWP8SDK, VirtualAddress, CodeType, ArmCodeFragment); } // Read original binary byte[] Binary = File.ReadAllBytes(InputFilePath); // Backup original checksum UInt32 ChecksumOffset = GetChecksumOffset(Binary); UInt32 OriginalChecksum = ByteOperations.ReadUInt32(Binary, ChecksumOffset); // Determine Raw Offset PeFile PeFile = new PeFile(Binary); UInt32 RawOffset = 0; if (VirtualAddress != 0) { RawOffset = PeFile.ConvertVirtualAddressToRawOffset(VirtualAddress); } // Add or replace patch string PatchDefintionsXml = File.ReadAllText(PatchDefintionsXmlPath); PatchEngine PatchEngine = new PatchEngine(PatchDefintionsXml); PatchDefinition PatchDefinition = PatchEngine.PatchDefinitions.Where(d => (string.Compare(d.Name, PatchDefinitionName, true) == 0)).FirstOrDefault(); if (PatchDefinition == null) { PatchDefinition = new PatchDefinition(); PatchDefinition.Name = PatchDefinitionName; PatchEngine.PatchDefinitions.Add(PatchDefinition); } TargetVersion TargetVersion = PatchDefinition.TargetVersions.Where(v => (string.Compare(v.Description, TargetVersionDescription, true) == 0)).FirstOrDefault(); if (TargetVersion == null) { TargetVersion = new TargetVersion(); TargetVersion.Description = TargetVersionDescription; PatchDefinition.TargetVersions.Add(TargetVersion); } TargetFile TargetFile = TargetVersion.TargetFiles.Where(f => ((f.Path != null) && (string.Compare(f.Path.TrimStart(new char[] { '\\' }), TargetFilePath.TrimStart(new char[] { '\\' }), true) == 0))).FirstOrDefault(); if (TargetFile == null) { TargetFile = new TargetFile(); TargetVersion.TargetFiles.Add(TargetFile); } TargetFile.Path = TargetFilePath; TargetFile.HashOriginal = SHA.ComputeHash(Binary); Patch Patch; if (VirtualAddress != 0) { Patch = TargetFile.Patches.Where(p => p.Address == RawOffset).FirstOrDefault(); if (Patch == null) { Patch = new Patch(); Patch.Address = RawOffset; TargetFile.Patches.Add(Patch); } Patch.OriginalBytes = new byte[CompiledCode.Length]; Buffer.BlockCopy(Binary, (int)RawOffset, Patch.OriginalBytes, 0, CompiledCode.Length); Patch.PatchedBytes = CompiledCode; } // Apply all patches foreach (Patch CurrentPatch in TargetFile.Patches) { Buffer.BlockCopy(CurrentPatch.PatchedBytes, 0, Binary, (int)CurrentPatch.Address, CurrentPatch.PatchedBytes.Length); } // Calculate checksum // This also modifies the binary // Original checksum is already backed up UInt32 Checksum = CalculateChecksum(Binary); // Add or replace checksum patch Patch = TargetFile.Patches.Where(p => p.Address == ChecksumOffset).FirstOrDefault(); if (Patch == null) { Patch = new Patch(); Patch.Address = ChecksumOffset; TargetFile.Patches.Add(Patch); } Patch.OriginalBytes = new byte[4]; ByteOperations.WriteUInt32(Patch.OriginalBytes, 0, OriginalChecksum); Patch.PatchedBytes = new byte[4]; ByteOperations.WriteUInt32(Patch.PatchedBytes, 0, Checksum); // Calculate hash for patched target file TargetFile.HashPatched = SHA.ComputeHash(Binary); // Write patched file if (OutputFilePath != null) { File.WriteAllBytes(OutputFilePath, Binary); } // Write PatchDefintions PatchEngine.WriteDefinitions(PatchDefintionsXmlPath); }