private void cmdCompile_Click(object sender, EventArgs e) { string VirtualOffsetString = txtVirtualOffset.Text.Trim(); if (VirtualOffsetString.StartsWith("0x", StringComparison.OrdinalIgnoreCase)) { VirtualOffsetString = VirtualOffsetString.Substring(2); } UInt32 VirtualOffset = 0; CodeType CodeType = Patcher.CodeType.Thumb2; byte[] CompiledCode = null; if (UInt32.TryParse(VirtualOffsetString, System.Globalization.NumberStyles.HexNumber, null, out VirtualOffset)) { CodeType = (CodeType)Enum.Parse(typeof(Patcher.CodeType), cmbCodeType.SelectedItem.ToString()); CompiledCode = ArmCompiler.Compile(txtVisualStudioPath.Text, VirtualOffset, CodeType, txtAssemblyCode.Text); } if ((VirtualOffset != 0) && (CompiledCode == null)) { txtCompiledOpcodes.Text = ArmCompiler.Output; } else if (CompiledCode != null) { txtCompiledOpcodes.Text = Converter.ConvertHexToString(CompiledCode, " "); } }
private void cmdPatch_Click(object sender, EventArgs e) { string VirtualOffsetString = txtVirtualOffset.Text.Trim(); if (VirtualOffsetString.StartsWith("0x", StringComparison.OrdinalIgnoreCase)) { VirtualOffsetString = VirtualOffsetString.Substring(2); } UInt32 VirtualOffset = 0; CodeType CodeType = Patcher.CodeType.Thumb2; byte[] CompiledCode = null; if (UInt32.TryParse(VirtualOffsetString, System.Globalization.NumberStyles.HexNumber, null, out VirtualOffset)) { CodeType = (CodeType)Enum.Parse(typeof(Patcher.CodeType), cmbCodeType.SelectedItem.ToString()); CompiledCode = ArmCompiler.Compile(txtVisualStudioPath.Text, VirtualOffset, CodeType, txtAssemblyCode.Text); } if ((VirtualOffset != 0) && (CompiledCode == null)) { txtCompiledOpcodes.Text = ArmCompiler.Output; } else { if (CompiledCode != null) { txtCompiledOpcodes.Text = Converter.ConvertHexToString(CompiledCode, " "); } string TargetFilePath = Path.Combine(cmbTargetPath.Text, Path.GetFileName(txtInputFile.Text)); if (TargetFilePath.StartsWith(@"\")) { TargetFilePath = TargetFilePath.Substring(1); } try { MainPatcher.AddPatch(txtInputFile.Text, (txtOutputFile.Text.Trim().Length > 0) ? txtOutputFile.Text : null, cmbPatchDefinitionName.Text, cmbTargetVersion.Text, TargetFilePath, txtVisualStudioPath.Text, VirtualOffset, CodeType, txtAssemblyCode.Text, txtPatchDefinitionsFile.Text); } catch (ArgumentOutOfRangeException) { txtCompiledOpcodes.Text = "BAD VIRTUAL OFFSET"; } catch { txtCompiledOpcodes.Text = "UNKNOWN ERROR"; } txtVirtualOffset.Focus(); txtVirtualOffset.SelectAll(); } }
// 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); }