Add Patcher Project

The other Patcher repository is locked from future modifications
This commit is contained in:
Gustave Monce
2024-10-21 08:57:39 +02:00
parent bc77e8b589
commit 3c66688303
39 changed files with 8895 additions and 0 deletions
+334
View File
@@ -0,0 +1,334 @@
## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons.
##
## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
# User-specific files
*.rsuser
*.suo
# *.user
*.userosscache
*.sln.docstates
# User-specific files (MonoDevelop/Xamarin Studio)
*.userprefs
# Build results
[Dd]ebug/
[Dd]ebugPublic/
[Rr]elease/
[Rr]eleases/
x64/
x86/
bld/
[Bb]in/
[Oo]bj/
[Ll]og/
# Visual Studio 2015/2017 cache/options directory
.vs/
# Uncomment if you have tasks that create the project's static files in wwwroot
#wwwroot/
# Visual Studio 2017 auto generated files
Generated\ Files/
# MSTest test Results
[Tt]est[Rr]esult*/
[Bb]uild[Ll]og.*
# NUNIT
*.VisualState.xml
TestResult.xml
# Build Results of an ATL Project
[Dd]ebugPS/
[Rr]eleasePS/
dlldata.c
# Benchmark Results
BenchmarkDotNet.Artifacts/
# .NET Core
project.lock.json
project.fragment.lock.json
artifacts/
# StyleCop
StyleCopReport.xml
# Files built by Visual Studio
*_i.c
*_p.c
*_h.h
*.ilk
*.meta
*.obj
*.iobj
*.pch
*.pdb
*.ipdb
*.pgc
*.pgd
*.rsp
*.sbr
*.tlb
*.tli
*.tlh
*.tmp
*.tmp_proj
*_wpftmp.csproj
*.log
*.vspscc
*.vssscc
.builds
*.pidb
*.svclog
*.scc
# Chutzpah Test files
_Chutzpah*
# Visual C++ cache files
ipch/
*.aps
*.ncb
*.opendb
*.opensdf
*.sdf
*.cachefile
*.VC.db
*.VC.VC.opendb
# Visual Studio profiler
*.psess
*.vsp
*.vspx
*.sap
# Visual Studio Trace Files
*.e2e
# TFS 2012 Local Workspace
$tf/
# Guidance Automation Toolkit
*.gpState
# ReSharper is a .NET coding add-in
_ReSharper*/
*.[Rr]e[Ss]harper
*.DotSettings.user
# JustCode is a .NET coding add-in
.JustCode
# TeamCity is a build add-in
_TeamCity*
# DotCover is a Code Coverage Tool
*.dotCover
# AxoCover is a Code Coverage Tool
.axoCover/*
!.axoCover/settings.json
# Visual Studio code coverage results
*.coverage
*.coveragexml
# NCrunch
_NCrunch_*
.*crunch*.local.xml
nCrunchTemp_*
# MightyMoose
*.mm.*
AutoTest.Net/
# Web workbench (sass)
.sass-cache/
# Installshield output folder
[Ee]xpress/
# DocProject is a documentation generator add-in
DocProject/buildhelp/
DocProject/Help/*.HxT
DocProject/Help/*.HxC
DocProject/Help/*.hhc
DocProject/Help/*.hhk
DocProject/Help/*.hhp
DocProject/Help/Html2
DocProject/Help/html
# Click-Once directory
publish/
# Publish Web Output
*.[Pp]ublish.xml
*.azurePubxml
# Note: Comment the next line if you want to checkin your web deploy settings,
# but database connection strings (with potential passwords) will be unencrypted
*.pubxml
*.publishproj
# Microsoft Azure Web App publish settings. Comment the next line if you want to
# checkin your Azure Web App publish settings, but sensitive information contained
# in these scripts will be unencrypted
PublishScripts/
# NuGet Packages
*.nupkg
# The packages folder can be ignored because of Package Restore
**/[Pp]ackages/*
# except build/, which is used as an MSBuild target.
!**/[Pp]ackages/build/
# Uncomment if necessary however generally it will be regenerated when needed
#!**/[Pp]ackages/repositories.config
# NuGet v3's project.json files produces more ignorable files
*.nuget.props
*.nuget.targets
# Microsoft Azure Build Output
csx/
*.build.csdef
# Microsoft Azure Emulator
ecf/
rcf/
# Windows Store app package directories and files
AppPackages/
BundleArtifacts/
Package.StoreAssociation.xml
_pkginfo.txt
*.appx
# Visual Studio cache files
# files ending in .cache can be ignored
*.[Cc]ache
# but keep track of directories ending in .cache
!*.[Cc]ache/
# Others
ClientBin/
~$*
*~
*.dbmdl
*.dbproj.schemaview
*.jfm
*.pfx
*.publishsettings
orleans.codegen.cs
# Including strong name files can present a security risk
# (https://github.com/github/gitignore/pull/2483#issue-259490424)
#*.snk
# Since there are multiple workflows, uncomment next line to ignore bower_components
# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
#bower_components/
# RIA/Silverlight projects
Generated_Code/
# Backup & report files from converting an old project file
# to a newer Visual Studio version. Backup files are not needed,
# because we have git ;-)
_UpgradeReport_Files/
Backup*/
UpgradeLog*.XML
UpgradeLog*.htm
ServiceFabricBackup/
*.rptproj.bak
# SQL Server files
*.mdf
*.ldf
*.ndf
# Business Intelligence projects
*.rdl.data
*.bim.layout
*.bim_*.settings
*.rptproj.rsuser
# Microsoft Fakes
FakesAssemblies/
# GhostDoc plugin setting file
*.GhostDoc.xml
# Node.js Tools for Visual Studio
.ntvs_analysis.dat
node_modules/
# Visual Studio 6 build log
*.plg
# Visual Studio 6 workspace options file
*.opt
# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
*.vbw
# Visual Studio LightSwitch build output
**/*.HTMLClient/GeneratedArtifacts
**/*.DesktopClient/GeneratedArtifacts
**/*.DesktopClient/ModelManifest.xml
**/*.Server/GeneratedArtifacts
**/*.Server/ModelManifest.xml
_Pvt_Extensions
# Paket dependency manager
.paket/paket.exe
paket-files/
# FAKE - F# Make
.fake/
# JetBrains Rider
.idea/
*.sln.iml
# CodeRush personal settings
.cr/personal
# Python Tools for Visual Studio (PTVS)
__pycache__/
*.pyc
# Cake - Uncomment if you are using it
# tools/**
# !tools/packages.config
# Tabs Studio
*.tss
# Telerik's JustMock configuration file
*.jmconfig
# BizTalk build output
*.btp.cs
*.btm.cs
*.odx.cs
*.xsd.cs
# OpenCover UI analysis results
OpenCover/
# Azure Stream Analytics local run output
ASALocalRun/
# MSBuild Binary and Structured Log
*.binlog
# NVidia Nsight GPU debugger configuration file
*.nvuser
# MFractors (Xamarin productivity tool) working folder
.mfractor/
# Local History for Visual Studio
.localhistory/
+6
View File
@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5.2" />
</startup>
</configuration>
+301
View File
@@ -0,0 +1,301 @@
// Copyright (c) 2018, Rene Lergner - wpinternals.net - @Heathcliff74xda
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Gee.External.Capstone;
using Gee.External.Capstone.Arm;
//using PeNet;
namespace Patcher
{
public static class ArmDisassembler
{
public static AnalyzedFile Analyze(string FilePath, string AsmPath = null)
{
PeFile File = new(FilePath);
SortedList<UInt32, ArmInstruction> AnalyzedCode = new(0x1000000); // Default capacity of 0x100000 was not enough for analyzing ntoskrnl.exe
if ((AsmPath != null) && System.IO.File.Exists(AsmPath))
{
using StreamReader Reader = new(AsmPath);
while (Reader.Peek() >= 0)
{
ArmInstruction Instruction = new(Reader.ReadLine());
AnalyzedCode.Add(Instruction.Address, Instruction);
}
}
else
{
CapstoneArmDisassembler Disassembler = CapstoneDisassembler.CreateArmDisassembler(ArmDisassembleMode.Thumb);
// Initially use a Dictionary and sort it afterwards. For analyzing ntoskrnl.exe this is about 60 times faster than using a SortedList from the start.
// Default capacity of 0x100000 was not enough for analyzing ntoskrnl.exe
Dictionary<UInt32, ArmInstruction> TempCode = new(0x1000000);
// Analyze from entrypoint
Analyze(Disassembler, File.Sections, TempCode, (UInt32)(File.ImageBase + File.EntryPoint));
// Analyze from exports
foreach (FunctionDescriptor Function in File.Exports)
Analyze(Disassembler, File.Sections, TempCode, (UInt32)Function.VirtualAddress);
// Analyze from imports
foreach (FunctionDescriptor Function in File.Imports)
Analyze(Disassembler, File.Sections, TempCode, (UInt32)Function.VirtualAddress);
// Analyze from runtime-functions
foreach (FunctionDescriptor Function in File.RuntimeFunctions)
Analyze(Disassembler, File.Sections, TempCode, (UInt32)Function.VirtualAddress);
// Sort the instructions.
// SortedList is used, because it can be indexed by value (not only by key).
List<UInt32> Keys = TempCode.Keys.ToList();
Keys.Sort();
foreach (UInt32 Key in Keys)
AnalyzedCode.Add(Key, TempCode[Key]);
if (AsmPath != null)
{
System.IO.Directory.CreateDirectory(System.IO.Path.GetDirectoryName(AsmPath));
using StreamWriter Writer = new(AsmPath, false);
for (int i = 0; i < AnalyzedCode.Count; i++)
{
Writer.WriteLine(AnalyzedCode.Values[i].ToString());
}
}
}
return new AnalyzedFile() { File = File, Code = AnalyzedCode };
}
public static void Analyze(CapstoneArmDisassembler Disassembler, List<Section> Sections, Dictionary<UInt32, ArmInstruction> AnalyzedCode, UInt32 VirtualAddress)
{
VirtualAddress -= (VirtualAddress % 2);
List<UInt32> AddressesToAnalyze = new();
AddressesToAnalyze.Add(VirtualAddress);
Section CurrentSection = null;
while (AddressesToAnalyze.Count > 0)
{
UInt32 CurrentAddress = AddressesToAnalyze[0];
if ((CurrentSection == null) || (CurrentAddress < CurrentSection.VirtualAddress) || (CurrentAddress > (CurrentSection.VirtualAddress + CurrentSection.VirtualSize)))
{
CurrentSection = Sections.Find(s => (CurrentAddress >= s.VirtualAddress) && (CurrentAddress < (s.VirtualAddress + s.VirtualSize)) && s.IsCode);
if (CurrentSection == null)
{
// throw new Exception("Address 0x" + CurrentAddress.ToString("X8") + " is not inside boundaries of code-sections");
// Probably jumped to this address because data was disassembled as if it were code. Ignore this.
// return;
AddressesToAnalyze.RemoveAt(0);
continue;
}
}
if (AnalyzedCode.ContainsKey(CurrentAddress))
{
// return;
AddressesToAnalyze.RemoveAt(0);
continue;
}
Gee.External.Capstone.Arm.ArmInstruction[] NewInstructions = Disassembler.Disassemble(CurrentSection.Buffer.Skip((int)CurrentAddress - (int)CurrentSection.VirtualAddress).ToArray(), CurrentAddress);
if (NewInstructions.Any())
{
UInt32 StartAddress = (UInt32)NewInstructions.First().Address;
UInt32 EndAddress = (UInt32)NewInstructions.Last().Address;
ArmInstruction PreviousInstruction = null;
foreach (Gee.External.Capstone.Arm.ArmInstruction DisassemblerInstruction in NewInstructions)
{
// ArmInstruction Instruction = new ArmInstruction(DisassemblerInstruction);
ArmInstruction Instruction = new()
{
Address = (UInt32)DisassemblerInstruction.Address,
Bytes = DisassemblerInstruction.Bytes,
Mnemonic = DisassemblerInstruction.Mnemonic,
Operand = DisassemblerInstruction.Operand.Replace("sb", "r9").Replace("sl", "r10").Replace("fp", "r11").Replace("ip", "r12")
};
if (AnalyzedCode.ContainsKey((UInt32)Instruction.Address))
break;
// Merge movw + movt into one command
// movw r3, #0x6010 + movt r3, #0x1000 = mov r3, #0x10006010
UInt32 HighPart, LowPart;
string HighString, LowString;
if ((PreviousInstruction?.Mnemonic == "movt") && (Instruction.Mnemonic == "movw") && (PreviousInstruction.Operand.Split(new char[] { ',' })[0] == Instruction.Operand.Split(new char[] { ',' })[0]))
{
byte[] Combined = new byte[8];
System.Buffer.BlockCopy(PreviousInstruction.Bytes, 0, Combined, 0, 4);
System.Buffer.BlockCopy(Instruction.Bytes, 0, Combined, 4, 4);
PreviousInstruction.Bytes = Combined;
PreviousInstruction.Mnemonic = "mov";
HighString = PreviousInstruction.Operand[(PreviousInstruction.Operand.IndexOf('#') + 1)..];
HighPart = (HighString.Length >= 2) && (HighString.Substring(0, 2) == "0x")
? UInt32.Parse(HighString[2..], System.Globalization.NumberStyles.HexNumber)
: UInt32.Parse(HighString);
LowString = Instruction.Operand[(Instruction.Operand.IndexOf('#') + 1)..];
LowPart = (LowString.Length >= 2) && (LowString.Substring(0, 2) == "0x")
? UInt32.Parse(LowString[2..], System.Globalization.NumberStyles.HexNumber)
: UInt32.Parse(LowString);
PreviousInstruction.Operand = string.Concat(PreviousInstruction.Operand.AsSpan(0, PreviousInstruction.Operand.IndexOf('#') + 1), "0x", ((HighPart << 16) + LowPart).ToString("X8"));
continue;
}
if ((PreviousInstruction?.Mnemonic == "movw") && (Instruction.Mnemonic == "movt") && (PreviousInstruction.Operand.Split(new char[] { ',' })[0] == Instruction.Operand.Split(new char[] { ',' })[0]))
{
byte[] Combined = new byte[8];
System.Buffer.BlockCopy(PreviousInstruction.Bytes, 0, Combined, 0, 4);
System.Buffer.BlockCopy(Instruction.Bytes, 0, Combined, 4, 4);
PreviousInstruction.Bytes = Combined;
PreviousInstruction.Mnemonic = "mov";
HighString = Instruction.Operand[(Instruction.Operand.IndexOf('#') + 1)..];
HighPart = (HighString.Length >= 2) && (HighString.Substring(0, 2) == "0x")
? UInt32.Parse(HighString[2..], System.Globalization.NumberStyles.HexNumber)
: UInt32.Parse(HighString);
LowString = PreviousInstruction.Operand[(PreviousInstruction.Operand.IndexOf('#') + 1)..];
LowPart = (LowString.Length >= 2) && (LowString.Substring(0, 2) == "0x")
? UInt32.Parse(LowString[2..], System.Globalization.NumberStyles.HexNumber)
: UInt32.Parse(LowString);
PreviousInstruction.Operand = string.Concat(PreviousInstruction.Operand.AsSpan(0, PreviousInstruction.Operand.IndexOf('#') + 1), "0x", ((HighPart << 16) + LowPart).ToString("X8"));
continue;
}
AnalyzedCode.Add((UInt32)Instruction.Address, Instruction);
int IndexOfIndirectConstant = Instruction.Operand.IndexOf("[pc, #0x");
if (IndexOfIndirectConstant >= 0)
{
int IndexOfEnd = Instruction.Operand.IndexOf("]", IndexOfIndirectConstant);
string PCOffsetString = Instruction.Operand.Substring(IndexOfIndirectConstant + 8, IndexOfEnd - IndexOfIndirectConstant - 8);
UInt32 PCOffset = UInt32.Parse(PCOffsetString, System.Globalization.NumberStyles.HexNumber);
UInt32 PC = (UInt32)Instruction.Address + 4;
UInt32 PCforIndirect = PC - (PC % 4);
UInt32 VirtualAddressOfIndirectConstant = PCforIndirect + PCOffset;
// If the address is outside the range of the section, then this is probably data which is compiled as code.
// In this case we will ignore this and not do this part of the analysis.
if ((VirtualAddressOfIndirectConstant >= CurrentSection.VirtualAddress) && (VirtualAddressOfIndirectConstant < (CurrentSection.VirtualAddress + CurrentSection.VirtualSize)))
{
UInt32 RawOffsetOfIndirectConstant = VirtualAddressOfIndirectConstant - CurrentSection.VirtualAddress;
UInt32 IndirectConstant = BitConverter.ToUInt32(CurrentSection.Buffer, (int)RawOffsetOfIndirectConstant);
Instruction.Operand = Instruction.Operand.Substring(0, IndexOfIndirectConstant) + "#0x" + IndirectConstant.ToString("x8") + Instruction.Operand[(IndexOfEnd + 1)..];
}
}
if (JumpCommands.Contains(Instruction.Mnemonic))
{
UInt32 NewAddress = UInt32.Parse(Instruction.Operand[(Instruction.Operand.IndexOf("#0x") + 3)..], System.Globalization.NumberStyles.HexNumber);
NewAddress -= (NewAddress % 2);
if (((NewAddress < StartAddress) || (NewAddress > EndAddress)) && !AddressesToAnalyze.Any(a => a == NewAddress))
AddressesToAnalyze.Add(NewAddress);
}
PreviousInstruction = Instruction;
}
}
AddressesToAnalyze.RemoveAt(0);
}
}
public static string[] JumpCommands = new string[]
{
"b", "b.w", "bl", "bl.w", "beq", "beq.w", "bne", "bne.w", "bhs", "bhs.w", "blo", "blo.w",
"bmi", "bmi.w", "bpl", "bpl.w", "bvs", "bvs.w", "bvc", "bvc.w", "bhi", "bhi.w", "bls", "bls.w",
"bge", "bge.w", "blt", "blt.w", "bgt", "bgt.w", "ble", "ble.w", "bal", "bal.w", "cbnz", "cbz"
};
public static string[] ConditionalJumpInstructions = new string[]
{
"beq", "beq.w", "bne", "bne.w", "bhs", "bhs.w", "blo", "blo.w", "bmi", "bmi.w",
"bpl", "bpl.w", "bvs", "bvs.w", "bvc", "bvc.w", "bhi", "bhi.w", "bls", "bls.w",
"bge", "bge.w", "blt", "blt.w", "bgt", "bgt.w", "ble", "ble.w", "bal", "bal.w", "cbnz", "cbz"
};
public static string WriteCode(SortedDictionary<UInt32, ArmInstruction> AnalyzedCode)
{
StringBuilder Code = new(1000);
foreach (var Instruction in AnalyzedCode)
{
Code.AppendFormat("{0:X}: \t {1} \t {2}\r\n", Instruction.Value.Address, Instruction.Value.Mnemonic, Instruction.Value.Operand);
}
return Code.ToString();
}
}
public class ArmInstruction
{
public UInt32 Address;
public byte[] Bytes;
public string Mnemonic;
public string Operand;
public ArmInstruction()
{
}
public ArmInstruction(string Assembly)
{
Address = UInt32.Parse(Assembly.Substring(0, 8), System.Globalization.NumberStyles.HexNumber);
string Hex = Assembly.Substring(12, 24).Trim();
Bytes = new byte[(Hex.Length + 1) / 3];
for (int i = 0; i < Bytes.Length; i++)
Bytes[i] = byte.Parse(Hex.Substring(i * 3, 2), System.Globalization.NumberStyles.HexNumber);
Mnemonic = Assembly.Substring(39, 16).Trim();
Operand = Assembly[55..];
}
public override string ToString()
{
StringBuilder Result = new();
Result.Append(Address.ToString("X8")); // 0
Result.Append(" ");
for (int i = 0; i < Bytes.Length; i++) // 12
{
Result.Append(Bytes[i].ToString("X2"));
Result.Append(' ');
}
Result.Append(new String(' ', (8 - Bytes.Length) * 3));
Result.Append(" ");
Result.Append(Mnemonic.PadRight(16)); // 39
Result.Append(Operand); // 55
return Result.ToString();
}
}
public class AnalyzedFile
{
public PeFile File;
public SortedList<UInt32, ArmInstruction> Code;
}
}
+56
View File
@@ -0,0 +1,56 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net5.0-windows</TargetFramework>
<OutputType>WinExe</OutputType>
<RootNamespace>Patcher</RootNamespace>
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
<UseWindowsForms>true</UseWindowsForms>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x86'">
<OutputPath>bin\x86\Debug\</OutputPath>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x86'">
<OutputPath>bin\x86\Release\</OutputPath>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
<OutputPath>bin\x64\Debug\</OutputPath>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
<OutputPath>bin\x64\Release\</OutputPath>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<ItemGroup>
<Compile Include="..\Patcher\ArmCompiler.cs">
<Link>ArmCompiler.cs</Link>
</Compile>
<Compile Include="..\Patcher\ByteOperations.cs">
<Link>ByteOperations.cs</Link>
</Compile>
<Compile Include="..\Patcher\HelperClasses.cs">
<Link>HelperClasses.cs</Link>
</Compile>
<Compile Include="..\Patcher\ObjectFileParser.cs">
<Link>ObjectFileParser.cs</Link>
</Compile>
<Compile Include="..\Patcher\PatchEngine.cs">
<Link>PatchEngine.cs</Link>
</Compile>
<Compile Include="..\Patcher\PeFile.cs">
<Link>PeFile.cs</Link>
</Compile>
<None Include="..\Patcher\LICENSE">
<Link>LICENSE</Link>
</None>
<None Update="BootUnllockAndRootAccessPatchScript.pds">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
</ItemGroup>
<ItemGroup>
<PackageReference Include="Gee.External.Capstone" Version="2.0.2" />
<PackageReference Include="Microsoft.CSharp" Version="4.7.0" />
<PackageReference Include="System.Data.DataSetExtensions" Version="4.5.0" />
</ItemGroup>
</Project>
@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup />
<ItemGroup>
<Compile Update="MainForm.cs">
<SubType>Form</SubType>
</Compile>
</ItemGroup>
</Project>
@@ -0,0 +1,698 @@
// Copyright (c) 2018, Rene Lergner - wpinternals.net - @Heathcliff74xda
//
// Patch Definition Script for Boot Unlock and Root Access on Windows Mobile
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
PatchDefinition Name="RootAccess-MainOS" VersionFrom="EFIESP\Windows\System32\Boot\mobilestartup.efi"
PatchFile Path="Windows\System32\sspisrv.dll"
JumpToImport "RpcImpersonateClient"
JumpToReference
FindPreviousInstruction "PUSH.W"
CreateLabel "CheckLowboxAccess" // Optional here
PatchCode
MOVS R1, #1
STR R1, [R0]
MOVS R0, #0
BX LR
EndPatch
PatchChecksum
PatchFile Path="Windows\System32\NtlmShared.dll"
JumpToExport "MsvpPasswordValidate"
PatchCode
MOVS R0, #1
BX LR
EndPatch
PatchChecksum
PatchFile Path="Windows\System32\pacmanserver.dll"
FindFirstUnicode "GetMaxCountForDeployedApp"
JumpToReference
FindPreviousInstruction "PUSH.W"
PatchCode
LDR R1, =0x7FFFFFFF
STR R1, [R0]
MOVS R0, #0
BX LR
EndPatch
PatchChecksum
PatchFile Path="Windows\System32\mscoree.dll"
JumpToImport "GetModuleFileNameW"
JumpToReference
FindPreviousInstruction "PUSH.W"
CreateLabel "CompareWithWhiteList" // Optional here
PatchCode
MOVS R0, #0
BX LR
EndPatch
PatchChecksum
PatchFile Path="Windows\System32\DeploymentExt.dll"
FindFirstUnicode "MaxUnsignedApp"
JumpToReference
FindValue 0x800413A0
FindPreviousConditionalJump
MakeJumpUnconditional
PatchChecksum
PatchFile Path="Windows\System32\ntoskrnl.exe"
// Fase 1: find all kernel-functions
JumpToExport "SeAccessCheckWithHint"
CreateLabel "SeAccessCheckWithHint"
FindFunctionCall R0 = "ADD R0, SP, #0x7C" R1 = "MOV R1, R?"
JumpToTarget
CreateLabel "SepFilterToDiscretionary"
JumpToReference R0 = "ADDS R0, R?, #0xD0"
FindPreviousInstruction "PUSH"
FindPreviousInstruction "PUSH"
CreateLabel "SeAccessCheckByType"
FindFunctionCall R0 = "ADDS R0, R?, #0xF8" R1 = "MOV R1, R?" R2 = "LDR R2, [R?,#0x28]" R3 = "MOV R3, R?"
JumpToTarget
CreateLabel "SepConstrainByMandatory"
JumpBack // to SeAccessCheckByType
JumpBack // to SepFilterToDiscretionary
JumpToReference R1 = "LDR R1, [R?,#8]"
FindPreviousInstruction "PUSH"
CreateLabel "SepCommonAccessCheckEx"
FindFunctionCall Result = "STR R0, [SP,#0xD4]"
JumpToTarget
CreateLabel "SepAccessCheckEx"
JumpBack // to SepCommonAccessCheckEx
JumpBack // to SepFilterToDiscretionary
JumpToReference R0 = "ADDS R0, R?, #0x130"
FindPreviousInstruction "PUSH"
FindPreviousInstruction "PUSH"
CreateLabel "SepAccessCheckAndAuditAlarm"
FindFunctionCall R0 = "LDR R0, [R?,#0x130]" R1 = "MOV R1, R?" R2 = "LDR R2, [R?,#0x50]" R3 = "MOV R3, R?"
JumpToTarget
CreateLabel "SepConstrainByConstraintMask"
FindNextConditionalJump
JumpToTarget
CreateLabel "SepConstrainByConstraintMask_FunctionChunk01"
JumpBack // to SepConstrainByConstraintMask
JumpBack // to SepAccessCheckAndAuditAlarm
JumpBack // to SepFilterToDiscretionary
JumpBack // to SeAccessCheckWithHint
FindFunctionCall R0 = "ADD R0, SP, #0x88" R1 = "MOV R1, R?"
JumpToTarget
CreateLabel "SepMandatoryToDiscretionary"
JumpBack
FindFunctionCall Result = "STR R0, [SP,#0x70]"
JumpToTarget
CreateLabel "SepAccessCheck"
JumpToExport "SePrivilegeCheck"
FindFunctionCall
JumpToTarget
CreateLabel "SepPrivilegeCheck"
JumpToExport "SeSinglePrivilegeCheck"
CreateLabel "SeSinglePrivilegeCheck"
JumpToExport "ObReferenceObjectByHandleWithTag"
CreateLabel "ObReferenceObjectByHandleWithTag"
// Fase 2: patches
JumpToLabel "SeAccessCheckByType"
// Patch 1:
FindNextValue 0xC0000022
FindPreviousConditionalJump
FindPreviousConditionalJump
FindPreviousConditionalJump
FindPreviousConditionalJump
MakeJumpUnconditional
FindNextValue 0xC0000022
// Patch 2:
FindNextValue 0xC0000022
FindStore
FindPreviousConditionalJump
MakeJumpUnconditional
// Patch 3:
FindNextValue 0xC0000022
FindPreviousConditionalJump
MakeJumpUnconditional // This jump is right above the value 0xC0000022. After patch the pointer is back on that value.
// FindNextValue 0xC0000022
// Patch 4:
FindNextValue 0xC0000022
FindPreviousConditionalJump
MakeJumpUnconditional // This jump is right above the value 0xC0000022. After patch the pointer is back on that value.
// FindNextValue 0xC0000022
// Patch 5:
FindNextValue 0xC0000022
FindNextInstruction "BNE"
JumpToTarget
CreateLabel "TargetPatch5"
JumpBack
FindPreviousInstruction "BEQ"
PatchCode
B TargetPatch5
EndPatch
// Patch 6:
FindNextValue 0xC0000022
FindNextConditionalJump
MakeJumpUnconditional
// Patch 7:
FindNextValue 0xC0000022
FindStore
FindPreviousConditionalJump
MakeJumpUnconditional
// Patch 8:
FindNextValue 0xC0000022
JumpToReference
ClearInstruction
JumpBack
// Patch 9:
FindNextValue 0xC0000022
JumpToReference
ClearInstruction
JumpBack
JumpToLabel "SepAccessCheckAndAuditAlarm"
// Patch 10:
FindNextValue 0xC0000022
FindPreviousConditionalJump
MakeJumpUnconditional
FindNextValue 0xC0000022
// Patch 11:
FindNextValue 0xC0000022
FindStore
CreateLabel "Patch11"
FindNextConditionalJump
JumpToTarget
CreateLabel "TargetPatch11"
JumpToLabel "Patch11"
PatchCode
B TargetPatch11
EndPatch
// Patch 12:
FindNextValue 0xC0000022
PatchCode
MOV.W R2, #0
EndPatch
JumpToLabel "SepCommonAccessCheckEx"
// Patch 13:
FindNextInstruction "TST"
FindNextInstruction "TST"
FindPreviousConditionalJump
ClearInstruction
JumpToLabel "SeAccessCheckWithHint"
// Patch 14:
FindNextInstruction "BEQ"
MakeJumpUnconditional
JumpToLabel "SeSinglePrivilegeCheck"
// Patch 15:
PatchCode
MOVS R0, #1
BX LR
EndPatch
JumpToLabel "ObReferenceObjectByHandleWithTag"
FindFunctionCall
JumpToTarget
CreateLabel "ObpReferenceObjectByHandleWithTag"
FindInstructionPattern "LDR R?, [R?,#0x74]; CMP R?, #0; BNE ?" InstructionIndex = 2
JumpToTarget
// Patch 16:
FindNextConditionalJump
MakeJumpUnconditional // This jump is right above the value 0xC0000022. After patch the pointer is on the error-value.
// Patch 17:
JumpToReference
ClearInstruction
JumpBack
JumpBack
// Patch 18:
FindNextValue 0xC0000022
JumpToReference
ClearInstruction
JumpToLabel "SepPrivilegeCheck"
// Patch 19:
PatchCode
MOVS R0, #1
BX LR
EndPatch
JumpToLabel "SepMandatoryToDiscretionary"
// Patch 20:
PatchCode
MOVS R0, #0
BX LR
EndPatch
JumpToLabel "SepAccessCheckEx"
// Patch 21:
FindNextValue 0x2000000
CreateLabel "Patch21"
FindNextInstruction "B"
JumpToTarget
CreateLabel "TargetPatch21"
JumpToLabel "Patch21"
PatchCode
B TargetPatch21
EndPatch
FindNextValue 0xC0000022
// Patch 22:
FindNextValue 0xC0000022
FindPreviousConditionalJump
MakeJumpUnconditional // This jump is right above the value 0xC0000022. After patch the pointer is back on that value.
// FindNextValue 0xC0000022
// Patch 23:
JumpToReference 0
ClearInstruction
JumpBack
// Patch 24:
JumpToReference 1
ClearInstruction
JumpBack
// Patch 25:
JumpToReference 2
ClearInstruction
JumpBack
// Patch 26:
FindNextValue 0xC0000022
FindPreviousConditionalJump
MakeJumpUnconditional
FindNextValue 0xC0000022
// Patch 27:
FindNextValue 0xC0000022
FindPreviousConditionalJump
MakeJumpUnconditional
FindNextValue 0xC0000022
// Patch 28:
JumpToReference
ClearInstruction
JumpToLabel "SepAccessCheck"
// Patch 29:
FindFunctionCall R0 = "LDR R0, [SP,#0x28]"
JumpToTarget
CreateLabel "SepNormalAccessCheck"
JumpBack
FindNextInstruction "TST"
FindNextConditionalJump
ClearInstruction
// Patch 30:
FindFunctionCall R0 = "MOV R0, R?" R1 = "MOV R1, R?" R2 = "MOV R2, R?" R3 = "LDR R3, [SP,#0x38]"
JumpToTarget
CreateLabel "SepMaximumAccessCheck"
JumpBack
FindNextConditionalJump
ClearInstruction
// Patch 31:
FindNextConditionalJump
ClearInstruction
// Patch 32:
FindNextValue 0xC0000022
JumpToReference 1
ClearInstruction
JumpBack
// Patch 33:
JumpToReference 2
ClearInstruction
JumpBack
// Patch 34:
FindNextValue 0xC0000022
FindPreviousInstruction "MOVS"
FindPreviousInstruction "MOVS"
JumpToReference
ClearInstruction
JumpBack
FindNextValue 0xC0000022
// Patch 35:
JumpToReference CodePattern = "BEQ"
ClearInstruction
JumpBack
// Patch 36:
JumpToReference CodePattern = "MOVS; B"
FindPreviousInstruction "B"
JumpToTarget
CreateLabel "TargetPatch36"
JumpBack
FindPreviousInstruction "CMP"
PatchCode
B.W TargetPatch36
EndPatch
JumpBack
// Patch 37:
JumpToReference CodePattern = "STR; B"
FindPreviousConditionalJump
MakeJumpUnconditional
// Patch 38:
// Stay in function-chunk. Error-code is between previous two patches.
FindPreviousValue 0xC0000022
FindPreviousConditionalJump
MakeJumpUnconditional
JumpToLabel "SepConstrainByMandatory"
// Patch 39:
FindNextInstruction "BNE"
JumpToTarget
FindNextInstruction "CBNZ"
JumpToTarget
CreateLabel "TargetPatch39"
JumpBack
FindPreviousInstruction "BEQ"
PatchCode
B TargetPatch39
EndPatch
JumpBack
// Patch 40:
FindNextInstruction "B"
JumpToTarget
FindNextInstruction "CBNZ"
JumpToTarget
CreateLabel "TargetPatch40"
JumpBack
FindPreviousInstruction "BEQ"
PatchCode
B TargetPatch40
EndPatch
JumpToLabel "SepFilterToDiscretionary"
// Patch 41:
PatchCode
MOVS R0, #0
BX LR
EndPatch
JumpToLabel "SepConstrainByConstraintMask_FunctionChunk01"
// Patch 42:
FindNextInstruction "TST"
FindNextInstruction "CBNZ"
JumpToTarget
CreateLabel "TargetPatch42"
JumpBack
FindPreviousInstruction "BEQ"
PatchCode
B TargetPatch42
EndPatch
// Patch 43:
FindNextInstruction "TST"
FindNextInstruction "CBNZ"
JumpToTarget
CreateLabel "TargetPatch43"
JumpBack
FindPreviousInstruction "BEQ"
FindPreviousInstruction "BEQ" // This one is actually not necessary. Kept here for consistency.
PatchCode
B TargetPatch43
EndPatch
PatchChecksum
PatchDefinition Name="SecureBootHack-MainOS" VersionFrom="EFIESP\Windows\System32\Boot\mobilestartup.efi"
PatchFile Path="Windows\System32\BOOT\winload.efi"
FindFirstAscii "1.3.6.1.4.1.311.61.4.1"
JumpToReference
FindPreviousInstruction "PUSH.W"
CreateLabel "ImgpValidateImageHash"
PatchCode
MOVS R0, #0
BX LR
EndPatch
PatchChecksum
PatchFile Path="Windows\System32\ci.dll"
JumpToImport "PsGetProcessSignatureLevel"
JumpToReference
CreateLabel "PsGetProcessSignatureLevelWrapper"
JumpToReference
FindPreviousInstruction "PUSH.W"
CreateLabel "CipReportAndReprieveUMCIFailure"
FindNextInstruction "TST.W"
FindNextConditionalJump
MakeJumpUnconditional "BNE" // BNE -> B, BEQ -> NOP
PatchChecksum
PatchDefinition Name="SecureBootHack-V1-EFIESP" VersionFrom="EFIESP\Windows\System32\Boot\mobilestartup.efi" RelativePath="EFIESP" RelativeOutputPath="SecureBootHack-V1"
PatchFile Path="Windows\System32\boot\mobilestartup.efi" // Symbols taken from pdb from version 10.0.10586.107
FindFirstAscii "1.3.6.1.4.1.311.61.4.1"
JumpToReference
FindPreviousInstruction "PUSH.W"
CreateLabel "ImgpValidateImageHash"
PatchCode
MOVS R0, #0
BX LR
EndPatch
FindFirstUnicode "BootDebugPolicyApplied"
JumpToReference
FindPreviousInstruction "PUSH.W"
CreateLabel "ApplyBootDebugPolicy"
PatchCode // This patch is for the new unlock for Lumia Spec A
MOVS R0, #0
BX LR
EndPatch
PatchChecksum
PatchFile Path="efi\boot\bootarm.efi"
FindFirstAscii "1.3.6.1.4.1.311.61.4.1"
JumpToReference
FindPreviousInstruction "PUSH.W"
CreateLabel "ImgpValidateImageHash"
PatchCode
MOVS R0, #0
BX LR
EndPatch
PatchChecksum
PatchDefinition Name="SecureBootHack-V2-EFIESP" VersionFrom="EFIESP\Windows\System32\Boot\mobilestartup.efi" RelativePath="EFIESP"
PatchFile Path="Windows\System32\boot\mobilestartup.efi"
FindFirstAscii "MZ"
CreateLabel "ImageBase"
FindFirstAscii "1.3.6.1.4.1.311.61.4.1"
JumpToReference
FindPreviousInstruction "PUSH.W"
CreateLabel "ImgpValidateImageHash"
PatchCode
MOVS R0, #0
BX LR
EndPatch
FindFirstUnicode "BootDebugPolicyApplied"
JumpToReference
FindPreviousInstruction "PUSH.W"
CreateLabel "ApplyBootDebugPolicy"
PatchCode
MOVS R0, #0
BX LR
EndPatch
CreateLabel "EnterMassStorageModeShellCode" // Use the left-over space of the ApplyBootDebugPolicy-function to insert shell-code later on
FindFirstUnicode "MassStorageFlag"
CreateLabel "MassStorageName"
PatchUnicode "Heathcliff74MSM"
FindFirstBytes "41 E5 C1 A0 CE 73 7F 46 88 EC D4 4F 92 34 50 4A"
CreateLabel "MassStorageGuid"
JumpToLabel "MassStorageName"
JumpToReference
FindNextInstruction "BL"
JumpToTarget
CreateLabel "EfiGetVariableVolatile"
FindValue 2
FindNextConditionalJump
MakeJumpUnconditional "BEQ"
FindFirstUnicode "\Windows\System32\boot\ui\boot.ums.waiting.bmpx"
JumpToReference
FindPreviousInstruction "PUSH.W"
CreateLabel "EnterMassStorageMode"
JumpToReference
PatchCode
B.W EnterMassStorageModeShellCode
EndPatch
CreateLabel ReturnFromMassStorageMode
FindFirstValue 0x26000145
IfNotFoundGo PatchForSetErrorDone
FindPreviousInstruction "PUSH.W"
CreateLabel "SetError"
PatchCode
MOVS R0, #1
BX LR
EndPatch
PatchForSetErrorDone:
FindFirstUnicode "DeviceIDVersion"
JumpToReference
FindNextInstruction "BL"
JumpToTarget
CreateLabel "EfiSetVariable"
FindFirstAscii "charge: DisplayPowerState protocol successfully loaded"
JumpToReference
FindPreviousInstruction "PUSH.W"
CreateLabel "InitGraphicsSubsystem"
FindNextInstruction "BL"
JumpToTarget
CreateLabel "BlpArchQueryCurrentContextType"
JumpBack
FindNextInstruction "BL"
FindNextInstruction "BL"
FindNextInstruction "BL"
JumpToTarget
CreateLabel "BlpArchSwitchContext"
JumpBack
FindNextInstruction "LDR"
JumpToTarget
CreateLabel "EfiBS"
JumpToLabel "EnterMassStorageModeShellCode"
PatchCode
MOV R0, PC
LDR R1, =(ApplyBootDebugPolicy - ImageBase + 8) // Subtract (Offset of shell-code + 4)
SUB R0, R0, R1 // R0 = relocated base of mobilestartup.efi
PUSH {R4-R6}
SUB SP, SP, #4
MOV R4, R0 // R4 = relocated base of mobilestartup.efi
LDR R3, =(MassStorageName - ImageBase) // Offset of NV var name (which is patched to "Heathcliff74MSM")
ADD R0, R4, R3
LDR R3, =(MassStorageGuid - ImageBase) // Offset of NV var Guid
ADD R1, R4, R3
MOVS R2, #3 // Non-volatile, boot-services
MOVS R3, #0 // Data-size
STR R3, [SP] // Pointer to data-buffer = NULL
LDR R6, =(EfiSetVariable - ImageBase + 1) // Offset of SetVariable + 1
ADD R5, R4, R6
BLX R5 // EfiSetVariable -> Delete variable
LDR R1, =(BlpArchQueryCurrentContextType - ImageBase + 1) // Offset to first thread-function + 1
ADD R5, R4, R1
BLX R5
MOV R6, R0
CMP R6, #1
BEQ ContextSwitchDone1
MOVS R0, #1
LDR R1, =(BlpArchSwitchContext - ImageBase + 1) // Offset to second thread-function + 1
ADD R5, R4, R1
BLX R5
ContextSwitchDone1:
LDR R0, =(EfiBS - ImageBase) // Offset of pointer to BootServices function-table
ADD R1, R4, R0 // R1 = pointer to pointer to BootServices function-table
LDR R1, [R1] // R1 = pointer to BootServices function-table
LDR.W R5, [R1,#0xAC] // LocateProtocol
ADR R0, VarServicesGuid // This is relative, no need to relocate
MOVS R1, #0
MOV R2, SP
BLX R5 // LocateProtocol - pVarServices in [SP]
LDR R5, [SP] // R5 = Pointer to VariableServices interface
LDR R5, [R5,#4] // R5 = pointer to FlushVariableNV()
CMP R5, #0
BNE PointerFound
LDR R5, [SP] // R5 = Pointer to VariableServices interface
LDR R5, [R5,#8] // R5 = pointer to FlushVariableNV()
PointerFound:
BLX R5 // FlushVariableNV()
CMP R6, #1
BEQ ContextSwitchDone2
MOV R0, R6
LDR R1, =(BlpArchSwitchContext - ImageBase + 1) // Offset to second thread-function + 1
ADD R5, R4, R1
BLX R5
ContextSwitchDone2:
LDR R6, =(EnterMassStorageMode - ImageBase + 1) // Offset of EnterMassStorageMode + 1
ADD R5, R4, R6
BLX R5 // EnterMassStorageMode
LDR R6, =(ReturnFromMassStorageMode - ImageBase + 1) // Offset of return address + 1
ADD R0, R4, R6
ADD SP, SP, #4
POP {R4-R6}
BX R0
VarServicesGuid:
DCD 0xf9085b9d
DCW 0x9304, 0x40fb
DCB 0x8f, 0xe0, 0x4a, 0xee, 0x3b, 0x1a, 0x78, 0x4b
EndPatch
PatchChecksum
+120
View File
@@ -0,0 +1,120 @@
// This class was found online.
// Original author is probably: Swizzy
// https://github.com/ttgxdinger/Random/blob/master/CPUKey%20Checker/CPUKey%20Checker/FolderSelectDialog.cs
using System;
using System.Windows.Forms;
namespace WPinternals
{
/// <summary>
/// Wraps System.Windows.Forms.OpenFileDialog to make it present
/// a vista-style dialog.
/// </summary>
public class FolderSelectDialog
{
// Wrapped dialog
private readonly OpenFileDialog ofd = null;
/// <summary>
/// Default constructor
/// </summary>
public FolderSelectDialog()
{
ofd = new OpenFileDialog
{
Filter = "Folders|\n",
AddExtension = false,
CheckFileExists = false,
DereferenceLinks = true,
Multiselect = false
};
}
#region Properties
/// <summary>
/// Gets/Sets the initial folder to be selected. A null value selects the current directory.
/// </summary>
public string InitialDirectory
{
get { return ofd.InitialDirectory; }
set { ofd.InitialDirectory = string.IsNullOrEmpty(value) ? Environment.CurrentDirectory : value; }
}
/// <summary>
/// Gets/Sets the title to show in the dialog
/// </summary>
public string Title
{
get { return ofd.Title; }
set { ofd.Title = value ?? "Select a folder"; }
}
/// <summary>
/// Gets the selected folder
/// </summary>
public string FileName
{
get { return ofd.FileName; }
}
#endregion
#region Methods
/// <summary>
/// Shows the dialog
/// </summary>
/// <returns>True if the user presses OK else false</returns>
public bool ShowDialog()
{
return ShowDialog(IntPtr.Zero);
}
/// <summary>
/// Shows the dialog
/// </summary>
/// <param name="hWndOwner">Handle of the control to be parent</param>
/// <returns>True if the user presses OK else false</returns>
public bool ShowDialog(IntPtr hWndOwner)
{
var fbd = new FolderBrowserDialog
{
Description = this.Title,
SelectedPath = this.InitialDirectory,
ShowNewFolderButton = false
};
if (fbd.ShowDialog(new WindowWrapper(hWndOwner)) != DialogResult.OK)
{
return false;
}
ofd.FileName = fbd.SelectedPath;
return true;
}
#endregion
}
/// <summary>
/// Creates IWin32Window around an IntPtr
/// </summary>
public class WindowWrapper : IWin32Window
{
/// <summary>
/// Constructor
/// </summary>
/// <param name="handle">Handle to wrap</param>
public WindowWrapper(IntPtr handle)
{
Handle = handle;
}
/// <summary>
/// Original ptr
/// </summary>
public IntPtr Handle { get; }
}
}
+423
View File
@@ -0,0 +1,423 @@
namespace Patcher
{
partial class MainForm
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.label1 = new System.Windows.Forms.Label();
this.txtVisualStudioPath = new System.Windows.Forms.TextBox();
this.FolderBrowserDialog = new System.Windows.Forms.FolderBrowserDialog();
this.OpenFileDialog = new System.Windows.Forms.OpenFileDialog();
this.SaveFileDialog = new System.Windows.Forms.SaveFileDialog();
this.cmdVisualStudioPath = new System.Windows.Forms.Button();
this.cmdInputFolder = new System.Windows.Forms.Button();
this.txtInputFolder = new System.Windows.Forms.TextBox();
this.label2 = new System.Windows.Forms.Label();
this.cmdOutputFolder = new System.Windows.Forms.Button();
this.txtOutputFolder = new System.Windows.Forms.TextBox();
this.label3 = new System.Windows.Forms.Label();
this.cmdPatchDefinitionsFile = new System.Windows.Forms.Button();
this.txtPatchDefinitionsFile = new System.Windows.Forms.TextBox();
this.label4 = new System.Windows.Forms.Label();
this.txtConsole = new System.Windows.Forms.TextBox();
this.label9 = new System.Windows.Forms.Label();
this.cmdCompile = new System.Windows.Forms.Button();
this.cmdPatch = new System.Windows.Forms.Button();
this.cmdScriptFile = new System.Windows.Forms.Button();
this.txtScriptFile = new System.Windows.Forms.TextBox();
this.label5 = new System.Windows.Forms.Label();
this.cmdBackupFolder = new System.Windows.Forms.Button();
this.txtBackupFolder = new System.Windows.Forms.TextBox();
this.label6 = new System.Windows.Forms.Label();
this.label7 = new System.Windows.Forms.Label();
this.CapstoneLink = new System.Windows.Forms.LinkLabel();
this.label8 = new System.Windows.Forms.Label();
this.CapstoneNetLink = new System.Windows.Forms.LinkLabel();
this.label10 = new System.Windows.Forms.Label();
this.SuspendLayout();
//
// label1
//
this.label1.AutoSize = true;
this.label1.Location = new System.Drawing.Point(15, 13);
this.label1.Name = "label1";
this.label1.Size = new System.Drawing.Size(191, 13);
this.label1.TabIndex = 0;
this.label1.Text = "Path to Visual Studio with ARM32 SDK";
//
// txtVisualStudioPath
//
this.txtVisualStudioPath.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.txtVisualStudioPath.Location = new System.Drawing.Point(18, 29);
this.txtVisualStudioPath.Name = "txtVisualStudioPath";
this.txtVisualStudioPath.Size = new System.Drawing.Size(665, 20);
this.txtVisualStudioPath.TabIndex = 1;
//
// OpenFileDialog
//
this.OpenFileDialog.FileName = "openFileDialog1";
//
// cmdVisualStudioPath
//
this.cmdVisualStudioPath.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
this.cmdVisualStudioPath.Font = new System.Drawing.Font("Arial", 9.75F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.cmdVisualStudioPath.Location = new System.Drawing.Point(689, 28);
this.cmdVisualStudioPath.Name = "cmdVisualStudioPath";
this.cmdVisualStudioPath.Size = new System.Drawing.Size(35, 22);
this.cmdVisualStudioPath.TabIndex = 2;
this.cmdVisualStudioPath.Text = "...";
this.cmdVisualStudioPath.UseVisualStyleBackColor = true;
this.cmdVisualStudioPath.Click += new System.EventHandler(this.cmdVisualStudioPath_Click);
//
// cmdInputFolder
//
this.cmdInputFolder.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
this.cmdInputFolder.Font = new System.Drawing.Font("Arial", 9.75F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.cmdInputFolder.Location = new System.Drawing.Point(689, 224);
this.cmdInputFolder.Name = "cmdInputFolder";
this.cmdInputFolder.Size = new System.Drawing.Size(35, 22);
this.cmdInputFolder.TabIndex = 8;
this.cmdInputFolder.Text = "...";
this.cmdInputFolder.UseVisualStyleBackColor = true;
this.cmdInputFolder.Click += new System.EventHandler(this.cmdInputFolder_Click);
//
// txtInputFolder
//
this.txtInputFolder.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.txtInputFolder.Location = new System.Drawing.Point(18, 225);
this.txtInputFolder.Name = "txtInputFolder";
this.txtInputFolder.Size = new System.Drawing.Size(665, 20);
this.txtInputFolder.TabIndex = 7;
//
// label2
//
this.label2.AutoSize = true;
this.label2.Location = new System.Drawing.Point(15, 209);
this.label2.Name = "label2";
this.label2.Size = new System.Drawing.Size(71, 13);
this.label2.TabIndex = 12;
this.label2.Text = "Input location";
//
// cmdOutputFolder
//
this.cmdOutputFolder.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
this.cmdOutputFolder.Font = new System.Drawing.Font("Arial", 9.75F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.cmdOutputFolder.Location = new System.Drawing.Point(689, 322);
this.cmdOutputFolder.Name = "cmdOutputFolder";
this.cmdOutputFolder.Size = new System.Drawing.Size(35, 22);
this.cmdOutputFolder.TabIndex = 12;
this.cmdOutputFolder.Text = "...";
this.cmdOutputFolder.UseVisualStyleBackColor = true;
this.cmdOutputFolder.Click += new System.EventHandler(this.cmdOutputFolder_Click);
//
// txtOutputFolder
//
this.txtOutputFolder.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.txtOutputFolder.Location = new System.Drawing.Point(18, 323);
this.txtOutputFolder.Name = "txtOutputFolder";
this.txtOutputFolder.Size = new System.Drawing.Size(665, 20);
this.txtOutputFolder.TabIndex = 11;
//
// label3
//
this.label3.AutoSize = true;
this.label3.Location = new System.Drawing.Point(15, 307);
this.label3.Name = "label3";
this.label3.Size = new System.Drawing.Size(125, 13);
this.label3.TabIndex = 15;
this.label3.Text = "Output location (optional)";
//
// cmdPatchDefinitionsFile
//
this.cmdPatchDefinitionsFile.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
this.cmdPatchDefinitionsFile.Font = new System.Drawing.Font("Arial", 9.75F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.cmdPatchDefinitionsFile.Location = new System.Drawing.Point(689, 91);
this.cmdPatchDefinitionsFile.Name = "cmdPatchDefinitionsFile";
this.cmdPatchDefinitionsFile.Size = new System.Drawing.Size(35, 22);
this.cmdPatchDefinitionsFile.TabIndex = 4;
this.cmdPatchDefinitionsFile.Text = "...";
this.cmdPatchDefinitionsFile.UseVisualStyleBackColor = true;
this.cmdPatchDefinitionsFile.Click += new System.EventHandler(this.cmdPatchDefinitionsFile_Click);
//
// txtPatchDefinitionsFile
//
this.txtPatchDefinitionsFile.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.txtPatchDefinitionsFile.Location = new System.Drawing.Point(18, 92);
this.txtPatchDefinitionsFile.Name = "txtPatchDefinitionsFile";
this.txtPatchDefinitionsFile.Size = new System.Drawing.Size(665, 20);
this.txtPatchDefinitionsFile.TabIndex = 3;
this.txtPatchDefinitionsFile.Leave += new System.EventHandler(this.txtPatchDefinitionsFile_Leave);
//
// label4
//
this.label4.AutoSize = true;
this.label4.Location = new System.Drawing.Point(15, 76);
this.label4.Name = "label4";
this.label4.Size = new System.Drawing.Size(117, 13);
this.label4.TabIndex = 3;
this.label4.Text = "Patch defintions xml-file";
//
// txtConsole
//
this.txtConsole.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
| System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.txtConsole.Font = new System.Drawing.Font("Courier New", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.txtConsole.Location = new System.Drawing.Point(18, 383);
this.txtConsole.Multiline = true;
this.txtConsole.Name = "txtConsole";
this.txtConsole.ScrollBars = System.Windows.Forms.ScrollBars.Vertical;
this.txtConsole.Size = new System.Drawing.Size(706, 392);
this.txtConsole.TabIndex = 13;
//
// label9
//
this.label9.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.label9.AutoSize = true;
this.label9.Location = new System.Drawing.Point(15, 367);
this.label9.Name = "label9";
this.label9.Size = new System.Drawing.Size(78, 13);
this.label9.TabIndex = 24;
this.label9.Text = "Console output";
//
// cmdCompile
//
this.cmdCompile.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
this.cmdCompile.Location = new System.Drawing.Point(470, 792);
this.cmdCompile.Name = "cmdCompile";
this.cmdCompile.Size = new System.Drawing.Size(120, 33);
this.cmdCompile.TabIndex = 14;
this.cmdCompile.Text = "Compile";
this.cmdCompile.UseVisualStyleBackColor = true;
this.cmdCompile.Click += new System.EventHandler(this.cmdCompile_Click);
//
// cmdPatch
//
this.cmdPatch.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
this.cmdPatch.Location = new System.Drawing.Point(604, 792);
this.cmdPatch.Name = "cmdPatch";
this.cmdPatch.Size = new System.Drawing.Size(120, 33);
this.cmdPatch.TabIndex = 15;
this.cmdPatch.Text = "Patch";
this.cmdPatch.UseVisualStyleBackColor = true;
this.cmdPatch.Click += new System.EventHandler(this.cmdPatch_Click);
//
// cmdScriptFile
//
this.cmdScriptFile.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
this.cmdScriptFile.Font = new System.Drawing.Font("Arial", 9.75F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.cmdScriptFile.Location = new System.Drawing.Point(689, 155);
this.cmdScriptFile.Name = "cmdScriptFile";
this.cmdScriptFile.Size = new System.Drawing.Size(35, 22);
this.cmdScriptFile.TabIndex = 6;
this.cmdScriptFile.Text = "...";
this.cmdScriptFile.UseVisualStyleBackColor = true;
this.cmdScriptFile.Click += new System.EventHandler(this.cmdScriptFile_Click);
//
// txtScriptFile
//
this.txtScriptFile.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.txtScriptFile.Location = new System.Drawing.Point(18, 156);
this.txtScriptFile.Name = "txtScriptFile";
this.txtScriptFile.Size = new System.Drawing.Size(665, 20);
this.txtScriptFile.TabIndex = 5;
//
// label5
//
this.label5.AutoSize = true;
this.label5.Location = new System.Drawing.Point(15, 140);
this.label5.Name = "label5";
this.label5.Size = new System.Drawing.Size(50, 13);
this.label5.TabIndex = 28;
this.label5.Text = "Script-file";
//
// cmdBackupFolder
//
this.cmdBackupFolder.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
this.cmdBackupFolder.Font = new System.Drawing.Font("Arial", 9.75F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.cmdBackupFolder.Location = new System.Drawing.Point(689, 273);
this.cmdBackupFolder.Name = "cmdBackupFolder";
this.cmdBackupFolder.Size = new System.Drawing.Size(35, 22);
this.cmdBackupFolder.TabIndex = 10;
this.cmdBackupFolder.Text = "...";
this.cmdBackupFolder.UseVisualStyleBackColor = true;
this.cmdBackupFolder.Click += new System.EventHandler(this.cmdBackupFolder_Click);
//
// txtBackupFolder
//
this.txtBackupFolder.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.txtBackupFolder.Location = new System.Drawing.Point(18, 274);
this.txtBackupFolder.Name = "txtBackupFolder";
this.txtBackupFolder.Size = new System.Drawing.Size(665, 20);
this.txtBackupFolder.TabIndex = 9;
//
// label6
//
this.label6.AutoSize = true;
this.label6.Location = new System.Drawing.Point(15, 258);
this.label6.Name = "label6";
this.label6.Size = new System.Drawing.Size(130, 13);
this.label6.TabIndex = 31;
this.label6.Text = "Backup location (optional)";
//
// label7
//
this.label7.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
this.label7.AutoSize = true;
this.label7.Location = new System.Drawing.Point(20, 807);
this.label7.Name = "label7";
this.label7.Size = new System.Drawing.Size(66, 13);
this.label7.TabIndex = 32;
this.label7.Text = "Powered by ";
//
// CapstoneLink
//
this.CapstoneLink.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
this.CapstoneLink.AutoSize = true;
this.CapstoneLink.Location = new System.Drawing.Point(80, 807);
this.CapstoneLink.Name = "CapstoneLink";
this.CapstoneLink.Size = new System.Drawing.Size(52, 13);
this.CapstoneLink.TabIndex = 33;
this.CapstoneLink.TabStop = true;
this.CapstoneLink.Text = "Capstone";
this.CapstoneLink.LinkClicked += new System.Windows.Forms.LinkLabelLinkClickedEventHandler(this.CapstoneLink_LinkClicked);
//
// label8
//
this.label8.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
this.label8.AutoSize = true;
this.label8.Location = new System.Drawing.Point(129, 807);
this.label8.Name = "label8";
this.label8.Size = new System.Drawing.Size(28, 13);
this.label8.TabIndex = 34;
this.label8.Text = "and ";
//
// CapstoneNetLink
//
this.CapstoneNetLink.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
this.CapstoneNetLink.AutoSize = true;
this.CapstoneNetLink.Location = new System.Drawing.Point(151, 807);
this.CapstoneNetLink.Name = "CapstoneNetLink";
this.CapstoneNetLink.Size = new System.Drawing.Size(77, 13);
this.CapstoneNetLink.TabIndex = 35;
this.CapstoneNetLink.TabStop = true;
this.CapstoneNetLink.Text = "Capstone.NET";
this.CapstoneNetLink.LinkClicked += new System.Windows.Forms.LinkLabelLinkClickedEventHandler(this.CapstoneNetLink_LinkClicked);
//
// label10
//
this.label10.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
this.label10.AutoSize = true;
this.label10.Location = new System.Drawing.Point(225, 807);
this.label10.Name = "label10";
this.label10.Size = new System.Drawing.Size(42, 13);
this.label10.TabIndex = 36;
this.label10.Text = "libraries";
//
// MainForm
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(742, 840);
this.Controls.Add(this.label10);
this.Controls.Add(this.CapstoneNetLink);
this.Controls.Add(this.label8);
this.Controls.Add(this.CapstoneLink);
this.Controls.Add(this.label7);
this.Controls.Add(this.cmdBackupFolder);
this.Controls.Add(this.txtBackupFolder);
this.Controls.Add(this.label6);
this.Controls.Add(this.cmdScriptFile);
this.Controls.Add(this.txtScriptFile);
this.Controls.Add(this.label5);
this.Controls.Add(this.cmdPatch);
this.Controls.Add(this.cmdCompile);
this.Controls.Add(this.txtConsole);
this.Controls.Add(this.label9);
this.Controls.Add(this.cmdPatchDefinitionsFile);
this.Controls.Add(this.txtPatchDefinitionsFile);
this.Controls.Add(this.label4);
this.Controls.Add(this.cmdOutputFolder);
this.Controls.Add(this.txtOutputFolder);
this.Controls.Add(this.label3);
this.Controls.Add(this.cmdInputFolder);
this.Controls.Add(this.txtInputFolder);
this.Controls.Add(this.label2);
this.Controls.Add(this.cmdVisualStudioPath);
this.Controls.Add(this.txtVisualStudioPath);
this.Controls.Add(this.label1);
this.Name = "MainForm";
this.Text = "ARM Auto-patcher by Rene Lergner";
this.FormClosed += new System.Windows.Forms.FormClosedEventHandler(this.MainForm_FormClosed);
this.Load += new System.EventHandler(this.MainForm_Load);
this.ResumeLayout(false);
this.PerformLayout();
}
#endregion
private System.Windows.Forms.Label label1;
private System.Windows.Forms.TextBox txtVisualStudioPath;
private System.Windows.Forms.FolderBrowserDialog FolderBrowserDialog;
private System.Windows.Forms.OpenFileDialog OpenFileDialog;
private System.Windows.Forms.SaveFileDialog SaveFileDialog;
private System.Windows.Forms.Button cmdVisualStudioPath;
private System.Windows.Forms.Button cmdInputFolder;
private System.Windows.Forms.TextBox txtInputFolder;
private System.Windows.Forms.Label label2;
private System.Windows.Forms.Button cmdOutputFolder;
private System.Windows.Forms.TextBox txtOutputFolder;
private System.Windows.Forms.Label label3;
private System.Windows.Forms.Button cmdPatchDefinitionsFile;
private System.Windows.Forms.TextBox txtPatchDefinitionsFile;
private System.Windows.Forms.Label label4;
private System.Windows.Forms.TextBox txtConsole;
private System.Windows.Forms.Label label9;
private System.Windows.Forms.Button cmdCompile;
private System.Windows.Forms.Button cmdPatch;
private System.Windows.Forms.Button cmdScriptFile;
private System.Windows.Forms.TextBox txtScriptFile;
private System.Windows.Forms.Label label5;
private System.Windows.Forms.Button cmdBackupFolder;
private System.Windows.Forms.TextBox txtBackupFolder;
private System.Windows.Forms.Label label6;
private System.Windows.Forms.Label label7;
private System.Windows.Forms.LinkLabel CapstoneLink;
private System.Windows.Forms.Label label8;
private System.Windows.Forms.LinkLabel CapstoneNetLink;
private System.Windows.Forms.Label label10;
}
}
+371
View File
@@ -0,0 +1,371 @@
// Copyright (c) 2018, Rene Lergner - wpinternals.net - @Heathcliff74xda
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using Microsoft.Win32;
using System;
using System.Collections.Generic;
using System.Data;
using System.IO;
using System.Linq;
using System.Windows.Forms;
using WPinternals;
namespace Patcher
{
public partial class MainForm : Form
{
private PatchEngine PatchEngine = null;
public MainForm()
{
InitializeComponent();
}
private void MainForm_Load(object sender, EventArgs e)
{
LoadPaths();
CenterToScreen();
}
private void LoadPaths()
{
RegistryKey Key = Registry.CurrentUser.OpenSubKey(@"Software\Patcher", true) ?? Registry.CurrentUser.CreateSubKey(@"Software\Patcher");
txtVisualStudioPath.Text = (string)Key.GetValue("VisualStudioPath", "");
if (txtVisualStudioPath.Text.Length == 0)
txtVisualStudioPath.Text = FindVisualStudioPath();
txtPatchDefinitionsFile.Text = (string)Key.GetValue("PatchDefinitionsFilePath", "");
txtScriptFile.Text = (string)Key.GetValue("ScriptFilePath", "");
txtInputFolder.Text = (string)Key.GetValue("InputFolderPath", "");
txtOutputFolder.Text = (string)Key.GetValue("OutputFolderPath", "");
txtBackupFolder.Text = (string)Key.GetValue("BackupFolderPath", "");
LoadPatchDefinitions();
}
public static string[] FindMSVCBinaryPaths(string s)
{
string LegacyPath = Path.Combine(s, @"VC\bin");
if (Directory.Exists(LegacyPath))
{
return new string[] { LegacyPath };
}
if (Directory.Exists(Path.Combine(s, @"VC\Tools\MSVC")))
{
IEnumerable<string> MSVCs = Directory.EnumerateDirectories(Path.Combine(s, @"VC\Tools\MSVC"));
IEnumerable<string> Bins = MSVCs.Select(s => Path.Combine(s, "bin")).Where(s => Directory.Exists(s));
return Bins.ToArray();
}
return Array.Empty<string>();
}
public static string FindArmAsmPath(string s)
{
foreach (string MSVCBin in FindMSVCBinaryPaths(s))
{
string path1 = Path.Combine(MSVCBin, "x86_arm");
string path2 = Path.Combine(MSVCBin, @"Hostx86\arm");
if (File.Exists(Path.Combine(path1, "armasm.exe")))
{
return path1;
}
if (File.Exists(Path.Combine(path2, "armasm.exe")))
{
return path2;
}
}
return "";
}
private static string FindVisualStudioPath()
{
IEnumerable<string> MainX86VSDirectories = Directory.EnumerateDirectories(@"C:\Program Files (x86)\", "Microsoft Visual Studio*");
IEnumerable<string> MainX64VSDirectories = Directory.EnumerateDirectories(@"C:\Program Files\", "Microsoft Visual Studio*");
IEnumerable<string> MainVSDirectories = MainX86VSDirectories.Union(MainX64VSDirectories);
IEnumerable<string> SubMainVSDirectories = MainVSDirectories.SelectMany(s => Directory.EnumerateDirectories(s));
IEnumerable<string> SubSubMainVSDirectories = SubMainVSDirectories.SelectMany(s => Directory.EnumerateDirectories(s));
IEnumerable<string> Directories = MainVSDirectories.Union(SubMainVSDirectories).Union(SubSubMainVSDirectories);
string attempt1 = Directories.Where(s => FindArmAsmPath(s) != "").OrderByDescending(s => File.GetCreationTime(Path.Combine(s, @"VC\bin\x86_arm\armasm.exe"))).FirstOrDefault() ?? "";
if (attempt1 != "")
return attempt1;
return Directories.Where(s => Directory.Exists(Path.Combine(s, @"VC\Tools\MSVC"))).Select(s => Path.Combine(s, @"VC\Tools\MSVC")).SelectMany(s => Directory.EnumerateDirectories(s)).Where(s => File.Exists(Path.Combine(s, @"bin\Hostx86\arm\armasm.exe"))).OrderByDescending(s => File.GetCreationTime(Path.Combine(s, @"bin\Hostx86\arm\armasm.exe"))).FirstOrDefault() ?? "";
}
private void StorePaths()
{
RegistryKey Key = Registry.CurrentUser.OpenSubKey(@"Software\Patcher", true) ?? Registry.CurrentUser.CreateSubKey(@"Software\Patcher");
string VisualStudioPath = txtVisualStudioPath.Text.Trim();
if (VisualStudioPath.Length == 0)
{
if (Key.GetValue("VisualStudioPath") != null)
Key.DeleteValue("VisualStudioPath");
}
else
{
Key.SetValue("VisualStudioPath", VisualStudioPath);
}
string PatchDefinitionsFilePath = txtPatchDefinitionsFile.Text.Trim();
if (PatchDefinitionsFilePath.Length == 0)
{
if (Key.GetValue("PatchDefinitionsFilePath") != null)
Key.DeleteValue("PatchDefinitionsFilePath");
}
else
{
Key.SetValue("PatchDefinitionsFilePath", PatchDefinitionsFilePath);
}
string ScriptFilePath = txtScriptFile.Text.Trim();
if (ScriptFilePath.Length == 0)
{
if (Key.GetValue("ScriptFilePath") != null)
Key.DeleteValue("ScriptFilePath");
}
else
{
Key.SetValue("ScriptFilePath", ScriptFilePath);
}
string InputFolderPath = txtInputFolder.Text.Trim();
if (InputFolderPath.Length == 0)
{
if (Key.GetValue("InputFolderPath") != null)
Key.DeleteValue("InputFolderPath");
}
else
{
Key.SetValue("InputFolderPath", InputFolderPath);
}
string OutputFolderPath = txtOutputFolder.Text.Trim();
if (OutputFolderPath.Length == 0)
{
if (Key.GetValue("OutputFolderPath") != null)
Key.DeleteValue("OutputFolderPath");
}
else
{
Key.SetValue("OutputFolderPath", OutputFolderPath);
}
string BackupFolderPath = txtBackupFolder.Text.Trim();
if (BackupFolderPath.Length == 0)
{
if (Key.GetValue("BackupFolderPath") != null)
Key.DeleteValue("BackupFolderPath");
}
else
{
Key.SetValue("BackupFolderPath", BackupFolderPath);
}
}
private bool LoadingPatchDefinitions = false;
private void LoadPatchDefinitions()
{
if (LoadingPatchDefinitions)
return;
LoadingPatchDefinitions = true;
try
{
string Definitions = File.ReadAllText(txtPatchDefinitionsFile.Text);
PatchEngine = new PatchEngine(Definitions);
}
catch
{
PatchEngine = new PatchEngine();
}
LoadingPatchDefinitions = false;
}
private void cmdVisualStudioPath_Click(object sender, EventArgs e)
{
FolderBrowserDialog.SelectedPath = txtVisualStudioPath.Text;
FolderBrowserDialog.Description = "Select path to Visual Studio with ARM32 SDK";
System.Windows.Forms.DialogResult Result = FolderBrowserDialog.ShowDialog();
if (Result == System.Windows.Forms.DialogResult.OK)
txtVisualStudioPath.Text = FolderBrowserDialog.SelectedPath;
}
private void cmdPatchDefinitionsFile_Click(object sender, EventArgs e)
{
OpenFileDialog.CheckFileExists = false;
OpenFileDialog.DefaultExt = "xml";
try
{
OpenFileDialog.FileName = Path.GetFileName(txtPatchDefinitionsFile.Text);
OpenFileDialog.InitialDirectory = Path.GetDirectoryName(txtPatchDefinitionsFile.Text);
}
catch { }
OpenFileDialog.Multiselect = false;
OpenFileDialog.Title = "Open patch-definitions file";
System.Windows.Forms.DialogResult Result = OpenFileDialog.ShowDialog();
if (Result == System.Windows.Forms.DialogResult.OK)
{
txtPatchDefinitionsFile.Text = OpenFileDialog.FileName;
WindowsFormsSynchronizationContext.Current.Post(s => LoadPatchDefinitions(), null);
}
}
private void txtPatchDefinitionsFile_Leave(object sender, EventArgs e)
{
WindowsFormsSynchronizationContext.Current.Post(s => LoadPatchDefinitions(), null);
}
private void MainForm_FormClosed(object sender, FormClosedEventArgs e)
{
StorePaths();
}
private void cmdInputFolder_Click(object sender, EventArgs e)
{
FolderSelectDialog Dialog = new();
Dialog.Title = "Select input location";
Dialog.InitialDirectory = txtInputFolder.Text;
try
{
Dialog.InitialDirectory = txtInputFolder.Text;
}
catch { }
bool Result = Dialog.ShowDialog();
if (Result)
{
txtInputFolder.Text = Dialog.FileName;
txtOutputFolder.Text = "";
}
}
private void cmdOutputFolder_Click(object sender, EventArgs e)
{
FolderSelectDialog Dialog = new();
Dialog.Title = "Select output location";
Dialog.InitialDirectory = txtOutputFolder.Text;
try
{
Dialog.InitialDirectory = txtOutputFolder.Text;
}
catch { }
bool Result = Dialog.ShowDialog();
if (Result)
{
txtOutputFolder.Text = Dialog.FileName;
}
}
private void cmdScriptFile_Click(object sender, EventArgs e)
{
OpenFileDialog.CheckFileExists = true;
OpenFileDialog.DefaultExt = "pds";
try
{
OpenFileDialog.FileName = Path.GetFileName(txtScriptFile.Text);
OpenFileDialog.InitialDirectory = Path.GetDirectoryName(txtScriptFile.Text);
}
catch { }
OpenFileDialog.Multiselect = false;
OpenFileDialog.Title = "Open patch-definition-script-file";
System.Windows.Forms.DialogResult Result = OpenFileDialog.ShowDialog();
if (Result == System.Windows.Forms.DialogResult.OK)
{
txtScriptFile.Text = OpenFileDialog.FileName;
}
}
private void cmdCompile_Click(object sender, EventArgs e)
{
ClearLog();
StorePaths();
ScriptEngine.ExecuteScript(txtVisualStudioPath.Text.Trim(), txtScriptFile.Text.Trim(), txtInputFolder.Text.Trim(), PatchEngine: PatchEngine, WriteLog: WriteLog);
}
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);
}
private void ClearLog()
{
txtConsole.Clear();
}
private void WriteLog(string Line)
{
if (txtConsole.InvokeRequired)
{
txtConsole.Invoke((MethodInvoker)delegate { WriteLog(Line); });
}
else
{
txtConsole.AppendText(Line + Environment.NewLine);
txtConsole.Select(txtConsole.Text.Length, 0);
txtConsole.ScrollToCaret();
System.Diagnostics.Debug.WriteLine(Line);
}
}
private void cmdBackupFolder_Click(object sender, EventArgs e)
{
FolderSelectDialog Dialog = new();
Dialog.Title = "Select backup location";
Dialog.InitialDirectory = txtBackupFolder.Text;
try
{
Dialog.InitialDirectory = txtBackupFolder.Text;
}
catch { }
bool Result = Dialog.ShowDialog();
if (Result)
{
txtBackupFolder.Text = Dialog.FileName;
}
}
private void CapstoneLink_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
{
System.Diagnostics.Process.Start("https://github.com/aquynh/capstone/blob/master/LICENSE.TXT");
}
private void CapstoneNetLink_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
{
System.Diagnostics.Process.Start("https://github.com/9ee1/Capstone.NET/blob/master/LICENSE");
}
}
}
+129
View File
@@ -0,0 +1,129 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<metadata name="FolderBrowserDialog.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>17, 17</value>
</metadata>
<metadata name="OpenFileDialog.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>182, 17</value>
</metadata>
<metadata name="SaveFileDialog.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>317, 17</value>
</metadata>
</root>
+39
View File
@@ -0,0 +1,39 @@
// Copyright (c) 2018, Rene Lergner - wpinternals.net - @Heathcliff74xda
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
using System.Windows.Forms;
namespace Patcher
{
internal static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
private static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new MainForm());
}
}
}
@@ -0,0 +1,36 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("AutoPatcher")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("AutoPatcher")]
[assembly: AssemblyCopyright("Copyright © 2018")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("95cf9509-c1c4-40f5-a60e-9d93ea6f438c")]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]
+63
View File
@@ -0,0 +1,63 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:4.0.30319.42000
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace Patcher.Properties {
using System;
/// <summary>
/// A strongly-typed resource class, for looking up localized strings, etc.
/// </summary>
// This class was auto-generated by the StronglyTypedResourceBuilder
// class via a tool like ResGen or Visual Studio.
// To add or remove a member, edit your .ResX file then rerun ResGen
// with the /str option, or rebuild your VS project.
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "15.0.0.0")]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
internal class Resources {
private static global::System.Resources.ResourceManager resourceMan;
private static global::System.Globalization.CultureInfo resourceCulture;
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
internal Resources() {
}
/// <summary>
/// Returns the cached ResourceManager instance used by this class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Resources.ResourceManager ResourceManager {
get {
if (object.ReferenceEquals(resourceMan, null)) {
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Patcher.Properties.Resources", typeof(Resources).Assembly);
resourceMan = temp;
}
return resourceMan;
}
}
/// <summary>
/// Overrides the current thread's CurrentUICulture property for all
/// resource lookups using this strongly typed resource class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Globalization.CultureInfo Culture {
get {
return resourceCulture;
}
set {
resourceCulture = value;
}
}
}
}
@@ -0,0 +1,117 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>
+26
View File
@@ -0,0 +1,26 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:4.0.30319.42000
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace Patcher.Properties {
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "15.8.0.0")]
internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
public static Settings Default {
get {
return defaultInstance;
}
}
}
}
@@ -0,0 +1,7 @@
<?xml version='1.0' encoding='utf-8'?>
<SettingsFile xmlns="http://schemas.microsoft.com/VisualStudio/2004/01/settings" CurrentProfile="(Default)">
<Profiles>
<Profile Name="(Default)" />
</Profiles>
<Settings />
</SettingsFile>
File diff suppressed because it is too large Load Diff
+81
View File
@@ -0,0 +1,81 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
VisualStudioVersion = 15.0.28010.2041
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Patcher", "Patcher\Patcher.csproj", "{B67C62AE-86C4-4C18-99AB-4E94A3E09D36}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AutoPatcher", "AutoPatcher\AutoPatcher.csproj", "{95CF9509-C1C4-40F5-A60E-9D93EA6F438C}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
.NET45Debug|Any CPU = .NET45Debug|Any CPU
.NET45Debug|x64 = .NET45Debug|x64
.NET45Debug|x86 = .NET45Debug|x86
.NET45Release|Any CPU = .NET45Release|Any CPU
.NET45Release|x64 = .NET45Release|x64
.NET45Release|x86 = .NET45Release|x86
Debug|Any CPU = Debug|Any CPU
Debug|x64 = Debug|x64
Debug|x86 = Debug|x86
Release|Any CPU = Release|Any CPU
Release|x64 = Release|x64
Release|x86 = Release|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{B67C62AE-86C4-4C18-99AB-4E94A3E09D36}..NET45Debug|Any CPU.ActiveCfg = Debug|Any CPU
{B67C62AE-86C4-4C18-99AB-4E94A3E09D36}..NET45Debug|Any CPU.Build.0 = Debug|Any CPU
{B67C62AE-86C4-4C18-99AB-4E94A3E09D36}..NET45Debug|x64.ActiveCfg = Debug|x64
{B67C62AE-86C4-4C18-99AB-4E94A3E09D36}..NET45Debug|x64.Build.0 = Debug|x64
{B67C62AE-86C4-4C18-99AB-4E94A3E09D36}..NET45Debug|x86.ActiveCfg = Debug|x86
{B67C62AE-86C4-4C18-99AB-4E94A3E09D36}..NET45Debug|x86.Build.0 = Debug|x86
{B67C62AE-86C4-4C18-99AB-4E94A3E09D36}..NET45Release|Any CPU.ActiveCfg = Release|Any CPU
{B67C62AE-86C4-4C18-99AB-4E94A3E09D36}..NET45Release|Any CPU.Build.0 = Release|Any CPU
{B67C62AE-86C4-4C18-99AB-4E94A3E09D36}..NET45Release|x64.ActiveCfg = Release|x64
{B67C62AE-86C4-4C18-99AB-4E94A3E09D36}..NET45Release|x64.Build.0 = Release|x64
{B67C62AE-86C4-4C18-99AB-4E94A3E09D36}..NET45Release|x86.ActiveCfg = Release|x86
{B67C62AE-86C4-4C18-99AB-4E94A3E09D36}..NET45Release|x86.Build.0 = Release|x86
{B67C62AE-86C4-4C18-99AB-4E94A3E09D36}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{B67C62AE-86C4-4C18-99AB-4E94A3E09D36}.Debug|Any CPU.Build.0 = Debug|Any CPU
{B67C62AE-86C4-4C18-99AB-4E94A3E09D36}.Debug|x64.ActiveCfg = Debug|x64
{B67C62AE-86C4-4C18-99AB-4E94A3E09D36}.Debug|x64.Build.0 = Debug|x64
{B67C62AE-86C4-4C18-99AB-4E94A3E09D36}.Debug|x86.ActiveCfg = Debug|Any CPU
{B67C62AE-86C4-4C18-99AB-4E94A3E09D36}.Debug|x86.Build.0 = Debug|Any CPU
{B67C62AE-86C4-4C18-99AB-4E94A3E09D36}.Release|Any CPU.ActiveCfg = Release|Any CPU
{B67C62AE-86C4-4C18-99AB-4E94A3E09D36}.Release|Any CPU.Build.0 = Release|Any CPU
{B67C62AE-86C4-4C18-99AB-4E94A3E09D36}.Release|x64.ActiveCfg = Release|x64
{B67C62AE-86C4-4C18-99AB-4E94A3E09D36}.Release|x64.Build.0 = Release|x64
{B67C62AE-86C4-4C18-99AB-4E94A3E09D36}.Release|x86.ActiveCfg = Release|Any CPU
{B67C62AE-86C4-4C18-99AB-4E94A3E09D36}.Release|x86.Build.0 = Release|Any CPU
{95CF9509-C1C4-40F5-A60E-9D93EA6F438C}..NET45Debug|Any CPU.ActiveCfg = Debug|Any CPU
{95CF9509-C1C4-40F5-A60E-9D93EA6F438C}..NET45Debug|Any CPU.Build.0 = Debug|Any CPU
{95CF9509-C1C4-40F5-A60E-9D93EA6F438C}..NET45Debug|x64.ActiveCfg = Debug|x64
{95CF9509-C1C4-40F5-A60E-9D93EA6F438C}..NET45Debug|x64.Build.0 = Debug|x64
{95CF9509-C1C4-40F5-A60E-9D93EA6F438C}..NET45Debug|x86.ActiveCfg = Debug|x86
{95CF9509-C1C4-40F5-A60E-9D93EA6F438C}..NET45Debug|x86.Build.0 = Debug|x86
{95CF9509-C1C4-40F5-A60E-9D93EA6F438C}..NET45Release|Any CPU.ActiveCfg = Release|Any CPU
{95CF9509-C1C4-40F5-A60E-9D93EA6F438C}..NET45Release|Any CPU.Build.0 = Release|Any CPU
{95CF9509-C1C4-40F5-A60E-9D93EA6F438C}..NET45Release|x64.ActiveCfg = Release|x64
{95CF9509-C1C4-40F5-A60E-9D93EA6F438C}..NET45Release|x64.Build.0 = Release|x64
{95CF9509-C1C4-40F5-A60E-9D93EA6F438C}..NET45Release|x86.ActiveCfg = Release|x86
{95CF9509-C1C4-40F5-A60E-9D93EA6F438C}..NET45Release|x86.Build.0 = Release|x86
{95CF9509-C1C4-40F5-A60E-9D93EA6F438C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{95CF9509-C1C4-40F5-A60E-9D93EA6F438C}.Debug|Any CPU.Build.0 = Debug|Any CPU
{95CF9509-C1C4-40F5-A60E-9D93EA6F438C}.Debug|x64.ActiveCfg = Debug|x64
{95CF9509-C1C4-40F5-A60E-9D93EA6F438C}.Debug|x64.Build.0 = Debug|x64
{95CF9509-C1C4-40F5-A60E-9D93EA6F438C}.Debug|x86.ActiveCfg = Debug|x86
{95CF9509-C1C4-40F5-A60E-9D93EA6F438C}.Debug|x86.Build.0 = Debug|x86
{95CF9509-C1C4-40F5-A60E-9D93EA6F438C}.Release|Any CPU.ActiveCfg = Release|Any CPU
{95CF9509-C1C4-40F5-A60E-9D93EA6F438C}.Release|Any CPU.Build.0 = Release|Any CPU
{95CF9509-C1C4-40F5-A60E-9D93EA6F438C}.Release|x64.ActiveCfg = Release|x64
{95CF9509-C1C4-40F5-A60E-9D93EA6F438C}.Release|x64.Build.0 = Release|x64
{95CF9509-C1C4-40F5-A60E-9D93EA6F438C}.Release|x86.ActiveCfg = Release|x86
{95CF9509-C1C4-40F5-A60E-9D93EA6F438C}.Release|x86.Build.0 = Release|x86
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {6763D5C5-7BCE-437C-9FD0-67BDD8D79FD2}
EndGlobalSection
EndGlobal
+6
View File
@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
</startup>
</configuration>
+229
View File
@@ -0,0 +1,229 @@
// Copyright (c) 2018, Rene Lergner - wpinternals.net - @Heathcliff74xda
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Text;
namespace Patcher
{
public enum CodeType
{
ARM,
Thumb,
Thumb2
}
public static class ArmCompiler
{
public static Int32 LastErrorCode;
public static string Output;
public static byte[] Compile(string PathToVisualStudio, UInt32 Origin, CodeType CodeType, string ArmCodeFragment)
{
if (PathToVisualStudio.Length == 0)
{
Output = "ARM SDK is missing.";
return null;
}
string AssemblyFilePath = Path.GetTempFileName();
string ObjectFilePathTmp = Path.GetTempFileName();
string ObjectFilePath = ObjectFilePathTmp.Replace(".tmp", ".obj");
File.Move(ObjectFilePathTmp, ObjectFilePath);
string CodeTypeDirective = null;
switch (CodeType)
{
case Patcher.CodeType.ARM:
CodeTypeDirective = "CODE32";
break;
case Patcher.CodeType.Thumb:
CodeTypeDirective = "CODE16";
break;
case Patcher.CodeType.Thumb2:
CodeTypeDirective = "THUMB";
break;
}
string FullAssemblyCode =
" AREA ARM_AREA, CODE, READONLY" + Environment.NewLine +
" " + CodeTypeDirective + Environment.NewLine;
string ProcessedAssembly = ProcessArmCodeFragment(ArmCodeFragment, Origin, out uint Padding);
if (Padding > 0)
FullAssemblyCode += " SPACE " + Padding.ToString() + Environment.NewLine;
FullAssemblyCode +=
"start" + Environment.NewLine +
ProcessedAssembly;
FullAssemblyCode += " end" + Environment.NewLine;
File.WriteAllText(AssemblyFilePath, FullAssemblyCode);
string ArmAsmPath = MainForm.FindArmAsmPath(PathToVisualStudio);
string BinPath = MainForm.FindMSVCBinaryPaths(PathToVisualStudio).FirstOrDefault() ?? "";
ProcessStartInfo psi = new(Path.Combine(ArmAsmPath, "armasm.exe"));
psi.EnvironmentVariables["PATH"] += ";" + Path.Combine(PathToVisualStudio, @"Common7\IDE\");
psi.EnvironmentVariables["PATH"] += ";" + Path.Combine(PathToVisualStudio, @"Common7\Tools\");
psi.EnvironmentVariables["PATH"] += ";" + BinPath;
psi.EnvironmentVariables["PATH"] += ";" + ArmAsmPath;
psi.UseShellExecute = false;
psi.RedirectStandardOutput = true;
psi.CreateNoWindow = true;
psi.Arguments = "-g \"" + AssemblyFilePath + "\" \"" + ObjectFilePath + "\"";
Process ArmAsmProcess = Process.Start(psi);
ArmAsmProcess.WaitForExit();
LastErrorCode = ArmAsmProcess.ExitCode;
if (ArmAsmProcess.ExitCode != 0)
{
using StreamReader reader = ArmAsmProcess.StandardOutput;
Output = reader.ReadToEnd();
string[] Lines = Output.Split(new[] { "\r\n", "\r", "\n" }, StringSplitOptions.None);
Output = "";
foreach (string Line in Lines)
{
string Out = Line.Trim();
if (Out.Length == 0) continue;
if (Out.StartsWith("Microsoft (R) ARM Macro Assembler")) continue;
if (Out.StartsWith("Copyright (C) Microsoft Corporation")) continue;
if (Out.StartsWith(AssemblyFilePath))
{
Out = Out[AssemblyFilePath.Length..];
int P = Out.IndexOf(':');
Out = Out[(P + 1)..].Trim();
}
Output += Out + Environment.NewLine;
}
}
byte[] Result = null;
if (LastErrorCode == 0)
Result = COFF.ObjectFileParser.ParseObjectFile(ObjectFilePath).SectionHeaders.First(h => h.Name == "ARM_AREA").RawData;
File.Delete(AssemblyFilePath);
File.Delete(ObjectFilePath);
if ((Result != null) && (Padding > 0))
{
byte[] RemovedPadding = new byte[Result.Length - Padding];
Buffer.BlockCopy(Result, (int)Padding, RemovedPadding, 0, RemovedPadding.Length);
Result = RemovedPadding;
}
return Result;
}
private static string ProcessArmCodeFragment(string ArmCodeFragment, UInt32 Origin, out UInt32 Padding)
{
string[] BranchOpcodes = new string[] { "B", "BEQ", "BNE", "BCS", "BHS", "BCC", "BLO", "BMI", "BPL", "BVS", "BVC", "BHI", "BLS", "BGE", "BLT", "BGT", "BLE", "BAL"};
StringBuilder Result = new(1000);
Padding = 0;
string[] Lines = ArmCodeFragment.Split(new[] { "\r\n", "\r", "\n" }, StringSplitOptions.None);
List<Tuple<string, string>> Labels = new();
foreach (string Line in Lines)
{
string Code = Line;
if (Line.Contains(':'))
{
string Label = Line.Substring(0, Line.IndexOf(':'));
Label = Label.Trim();
if (Label.Length > 0)
Result.AppendLine(Label);
Code = Line[(Line.IndexOf(':') + 1)..];
}
int EquPos = Code.IndexOf("EQU", StringComparison.OrdinalIgnoreCase);
if ((EquPos > 0) && (EquPos > 0) && (EquPos < (Code.Length - 3)))
{
if (new char[] { '\t', ' ' }.Contains(Line[EquPos - 1]) &&
new char[] { '\t', ' ' }.Contains(Line[EquPos + 3]))
{
Result.AppendLine(Line.Trim());
Labels.Add(new Tuple<string, string>(Line.Substring(0, EquPos).Trim(), Line[(EquPos + 3)..].Trim()));
continue;
}
}
Code = Code.Trim();
bool IsAbsoluteAddress = false;
int OpcodeLength = Code.IndexOfAny(new char [] { '\t', ' ', '.' });
if (OpcodeLength > 0)
{
string Opcode = Code.Substring(0, OpcodeLength).ToUpper();
string PossibleAddress = null;
if (Opcode == "LDR")
{
PossibleAddress = Code[(Code.IndexOf(',') + 1)..].Trim();
}
else if (BranchOpcodes.Contains(Opcode))
{
PossibleAddress = Code[(Code.IndexOfAny(new char[] { '\t', ' ' }) + 1)..].Trim();
}
if (PossibleAddress != null)
{
foreach (Tuple<string, string> Label in Labels)
{
if (string.Equals(Label.Item1, PossibleAddress, StringComparison.CurrentCultureIgnoreCase))
{
PossibleAddress = Label.Item2;
break;
}
}
if (PossibleAddress.StartsWith("0x"))
PossibleAddress = PossibleAddress[2..];
IsAbsoluteAddress = UInt32.TryParse(PossibleAddress, NumberStyles.HexNumber, CultureInfo.CurrentCulture, out uint ParsedValue);
if (IsAbsoluteAddress && (ParsedValue < Origin))
Padding = Math.Max(Padding, Origin - ParsedValue);
}
}
Result.Append(' ');
Result.Append(Code);
if (IsAbsoluteAddress)
{
Result.Append(" + start - 0x");
Result.Append(Origin.ToString("X8"));
}
Result.Append(Environment.NewLine);
}
return Result.ToString();
}
}
}
+382
View File
@@ -0,0 +1,382 @@
// Copyright (c) 2018, Rene Lergner - wpinternals.net - @Heathcliff74xda
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
using System.IO;
namespace WPinternals
{
internal static class ByteOperations
{
internal static string ReadAsciiString(byte[] ByteArray, UInt32 Offset)
{
UInt32 Length = 0;
while (((Offset + Length) < ByteArray.Length) && (ByteArray[Offset + Length] != 0))
Length++;
byte[] Bytes = new byte[Length];
Buffer.BlockCopy(ByteArray, (int)Offset, Bytes, 0, (int)Length);
return System.Text.Encoding.ASCII.GetString(Bytes);
}
internal static string ReadAsciiString(byte[] ByteArray, UInt32 Offset, UInt32 Length)
{
byte[] Bytes = new byte[Length];
Buffer.BlockCopy(ByteArray, (int)Offset, Bytes, 0, (int)Length);
return System.Text.Encoding.ASCII.GetString(Bytes);
}
internal static string ReadUnicodeString(byte[] ByteArray, UInt32 Offset, UInt32 Length)
{
byte[] Bytes = new byte[Length];
Buffer.BlockCopy(ByteArray, (int)Offset, Bytes, 0, (int)Length);
return System.Text.Encoding.Unicode.GetString(Bytes);
}
internal static void WriteUnicodeString(byte[] ByteArray, UInt32 Offset, string Text, UInt32? MaxBufferLength = null)
{
if (MaxBufferLength != null)
Array.Clear(ByteArray, (int)Offset, (int)MaxBufferLength);
byte[] TextBytes = System.Text.UnicodeEncoding.Unicode.GetBytes(Text);
int WriteLength = TextBytes.Length;
if (WriteLength > MaxBufferLength)
WriteLength = (int)MaxBufferLength;
Buffer.BlockCopy(TextBytes, 0, ByteArray, (int)Offset, WriteLength);
}
internal static UInt32 ReadUInt32(byte[] ByteArray, UInt32 Offset)
{
// Assume CPU and FFU are both Little Endian
return BitConverter.ToUInt32(ByteArray, (int)Offset);
}
internal static void WriteUInt32(byte[] ByteArray, UInt32 Offset, UInt32 Value)
{
System.Buffer.BlockCopy(BitConverter.GetBytes(Value), 0, ByteArray, (int)Offset, 4);
}
internal static Int32 ReadInt32(byte[] ByteArray, UInt32 Offset)
{
// Assume CPU and FFU are both Little Endian
return BitConverter.ToInt32(ByteArray, (int)Offset);
}
internal static void WriteInt32(byte[] ByteArray, UInt32 Offset, Int32 Value)
{
System.Buffer.BlockCopy(BitConverter.GetBytes(Value), 0, ByteArray, (int)Offset, 4);
}
internal static UInt16 ReadUInt16(byte[] ByteArray, UInt32 Offset)
{
// Assume CPU and FFU are both Little Endian
return BitConverter.ToUInt16(ByteArray, (int)Offset);
}
internal static void WriteUInt16(byte[] ByteArray, UInt32 Offset, UInt16 Value)
{
System.Buffer.BlockCopy(BitConverter.GetBytes(Value), 0, ByteArray, (int)Offset, 2);
}
internal static Int16 ReadInt16(byte[] ByteArray, UInt32 Offset)
{
// Assume CPU and FFU are both Little Endian
return BitConverter.ToInt16(ByteArray, (int)Offset);
}
internal static void WriteInt16(byte[] ByteArray, UInt32 Offset, Int16 Value)
{
System.Buffer.BlockCopy(BitConverter.GetBytes(Value), 0, ByteArray, (int)Offset, 2);
}
internal static byte ReadUInt8(byte[] ByteArray, UInt32 Offset)
{
return ByteArray[Offset];
}
internal static void WriteUInt8(byte[] ByteArray, UInt32 Offset, byte Value)
{
ByteArray[Offset] = Value;
}
internal static UInt32 ReadUInt24(byte[] ByteArray, UInt32 Offset)
{
return (UInt32)(ByteArray[Offset] + (ByteArray[Offset + 1] << 8) + (ByteArray[Offset + 2] << 16));
}
internal static void WriteUInt24(byte[] ByteArray, UInt32 Offset, UInt32 Value)
{
System.Buffer.BlockCopy(BitConverter.GetBytes(Value), 0, ByteArray, (int)Offset, 3);
}
internal static UInt64 ReadUInt64(byte[] ByteArray, UInt32 Offset)
{
// Assume CPU and FFU are both Little Endian
return BitConverter.ToUInt64(ByteArray, (int)Offset);
}
internal static void WriteUInt64(byte[] ByteArray, UInt32 Offset, UInt64 Value)
{
System.Buffer.BlockCopy(BitConverter.GetBytes(Value), 0, ByteArray, (int)Offset, 8);
}
internal static Guid ReadGuid(byte[] ByteArray, UInt32 Offset)
{
byte[] GuidBuffer = new byte[0x10];
Buffer.BlockCopy(ByteArray, (int)Offset, GuidBuffer, 0, 0x10);
return new Guid(GuidBuffer);
}
internal static void WriteGuid(byte[] ByteArray, UInt32 Offset, Guid Value)
{
Buffer.BlockCopy(Value.ToByteArray(), 0, ByteArray, (int)Offset, 0x10);
}
internal static UInt32 Align(UInt32 Base, UInt32 Offset, UInt32 Alignment)
{
if (((Offset - Base) % Alignment) == 0)
return Offset;
else
return ((((Offset - Base) / Alignment) + 1) * Alignment) + Base;
}
internal static UInt32? FindPatternInFile(string FileName, byte[] Pattern, byte[] Mask, out byte[] OutPattern)
{
// The mask is optional.
// In the mask 0x00 means the value must match, and 0xFF means that this position is a wildcard.
UInt32? Result = null;
FileStream Stream = new(FileName, FileMode.Open, FileAccess.Read);
byte[] Buffer = new byte[0x10000 + Pattern.Length - 1];
UInt32 BytesInBuffer = 0;
UInt32 BytesRead;
UInt32 SearchPositionFile = 0;
UInt32 SearchPositionBuffer = 0;
UInt32 BufferFileOffset = 0; // Offset in file where data from buffer is located.
int i;
OutPattern = null;
while (SearchPositionFile <= (Stream.Length - Pattern.Length))
{
if ((SearchPositionBuffer + Pattern.Length) > BytesInBuffer)
{
// Need to read next chunk
if ((BytesInBuffer - SearchPositionBuffer) > 0)
{
System.Buffer.BlockCopy(Buffer, (int)SearchPositionBuffer, Buffer, 0, (int)(BytesInBuffer - SearchPositionBuffer));
}
uint BufferReadPosition = BytesInBuffer - SearchPositionBuffer;
BytesInBuffer -= SearchPositionBuffer;
BufferFileOffset += SearchPositionBuffer;
SearchPositionBuffer = 0;
BytesRead = (UInt32)Stream.Read(Buffer, (int)BufferReadPosition, Buffer.Length - (int)BufferReadPosition);
BytesInBuffer += BytesRead;
}
bool Match = true;
for (i = 0; i < Pattern.Length; i++)
{
if (Buffer[SearchPositionBuffer + i] != Pattern[i])
{
if ((Mask == null) || (Mask[i] == 0))
{
Match = false;
break;
}
}
}
if (Match)
{
Result = SearchPositionFile;
OutPattern = new byte[Pattern.Length];
System.Buffer.BlockCopy(Buffer, (int)SearchPositionBuffer, OutPattern, 0, Pattern.Length);
break;
}
SearchPositionBuffer++;
SearchPositionFile++;
}
Stream.Close();
return Result;
}
internal static UInt32? FindAscii(byte[] SourceBuffer, string Pattern)
{
return FindPattern(SourceBuffer, System.Text.ASCIIEncoding.ASCII.GetBytes((string)Pattern), null, null);
}
internal static UInt32? FindAscii(byte[] SourceBuffer, uint SourceOffset, string Pattern)
{
return FindPattern(SourceBuffer, SourceOffset, null, System.Text.ASCIIEncoding.ASCII.GetBytes((string)Pattern), null, null);
}
internal static UInt32? FindUnicode(byte[] SourceBuffer, string Pattern)
{
return FindPattern(SourceBuffer, System.Text.UnicodeEncoding.Unicode.GetBytes((string)Pattern), null, null);
}
internal static UInt32? FindUnicode(byte[] SourceBuffer, uint SourceOffset, string Pattern)
{
return FindPattern(SourceBuffer, SourceOffset, null, System.Text.UnicodeEncoding.Unicode.GetBytes((string)Pattern), null, null);
}
internal static UInt32? FindUint(byte[] SourceBuffer, UInt32 Pattern)
{
return FindPattern(SourceBuffer, BitConverter.GetBytes((UInt32)Pattern), null, null);
}
internal static UInt32? FindPattern(byte[] SourceBuffer, byte[] Pattern, byte[] Mask, byte[] OutPattern)
{
return FindPattern(SourceBuffer, 0, null, Pattern, Mask, OutPattern);
}
internal static UInt32? FindPattern(byte[] SourceBuffer, uint SourceOffset, uint? SourceSize, byte[] Pattern, byte[] Mask, byte[] OutPattern)
{
// The mask is optional.
// In the mask 0x00 means the value must match, and 0xFF means that this position is a wildcard.
UInt32? Result = null;
UInt32 SearchPosition = SourceOffset;
int i;
while ((SearchPosition <= (SourceBuffer.Length - Pattern.Length)) && ((SourceSize == null) || (SearchPosition <= (SourceOffset + SourceSize - Pattern.Length))))
{
bool Match = true;
for (i = 0; i < Pattern.Length; i++)
{
if (SourceBuffer[SearchPosition + i] != Pattern[i])
{
if ((Mask == null) || (Mask[i] == 0))
{
Match = false;
break;
}
}
}
if (Match)
{
Result = SearchPosition;
if (OutPattern != null)
System.Buffer.BlockCopy(SourceBuffer, (int)SearchPosition, OutPattern, 0, Pattern.Length);
break;
}
SearchPosition++;
}
return Result;
}
internal static byte CalculateChecksum8(byte[] Buffer, UInt32 Offset, UInt32 Size)
{
byte Checksum = 0;
for (UInt32 i = Offset; i < (Offset + Size); i++)
Checksum += Buffer[i];
return (byte)(0x100 - Checksum);
}
internal static UInt16 CalculateChecksum16(byte[] Buffer, UInt32 Offset, UInt32 Size)
{
UInt16 Checksum = 0;
for (UInt32 i = Offset; i < (Offset + Size - 1); i += 2)
Checksum += BitConverter.ToUInt16(Buffer, (int)i);
return (UInt16)(0x10000 - Checksum);
}
private static readonly UInt32[] CRC32Table = new UInt32[] {
0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F,
0xE963A535, 0x9E6495A3, 0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988,
0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91, 0x1DB71064, 0x6AB020F2,
0xF3B97148, 0x84BE41DE, 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7,
0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, 0x14015C4F, 0x63066CD9,
0xFA0F3D63, 0x8D080DF5, 0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172,
0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B, 0x35B5A8FA, 0x42B2986C,
0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59,
0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423,
0xCFBA9599, 0xB8BDA50F, 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924,
0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D, 0x76DC4190, 0x01DB7106,
0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433,
0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB, 0x086D3D2D,
0x91646C97, 0xE6635C01, 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E,
0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457, 0x65B0D9C6, 0x12B7E950,
0x8BBEB8EA, 0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65,
0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, 0x4ADFA541, 0x3DD895D7,
0xA4D1C46D, 0xD3D6F4FB, 0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0,
0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9, 0x5005713C, 0x270241AA,
0xBE0B1010, 0xC90C2086, 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F,
0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81,
0xB7BD5C3B, 0xC0BA6CAD, 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A,
0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683, 0xE3630B12, 0x94643B84,
0x0D6D6A3E, 0x7A6A5AA8, 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1,
0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D, 0x806567CB,
0x196C3671, 0x6E6B06E7, 0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC,
0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5, 0xD6D6A3E8, 0xA1D1937E,
0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B,
0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, 0xDF60EFC3, 0xA867DF55,
0x316E8EEF, 0x4669BE79, 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236,
0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F, 0xC5BA3BBE, 0xB2BD0B28,
0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D,
0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, 0x9C0906A9, 0xEB0E363F,
0x72076785, 0x05005713, 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38,
0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21, 0x86D3D2D4, 0xF1D4E242,
0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777,
0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, 0x8F659EFF, 0xF862AE69,
0x616BFFD3, 0x166CCF45, 0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2,
0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB, 0xAED16A4A, 0xD9D65ADC,
0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9,
0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605, 0xCDD70693,
0x54DE5729, 0x23D967BF, 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94,
0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D
};
internal static UInt32 CRC32(byte[] Input, UInt32 Offset, UInt32 Length)
{
if ((Input == null) || ((Offset + Length) > Input.Length))
throw new ArgumentException();
unchecked
{
uint crc = (uint)(((uint)0) ^ (-1));
for (var i = Offset; i < (Offset + Length); i++)
{
crc = (crc >> 8) ^ CRC32Table[ (crc ^ Input[i]) & 0xFF ];
}
crc = (uint)(crc ^ (-1));
return crc;
}
}
}
}
+66
View File
@@ -0,0 +1,66 @@
// Copyright (c) 2018, Rene Lergner - wpinternals.net - @Heathcliff74xda
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
using System.Text;
namespace WPinternals
{
public static class Converter
{
public static string ConvertHexToString(byte[] Bytes, string Separator)
{
StringBuilder s = new(1000);
for (int i = Bytes.GetLowerBound(0); i <= Bytes.GetUpperBound(0); i++)
{
if (i != Bytes.GetLowerBound(0))
s.Append(Separator);
s.Append(Bytes[i].ToString("X2"));
}
return s.ToString();
}
public static byte[] ConvertStringToHex(string HexString)
{
if (HexString.Length % 2 == 1)
throw new Exception("The binary key cannot have an odd number of digits");
byte[] arr = new byte[HexString.Length >> 1];
for (int i = 0; i < (HexString.Length >> 1); ++i)
{
arr[i] = (byte)((GetHexVal(HexString[i << 1]) << 4) + GetHexVal(HexString[(i << 1) + 1]));
}
return arr;
}
public static int GetHexVal(char hex)
{
int val = (int)hex;
//For uppercase A-F letters:
//return val - (val < 58 ? 48 : 55);
//For lowercase a-f letters:
//return val - (val < 58 ? 48 : 87);
//Or the two combined, but a bit slower:
return val - (val < 58 ? 48 : (val < 97 ? 55 : 87));
}
}
}
+21
View File
@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2018, Rene Lergner - wpinternals.net - @Heathcliff74xda
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
+426
View File
@@ -0,0 +1,426 @@
namespace Patcher
{
partial class MainForm
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.label1 = new System.Windows.Forms.Label();
this.txtVisualStudioPath = new System.Windows.Forms.TextBox();
this.FolderBrowserDialog = new System.Windows.Forms.FolderBrowserDialog();
this.OpenFileDialog = new System.Windows.Forms.OpenFileDialog();
this.SaveFileDialog = new System.Windows.Forms.SaveFileDialog();
this.cmdVisualStudioPath = new System.Windows.Forms.Button();
this.cmdInputFile = new System.Windows.Forms.Button();
this.txtInputFile = new System.Windows.Forms.TextBox();
this.label2 = new System.Windows.Forms.Label();
this.cmdOutputFile = new System.Windows.Forms.Button();
this.txtOutputFile = new System.Windows.Forms.TextBox();
this.label3 = new System.Windows.Forms.Label();
this.cmdPatchDefinitionsFile = new System.Windows.Forms.Button();
this.txtPatchDefinitionsFile = new System.Windows.Forms.TextBox();
this.label4 = new System.Windows.Forms.Label();
this.label5 = new System.Windows.Forms.Label();
this.cmbPatchDefinitionName = new System.Windows.Forms.ComboBox();
this.cmbTargetVersion = new System.Windows.Forms.ComboBox();
this.label6 = new System.Windows.Forms.Label();
this.cmbTargetPath = new System.Windows.Forms.ComboBox();
this.label7 = new System.Windows.Forms.Label();
this.label8 = new System.Windows.Forms.Label();
this.txtAssemblyCode = new System.Windows.Forms.TextBox();
this.txtCompiledOpcodes = new System.Windows.Forms.TextBox();
this.label9 = new System.Windows.Forms.Label();
this.txtVirtualOffset = new System.Windows.Forms.TextBox();
this.label10 = new System.Windows.Forms.Label();
this.cmbCodeType = new System.Windows.Forms.ComboBox();
this.label11 = new System.Windows.Forms.Label();
this.cmdCompile = new System.Windows.Forms.Button();
this.cmdPatch = new System.Windows.Forms.Button();
this.SuspendLayout();
//
// label1
//
this.label1.AutoSize = true;
this.label1.Location = new System.Drawing.Point(15, 13);
this.label1.Name = "label1";
this.label1.Size = new System.Drawing.Size(191, 13);
this.label1.TabIndex = 0;
this.label1.Text = "Path to Visual Studio with ARM32 SDK";
//
// txtVisualStudioPath
//
this.txtVisualStudioPath.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.txtVisualStudioPath.Location = new System.Drawing.Point(18, 29);
this.txtVisualStudioPath.Name = "txtVisualStudioPath";
this.txtVisualStudioPath.Size = new System.Drawing.Size(665, 20);
this.txtVisualStudioPath.TabIndex = 1;
//
// OpenFileDialog
//
this.OpenFileDialog.FileName = "openFileDialog1";
//
// cmdVisualStudioPath
//
this.cmdVisualStudioPath.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
this.cmdVisualStudioPath.Font = new System.Drawing.Font("Arial", 9.75F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.cmdVisualStudioPath.Location = new System.Drawing.Point(689, 28);
this.cmdVisualStudioPath.Name = "cmdVisualStudioPath";
this.cmdVisualStudioPath.Size = new System.Drawing.Size(35, 22);
this.cmdVisualStudioPath.TabIndex = 2;
this.cmdVisualStudioPath.Text = "...";
this.cmdVisualStudioPath.UseVisualStyleBackColor = true;
this.cmdVisualStudioPath.Click += new System.EventHandler(this.cmdVisualStudioPath_Click);
//
// cmdInputFile
//
this.cmdInputFile.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
this.cmdInputFile.Font = new System.Drawing.Font("Arial", 9.75F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.cmdInputFile.Location = new System.Drawing.Point(689, 301);
this.cmdInputFile.Name = "cmdInputFile";
this.cmdInputFile.Size = new System.Drawing.Size(35, 22);
this.cmdInputFile.TabIndex = 14;
this.cmdInputFile.Text = "...";
this.cmdInputFile.UseVisualStyleBackColor = true;
this.cmdInputFile.Click += new System.EventHandler(this.cmdInputFile_Click);
//
// txtInputFile
//
this.txtInputFile.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.txtInputFile.Location = new System.Drawing.Point(18, 302);
this.txtInputFile.Name = "txtInputFile";
this.txtInputFile.Size = new System.Drawing.Size(665, 20);
this.txtInputFile.TabIndex = 13;
//
// label2
//
this.label2.AutoSize = true;
this.label2.Location = new System.Drawing.Point(15, 286);
this.label2.Name = "label2";
this.label2.Size = new System.Drawing.Size(47, 13);
this.label2.TabIndex = 12;
this.label2.Text = "Input file";
//
// cmdOutputFile
//
this.cmdOutputFile.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
this.cmdOutputFile.Font = new System.Drawing.Font("Arial", 9.75F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.cmdOutputFile.Location = new System.Drawing.Point(689, 349);
this.cmdOutputFile.Name = "cmdOutputFile";
this.cmdOutputFile.Size = new System.Drawing.Size(35, 22);
this.cmdOutputFile.TabIndex = 17;
this.cmdOutputFile.Text = "...";
this.cmdOutputFile.UseVisualStyleBackColor = true;
this.cmdOutputFile.Click += new System.EventHandler(this.cmdOutputFile_Click);
//
// txtOutputFile
//
this.txtOutputFile.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.txtOutputFile.Location = new System.Drawing.Point(18, 350);
this.txtOutputFile.Name = "txtOutputFile";
this.txtOutputFile.Size = new System.Drawing.Size(665, 20);
this.txtOutputFile.TabIndex = 16;
//
// label3
//
this.label3.AutoSize = true;
this.label3.Location = new System.Drawing.Point(15, 334);
this.label3.Name = "label3";
this.label3.Size = new System.Drawing.Size(101, 13);
this.label3.TabIndex = 15;
this.label3.Text = "Output file (optional)";
//
// cmdPatchDefinitionsFile
//
this.cmdPatchDefinitionsFile.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
this.cmdPatchDefinitionsFile.Font = new System.Drawing.Font("Arial", 9.75F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.cmdPatchDefinitionsFile.Location = new System.Drawing.Point(689, 91);
this.cmdPatchDefinitionsFile.Name = "cmdPatchDefinitionsFile";
this.cmdPatchDefinitionsFile.Size = new System.Drawing.Size(35, 22);
this.cmdPatchDefinitionsFile.TabIndex = 5;
this.cmdPatchDefinitionsFile.Text = "...";
this.cmdPatchDefinitionsFile.UseVisualStyleBackColor = true;
this.cmdPatchDefinitionsFile.Click += new System.EventHandler(this.cmdPatchDefinitionsFile_Click);
//
// txtPatchDefinitionsFile
//
this.txtPatchDefinitionsFile.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.txtPatchDefinitionsFile.Location = new System.Drawing.Point(18, 92);
this.txtPatchDefinitionsFile.Name = "txtPatchDefinitionsFile";
this.txtPatchDefinitionsFile.Size = new System.Drawing.Size(665, 20);
this.txtPatchDefinitionsFile.TabIndex = 4;
this.txtPatchDefinitionsFile.Leave += new System.EventHandler(this.txtPatchDefinitionsFile_Leave);
//
// label4
//
this.label4.AutoSize = true;
this.label4.Location = new System.Drawing.Point(15, 76);
this.label4.Name = "label4";
this.label4.Size = new System.Drawing.Size(117, 13);
this.label4.TabIndex = 3;
this.label4.Text = "Patch defintions xml-file";
//
// label5
//
this.label5.AutoSize = true;
this.label5.Location = new System.Drawing.Point(15, 124);
this.label5.Name = "label5";
this.label5.Size = new System.Drawing.Size(107, 13);
this.label5.TabIndex = 6;
this.label5.Text = "Patch defintion name";
//
// cmbPatchDefinitionName
//
this.cmbPatchDefinitionName.FormattingEnabled = true;
this.cmbPatchDefinitionName.Location = new System.Drawing.Point(18, 140);
this.cmbPatchDefinitionName.Name = "cmbPatchDefinitionName";
this.cmbPatchDefinitionName.Size = new System.Drawing.Size(302, 21);
this.cmbPatchDefinitionName.TabIndex = 7;
this.cmbPatchDefinitionName.SelectedValueChanged += new System.EventHandler(this.cmbPatchDefinitionName_SelectedValueChanged);
this.cmbPatchDefinitionName.Leave += new System.EventHandler(this.cmbPatchDefinitionName_Leave);
//
// cmbTargetVersion
//
this.cmbTargetVersion.FormattingEnabled = true;
this.cmbTargetVersion.Location = new System.Drawing.Point(18, 189);
this.cmbTargetVersion.Name = "cmbTargetVersion";
this.cmbTargetVersion.Size = new System.Drawing.Size(302, 21);
this.cmbTargetVersion.TabIndex = 9;
this.cmbTargetVersion.SelectedValueChanged += new System.EventHandler(this.cmbTargetVersion_SelectedValueChanged);
this.cmbTargetVersion.Leave += new System.EventHandler(this.cmbTargetVersion_Leave);
//
// label6
//
this.label6.AutoSize = true;
this.label6.Location = new System.Drawing.Point(15, 173);
this.label6.Name = "label6";
this.label6.Size = new System.Drawing.Size(129, 13);
this.label6.TabIndex = 8;
this.label6.Text = "Target version description";
//
// cmbTargetPath
//
this.cmbTargetPath.FormattingEnabled = true;
this.cmbTargetPath.Location = new System.Drawing.Point(18, 238);
this.cmbTargetPath.Name = "cmbTargetPath";
this.cmbTargetPath.Size = new System.Drawing.Size(302, 21);
this.cmbTargetPath.TabIndex = 11;
//
// label7
//
this.label7.AutoSize = true;
this.label7.Location = new System.Drawing.Point(15, 222);
this.label7.Name = "label7";
this.label7.Size = new System.Drawing.Size(269, 13);
this.label7.TabIndex = 10;
this.label7.Text = "Folder for target file relative to Patch Defintion rootfolder";
//
// label8
//
this.label8.AutoSize = true;
this.label8.Location = new System.Drawing.Point(15, 497);
this.label8.Name = "label8";
this.label8.Size = new System.Drawing.Size(365, 13);
this.label8.TabIndex = 22;
this.label8.Text = "ARM32 Patch / Shell assembly code (labels need to be followed by a colon)";
//
// txtAssemblyCode
//
this.txtAssemblyCode.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
| System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.txtAssemblyCode.Font = new System.Drawing.Font("Courier New", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.txtAssemblyCode.Location = new System.Drawing.Point(18, 513);
this.txtAssemblyCode.Multiline = true;
this.txtAssemblyCode.Name = "txtAssemblyCode";
this.txtAssemblyCode.ScrollBars = System.Windows.Forms.ScrollBars.Vertical;
this.txtAssemblyCode.Size = new System.Drawing.Size(706, 161);
this.txtAssemblyCode.TabIndex = 23;
//
// txtCompiledOpcodes
//
this.txtCompiledOpcodes.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.txtCompiledOpcodes.Font = new System.Drawing.Font("Courier New", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.txtCompiledOpcodes.Location = new System.Drawing.Point(18, 713);
this.txtCompiledOpcodes.Multiline = true;
this.txtCompiledOpcodes.Name = "txtCompiledOpcodes";
this.txtCompiledOpcodes.ScrollBars = System.Windows.Forms.ScrollBars.Vertical;
this.txtCompiledOpcodes.Size = new System.Drawing.Size(706, 59);
this.txtCompiledOpcodes.TabIndex = 25;
//
// label9
//
this.label9.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.label9.AutoSize = true;
this.label9.Location = new System.Drawing.Point(15, 697);
this.label9.Name = "label9";
this.label9.Size = new System.Drawing.Size(94, 13);
this.label9.TabIndex = 24;
this.label9.Text = "Compiled opcodes";
//
// txtVirtualOffset
//
this.txtVirtualOffset.Location = new System.Drawing.Point(18, 416);
this.txtVirtualOffset.Name = "txtVirtualOffset";
this.txtVirtualOffset.Size = new System.Drawing.Size(302, 20);
this.txtVirtualOffset.TabIndex = 19;
//
// label10
//
this.label10.AutoSize = true;
this.label10.Location = new System.Drawing.Point(15, 400);
this.label10.Name = "label10";
this.label10.Size = new System.Drawing.Size(309, 13);
this.label10.TabIndex = 18;
this.label10.Text = "Virtual offset (hex) (leave empty for only recalculating checksum)";
//
// cmbCodeType
//
this.cmbCodeType.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
this.cmbCodeType.FormattingEnabled = true;
this.cmbCodeType.Items.AddRange(new object[] {
"ARM",
"Thumb",
"Thumb2"});
this.cmbCodeType.Location = new System.Drawing.Point(18, 464);
this.cmbCodeType.Name = "cmbCodeType";
this.cmbCodeType.Size = new System.Drawing.Size(302, 21);
this.cmbCodeType.TabIndex = 21;
//
// label11
//
this.label11.AutoSize = true;
this.label11.Location = new System.Drawing.Point(15, 448);
this.label11.Name = "label11";
this.label11.Size = new System.Drawing.Size(55, 13);
this.label11.TabIndex = 20;
this.label11.Text = "Code type";
//
// cmdCompile
//
this.cmdCompile.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
this.cmdCompile.Location = new System.Drawing.Point(470, 792);
this.cmdCompile.Name = "cmdCompile";
this.cmdCompile.Size = new System.Drawing.Size(120, 33);
this.cmdCompile.TabIndex = 26;
this.cmdCompile.Text = "Compile";
this.cmdCompile.UseVisualStyleBackColor = true;
this.cmdCompile.Click += new System.EventHandler(this.cmdCompile_Click);
//
// cmdPatch
//
this.cmdPatch.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
this.cmdPatch.Location = new System.Drawing.Point(604, 792);
this.cmdPatch.Name = "cmdPatch";
this.cmdPatch.Size = new System.Drawing.Size(120, 33);
this.cmdPatch.TabIndex = 27;
this.cmdPatch.Text = "Patch";
this.cmdPatch.UseVisualStyleBackColor = true;
this.cmdPatch.Click += new System.EventHandler(this.cmdPatch_Click);
//
// MainForm
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(742, 840);
this.Controls.Add(this.cmdPatch);
this.Controls.Add(this.cmdCompile);
this.Controls.Add(this.cmbCodeType);
this.Controls.Add(this.label11);
this.Controls.Add(this.txtVirtualOffset);
this.Controls.Add(this.label10);
this.Controls.Add(this.txtCompiledOpcodes);
this.Controls.Add(this.label9);
this.Controls.Add(this.txtAssemblyCode);
this.Controls.Add(this.label8);
this.Controls.Add(this.cmbTargetPath);
this.Controls.Add(this.label7);
this.Controls.Add(this.cmbTargetVersion);
this.Controls.Add(this.label6);
this.Controls.Add(this.cmbPatchDefinitionName);
this.Controls.Add(this.label5);
this.Controls.Add(this.cmdPatchDefinitionsFile);
this.Controls.Add(this.txtPatchDefinitionsFile);
this.Controls.Add(this.label4);
this.Controls.Add(this.cmdOutputFile);
this.Controls.Add(this.txtOutputFile);
this.Controls.Add(this.label3);
this.Controls.Add(this.cmdInputFile);
this.Controls.Add(this.txtInputFile);
this.Controls.Add(this.label2);
this.Controls.Add(this.cmdVisualStudioPath);
this.Controls.Add(this.txtVisualStudioPath);
this.Controls.Add(this.label1);
this.Name = "MainForm";
this.Text = "ARM patcher by Rene Lergner";
this.FormClosed += new System.Windows.Forms.FormClosedEventHandler(this.MainForm_FormClosed);
this.Load += new System.EventHandler(this.MainForm_Load);
this.ResumeLayout(false);
this.PerformLayout();
}
#endregion
private System.Windows.Forms.Label label1;
private System.Windows.Forms.TextBox txtVisualStudioPath;
private System.Windows.Forms.FolderBrowserDialog FolderBrowserDialog;
private System.Windows.Forms.OpenFileDialog OpenFileDialog;
private System.Windows.Forms.SaveFileDialog SaveFileDialog;
private System.Windows.Forms.Button cmdVisualStudioPath;
private System.Windows.Forms.Button cmdInputFile;
private System.Windows.Forms.TextBox txtInputFile;
private System.Windows.Forms.Label label2;
private System.Windows.Forms.Button cmdOutputFile;
private System.Windows.Forms.TextBox txtOutputFile;
private System.Windows.Forms.Label label3;
private System.Windows.Forms.Button cmdPatchDefinitionsFile;
private System.Windows.Forms.TextBox txtPatchDefinitionsFile;
private System.Windows.Forms.Label label4;
private System.Windows.Forms.Label label5;
private System.Windows.Forms.ComboBox cmbPatchDefinitionName;
private System.Windows.Forms.ComboBox cmbTargetVersion;
private System.Windows.Forms.Label label6;
private System.Windows.Forms.ComboBox cmbTargetPath;
private System.Windows.Forms.Label label7;
private System.Windows.Forms.Label label8;
private System.Windows.Forms.TextBox txtAssemblyCode;
private System.Windows.Forms.TextBox txtCompiledOpcodes;
private System.Windows.Forms.Label label9;
private System.Windows.Forms.TextBox txtVirtualOffset;
private System.Windows.Forms.Label label10;
private System.Windows.Forms.ComboBox cmbCodeType;
private System.Windows.Forms.Label label11;
private System.Windows.Forms.Button cmdCompile;
private System.Windows.Forms.Button cmdPatch;
}
}
+410
View File
@@ -0,0 +1,410 @@
// Copyright (c) 2018, Rene Lergner - wpinternals.net - @Heathcliff74xda
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using Microsoft.Win32;
using System;
using System.Collections.Generic;
using System.Data;
using System.IO;
using System.Linq;
using System.Windows.Forms;
using WPinternals;
namespace Patcher
{
public partial class MainForm : Form
{
public MainForm()
{
InitializeComponent();
}
private void MainForm_Load(object sender, EventArgs e)
{
cmbCodeType.SelectedItem = "Thumb2";
LoadPaths();
CenterToScreen();
}
private void cmdCompile_Click(object sender, EventArgs e)
{
string VirtualOffsetString = txtVirtualOffset.Text.Trim();
if (VirtualOffsetString.StartsWith("0x", StringComparison.OrdinalIgnoreCase))
VirtualOffsetString = VirtualOffsetString[2..];
CodeType CodeType = Patcher.CodeType.Thumb2;
byte[] CompiledCode = null;
if (UInt32.TryParse(VirtualOffsetString, System.Globalization.NumberStyles.HexNumber, null, out uint 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 LoadPaths()
{
RegistryKey Key = Registry.CurrentUser.OpenSubKey(@"Software\Patcher", true) ?? Registry.CurrentUser.CreateSubKey(@"Software\Patcher");
txtVisualStudioPath.Text = (string)Key.GetValue("VisualStudioPath", "");
if (txtVisualStudioPath.Text.Length == 0)
txtVisualStudioPath.Text = FindVisualStudioPath();
txtPatchDefinitionsFile.Text = (string)Key.GetValue("PatchDefinitionsFilePath", "");
cmbPatchDefinitionName.Text = (string)Key.GetValue("PatchDefinitionName", "");
cmbTargetVersion.Text = (string)Key.GetValue("TargetVersion", "");
cmbTargetPath.Text = (string)Key.GetValue("TargetFilePath", "");
txtInputFile.Text = (string)Key.GetValue("InputFilePath", "");
txtOutputFile.Text = (string)Key.GetValue("OutputFilePath", "");
LoadPatchDefinitions();
}
public static string[] FindMSVCBinaryPaths(string s)
{
string LegacyPath = Path.Combine(s, @"VC\bin");
if (Directory.Exists(LegacyPath))
{
return new string[] { LegacyPath };
}
if (Directory.Exists(Path.Combine(s, @"VC\Tools\MSVC")))
{
IEnumerable<string> MSVCs = Directory.EnumerateDirectories(Path.Combine(s, @"VC\Tools\MSVC"));
IEnumerable<string> Bins = MSVCs.Select(s => Path.Combine(s, "bin")).Where(s => Directory.Exists(s));
return Bins.ToArray();
}
return Array.Empty<string>();
}
public static string FindArmAsmPath(string s)
{
foreach (string MSVCBin in FindMSVCBinaryPaths(s))
{
string path1 = Path.Combine(MSVCBin, "x86_arm");
string path2 = Path.Combine(MSVCBin, @"Hostx86\arm");
if (File.Exists(Path.Combine(path1, "armasm.exe")))
{
return path1;
}
if (File.Exists(Path.Combine(path2, "armasm.exe")))
{
return path2;
}
}
return "";
}
private static string FindVisualStudioPath()
{
IEnumerable<string> MainX86VSDirectories = Directory.EnumerateDirectories(@"C:\Program Files (x86)\", "Microsoft Visual Studio*");
IEnumerable<string> MainX64VSDirectories = Directory.EnumerateDirectories(@"C:\Program Files\", "Microsoft Visual Studio*");
IEnumerable<string> MainVSDirectories = MainX86VSDirectories.Union(MainX64VSDirectories);
IEnumerable<string> SubMainVSDirectories = MainVSDirectories.SelectMany(s => Directory.EnumerateDirectories(s));
IEnumerable<string> SubSubMainVSDirectories = SubMainVSDirectories.SelectMany(s => Directory.EnumerateDirectories(s));
IEnumerable<string> Directories = MainVSDirectories.Union(SubMainVSDirectories).Union(SubSubMainVSDirectories);
string attempt1 = Directories.Where(s => FindArmAsmPath(s) != "").OrderByDescending(s => File.GetCreationTime(Path.Combine(s, @"VC\bin\x86_arm\armasm.exe"))).FirstOrDefault() ?? "";
if (attempt1 != "")
return attempt1;
return Directories.Where(s => Directory.Exists(Path.Combine(s, @"VC\Tools\MSVC"))).Select(s => Path.Combine(s, @"VC\Tools\MSVC")).SelectMany(s => Directory.EnumerateDirectories(s)).Where(s => File.Exists(Path.Combine(s, @"bin\Hostx86\arm\armasm.exe"))).OrderByDescending(s => File.GetCreationTime(Path.Combine(s, @"bin\Hostx86\arm\armasm.exe"))).FirstOrDefault() ?? "";
}
private void StorePaths()
{
RegistryKey Key = Registry.CurrentUser.OpenSubKey(@"Software\Patcher", true) ?? Registry.CurrentUser.CreateSubKey(@"Software\Patcher");
string VisualStudioPath = txtVisualStudioPath.Text.Trim();
if (VisualStudioPath.Length == 0)
{
if (Key.GetValue("VisualStudioPath") != null)
Key.DeleteValue("VisualStudioPath");
}
else
{
Key.SetValue("VisualStudioPath", VisualStudioPath);
}
string PatchDefinitionsFilePath = txtPatchDefinitionsFile.Text.Trim();
if (PatchDefinitionsFilePath.Length == 0)
{
if (Key.GetValue("PatchDefinitionsFilePath") != null)
Key.DeleteValue("PatchDefinitionsFilePath");
}
else
{
Key.SetValue("PatchDefinitionsFilePath", PatchDefinitionsFilePath);
}
string PatchDefinitionName = cmbPatchDefinitionName.Text.Trim();
if (PatchDefinitionName.Length == 0)
{
if (Key.GetValue("PatchDefinitionName") != null)
Key.DeleteValue("PatchDefinitionName");
}
else
{
Key.SetValue("PatchDefinitionName", PatchDefinitionName);
}
string TargetVersion = cmbTargetVersion.Text.Trim();
if (TargetVersion.Length == 0)
{
if (Key.GetValue("TargetVersion") != null)
Key.DeleteValue("TargetVersion");
}
else
{
Key.SetValue("TargetVersion", TargetVersion);
}
string TargetFilePath = cmbTargetPath.Text.Trim();
if (TargetFilePath.Length == 0)
{
if (Key.GetValue("TargetFilePath") != null)
Key.DeleteValue("TargetFilePath");
}
else
{
Key.SetValue("TargetFilePath", TargetFilePath);
}
string InputFilePath = txtInputFile.Text.Trim();
if (InputFilePath.Length == 0)
{
if (Key.GetValue("InputFilePath") != null)
Key.DeleteValue("InputFilePath");
}
else
{
Key.SetValue("InputFilePath", InputFilePath);
}
string OutputFilePath = txtOutputFile.Text.Trim();
if (OutputFilePath.Length == 0)
{
if (Key.GetValue("OutputFilePath") != null)
Key.DeleteValue("OutputFilePath");
}
else
{
Key.SetValue("OutputFilePath", OutputFilePath);
}
}
private bool LoadingPatchDefinitions = false;
private void LoadPatchDefinitions()
{
if (LoadingPatchDefinitions)
return;
LoadingPatchDefinitions = true;
string PatchDefinitionName = cmbPatchDefinitionName.Text;
string TargetVersion = cmbTargetVersion.Text;
string TargetPath = cmbTargetPath.Text;
cmbPatchDefinitionName.SelectedIndex = -1;
cmbTargetVersion.SelectedIndex = -1;
cmbTargetPath.SelectedIndex = -1;
cmbPatchDefinitionName.Items.Clear();
cmbTargetVersion.Items.Clear();
cmbTargetPath.Items.Clear();
cmbPatchDefinitionName.Text = PatchDefinitionName;
cmbTargetVersion.Text = TargetVersion;
cmbTargetPath.Text = TargetPath;
try
{
string Definitions = File.ReadAllText(txtPatchDefinitionsFile.Text);
PatchEngine Engine = new(Definitions);
Engine.PatchDefinitions.Where(d => !string.IsNullOrEmpty(d.Name)).Select(d => d.Name).Distinct().ToList().ForEach(n => cmbPatchDefinitionName.Items.Add(n));
PatchDefinition Definition = null;
if (cmbPatchDefinitionName.Text.Trim().Length > 0)
Definition = Engine.PatchDefinitions.Find(d => string.Equals(d.Name, cmbPatchDefinitionName.Text.Trim(), StringComparison.CurrentCultureIgnoreCase));
if (Definition != null)
{
Definition.TargetVersions.Where(v => !string.IsNullOrEmpty(v.Description)).Select(v => v.Description).Distinct().ToList().ForEach(d => cmbTargetVersion.Items.Add(d));
TargetVersion Version = null;
if (cmbTargetVersion.Text.Trim().Length > 0)
Version = Definition.TargetVersions.Find(v => string.Equals(v.Description, cmbTargetVersion.Text.Trim(), StringComparison.CurrentCultureIgnoreCase));
if (Version != null)
{
Version.TargetFiles.Where(f => !string.IsNullOrEmpty(f.Path)).Select(f => Path.GetDirectoryName(f.Path)).Distinct().ToList().ForEach(f => cmbTargetPath.Items.Add(f));
}
}
}
catch { }
LoadingPatchDefinitions = false;
}
private void cmdVisualStudioPath_Click(object sender, EventArgs e)
{
FolderBrowserDialog.SelectedPath = txtVisualStudioPath.Text;
FolderBrowserDialog.Description = "Select path to Visual Studio with ARM32 SDK";
System.Windows.Forms.DialogResult Result = FolderBrowserDialog.ShowDialog();
if (Result == System.Windows.Forms.DialogResult.OK)
txtVisualStudioPath.Text = FolderBrowserDialog.SelectedPath;
}
private void cmdPatchDefinitionsFile_Click(object sender, EventArgs e)
{
OpenFileDialog.CheckFileExists = false;
OpenFileDialog.DefaultExt = "xml";
try
{
OpenFileDialog.FileName = Path.GetFileName(txtPatchDefinitionsFile.Text);
OpenFileDialog.InitialDirectory = Path.GetDirectoryName(txtPatchDefinitionsFile.Text);
}
catch { }
OpenFileDialog.Multiselect = false;
OpenFileDialog.Title = "Open patch-definitions file";
System.Windows.Forms.DialogResult Result = OpenFileDialog.ShowDialog();
if (Result == System.Windows.Forms.DialogResult.OK)
{
txtPatchDefinitionsFile.Text = OpenFileDialog.FileName;
WindowsFormsSynchronizationContext.Current.Post(s => LoadPatchDefinitions(), null);
}
}
private void txtPatchDefinitionsFile_Leave(object sender, EventArgs e)
{
WindowsFormsSynchronizationContext.Current.Post(s => LoadPatchDefinitions(), null);
}
private void MainForm_FormClosed(object sender, FormClosedEventArgs e)
{
StorePaths();
}
private void cmbPatchDefinitionName_SelectedValueChanged(object sender, EventArgs e)
{
WindowsFormsSynchronizationContext.Current.Post(s => LoadPatchDefinitions(), null);
}
private void cmbPatchDefinitionName_Leave(object sender, EventArgs e)
{
WindowsFormsSynchronizationContext.Current.Post(s => LoadPatchDefinitions(), null);
}
private void cmbTargetVersion_SelectedValueChanged(object sender, EventArgs e)
{
WindowsFormsSynchronizationContext.Current.Post(s => LoadPatchDefinitions(), null);
}
private void cmbTargetVersion_Leave(object sender, EventArgs e)
{
WindowsFormsSynchronizationContext.Current.Post(s => LoadPatchDefinitions(), null);
}
private void cmdInputFile_Click(object sender, EventArgs e)
{
OpenFileDialog.CheckFileExists = true;
OpenFileDialog.DefaultExt = "";
try
{
OpenFileDialog.FileName = Path.GetFileName(txtInputFile.Text);
OpenFileDialog.InitialDirectory = Path.GetDirectoryName(txtInputFile.Text);
}
catch { }
OpenFileDialog.Multiselect = false;
OpenFileDialog.Title = "Open input file";
System.Windows.Forms.DialogResult Result = OpenFileDialog.ShowDialog();
if (Result == System.Windows.Forms.DialogResult.OK)
{
txtInputFile.Text = OpenFileDialog.FileName;
txtOutputFile.Text = "";
}
}
private void cmdOutputFile_Click(object sender, EventArgs e)
{
SaveFileDialog.CheckFileExists = false;
SaveFileDialog.DefaultExt = "";
try
{
SaveFileDialog.FileName = Path.GetFileName(txtInputFile.Text);
SaveFileDialog.InitialDirectory = Path.GetDirectoryName(txtOutputFile.Text);
}
catch { }
SaveFileDialog.Title = "Open input file";
System.Windows.Forms.DialogResult Result = SaveFileDialog.ShowDialog();
if (Result == System.Windows.Forms.DialogResult.OK)
txtOutputFile.Text = SaveFileDialog.FileName;
}
private void cmdPatch_Click(object sender, EventArgs e)
{
string VirtualOffsetString = txtVirtualOffset.Text.Trim();
if (VirtualOffsetString.StartsWith("0x", StringComparison.OrdinalIgnoreCase))
VirtualOffsetString = VirtualOffsetString[2..];
CodeType CodeType = Patcher.CodeType.Thumb2;
byte[] CompiledCode = null;
if (UInt32.TryParse(VirtualOffsetString, System.Globalization.NumberStyles.HexNumber, null, out uint VirtualAddress))
{
CodeType = (CodeType)Enum.Parse(typeof(Patcher.CodeType), cmbCodeType.SelectedItem.ToString());
CompiledCode = ArmCompiler.Compile(txtVisualStudioPath.Text, VirtualAddress, CodeType, txtAssemblyCode.Text);
}
if ((VirtualAddress != 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[1..];
try
{
MainPatcher.AddPatch(txtInputFile.Text, (txtOutputFile.Text.Trim().Length > 0) ? txtOutputFile.Text : null, cmbPatchDefinitionName.Text, cmbTargetVersion.Text, TargetFilePath, txtVisualStudioPath.Text, VirtualAddress, CodeType, txtAssemblyCode.Text, txtPatchDefinitionsFile.Text);
}
catch (ArgumentOutOfRangeException)
{
txtCompiledOpcodes.Text = "BAD VIRTUAL OFFSET";
}
catch
{
txtCompiledOpcodes.Text = "UNKNOWN ERROR";
}
txtVirtualOffset.Focus();
txtVirtualOffset.SelectAll();
}
}
}
}
+129
View File
@@ -0,0 +1,129 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<metadata name="FolderBrowserDialog.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>17, 17</value>
</metadata>
<metadata name="OpenFileDialog.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>182, 17</value>
</metadata>
<metadata name="SaveFileDialog.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>317, 17</value>
</metadata>
</root>
+189
View File
@@ -0,0 +1,189 @@
// Copyright (c) 2018, Rene Lergner - wpinternals.net - @Heathcliff74xda
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
using System.IO;
using System.Linq;
using System.Security.Cryptography;
using WPinternals;
namespace Patcher
{
public static class MainPatcher
{
/// <summary>
/// TargetFilePath is relative to the root of the PatchDefinition
/// OutputFilePath can be null
/// </summary>
/// <param name="InputFilePath"></param>
/// <param name="OutputFilePath"></param>
/// <param name="PatchDefinitionName"></param>
/// <param name="TargetVersionDescription"></param>
/// <param name="TargetFilePath"></param>
/// <param name="PathToVisualStudioWithWP8SDK"></param>
/// <param name="VirtualAddress"></param>
/// <param name="CodeType"></param>
/// <param name="ArmCodeFragment"></param>
/// <param name="PatchDefintionsXmlPath"></param>
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();
// 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(Binary);
UInt32 RawOffset = 0;
if (VirtualAddress != 0)
RawOffset = PeFile.ConvertVirtualAddressToRawOffset(VirtualAddress);
// Add or replace patch
string PatchDefintionsXml = File.ReadAllText(PatchDefintionsXmlPath);
PatchEngine PatchEngine = new(PatchDefintionsXml);
PatchDefinition PatchDefinition = PatchEngine.PatchDefinitions.Find(d => string.Equals(d.Name, PatchDefinitionName, StringComparison.CurrentCultureIgnoreCase));
if (PatchDefinition == null)
{
PatchDefinition = new PatchDefinition
{
Name = PatchDefinitionName
};
PatchEngine.PatchDefinitions.Add(PatchDefinition);
}
TargetVersion TargetVersion = PatchDefinition.TargetVersions.Find(v => string.Equals(v.Description, TargetVersionDescription, StringComparison.CurrentCultureIgnoreCase));
if (TargetVersion == null)
{
TargetVersion = new TargetVersion
{
Description = TargetVersionDescription
};
PatchDefinition.TargetVersions.Add(TargetVersion);
}
TargetFile TargetFile = TargetVersion.TargetFiles.Find(f => (f.Path != null) && (string.Equals(f.Path.TrimStart(new char[] { '\\' }), TargetFilePath.TrimStart(new char[] { '\\' }), StringComparison.CurrentCultureIgnoreCase)));
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.Find(p => p.Address == RawOffset);
if (Patch == null)
{
Patch = new 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.Find(p => p.Address == ChecksumOffset);
if (Patch == null)
{
Patch = new 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);
}
private static UInt32 CalculateChecksum(byte[] PEFile)
{
UInt32 Checksum = 0;
UInt32 Hi;
// Clear file checksum
ByteOperations.WriteUInt32(PEFile, GetChecksumOffset(PEFile), 0);
for (UInt32 i = 0; i < ((UInt32)PEFile.Length & 0xfffffffe); i += 2)
{
Checksum += ByteOperations.ReadUInt16(PEFile, i);
Hi = Checksum >> 16;
if (Hi != 0)
{
Checksum = Hi + (Checksum & 0xFFFF);
}
}
if ((PEFile.Length % 2) != 0)
{
Checksum += (UInt32)ByteOperations.ReadUInt8(PEFile, (UInt32)PEFile.Length - 1);
Hi = Checksum >> 16;
if (Hi != 0)
{
Checksum = Hi + (Checksum & 0xFFFF);
}
}
Checksum += (UInt32)PEFile.Length;
// Write file checksum
ByteOperations.WriteUInt32(PEFile, GetChecksumOffset(PEFile), Checksum);
return Checksum;
}
private static UInt32 GetChecksumOffset(byte[] PEFile)
{
return ByteOperations.ReadUInt32(PEFile, 0x3C) + +0x58;
}
}
}
+819
View File
@@ -0,0 +1,819 @@
// Copyright (c) 2018, Rene Lergner - wpinternals.net - @Heathcliff74xda
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
// This code is based on Get-ObjDump from Matthew Graeber (@mattifestation)
using System;
using System.IO;
using System.Text;
using System.Linq;
namespace COFF
{
public enum Machine : ushort
{
UNKNOWN = 0,
/// <summary>
/// Intel 386.
/// </summary>
I386 = 0x014C,
/// <summary>
/// MIPS little-endian =0x160 big-endian
/// </summary>
R3000 = 0x0162,
/// <summary>
/// MIPS little-endian
/// </summary>
R4000 = 0x0166,
/// <summary>
/// MIPS little-endian
/// </summary>
R10000 = 0x0168,
/// <summary>
/// MIPS little-endian WCE v2
/// </summary>
WCEMIPSV2 = 0x0169,
/// <summary>
/// Alpha_AXP
/// </summary>
ALPHA = 0x0184,
/// <summary>
/// SH3 little-endian
/// </summary>
SH3 = 0x01A2,
SH3DSP = 0x01A3,
/// <summary>
/// SH3E little-endian
/// </summary>
SH3E = 0x01A4,
/// <summary>
/// SH4 little-endian
/// </summary>
SH4 = 0x01A6,
/// <summary>
/// SH5
/// </summary>
SH5 = 0x01A8,
/// <summary>
/// ARM Little-Endian
/// </summary>
ARM = 0x01C0,
THUMB = 0x01C2,
/// <summary>
/// ARM Thumb-2 Little-Endian
/// </summary>
ARMV7 = 0x01C4,
AM33 = 0x01D3,
/// <summary>
/// IBM PowerPC Little-Endian
/// </summary>
POWERPC = 0x01F0,
POWERPCFP = 0x01F1,
/// <summary>
/// Intel 64
/// </summary>
IA64 = 0x0200,
/// <summary>
/// MIPS
/// </summary>
MIPS16 = 0x0266,
/// <summary>
/// ALPHA64
/// </summary>
ALPHA64 = 0x0284,
/// <summary>
/// MIPS
/// </summary>
MIPSFPU = 0x0366,
/// <summary>
/// MIPS
/// </summary>
MIPSFPU16 = 0x0466,
AXP64 = ALPHA64,
/// <summary>
/// Infineon
/// </summary>
TRICORE = 0x0520,
CEF = 0x0CEF,
/// <summary>
/// EFI public byte Code
/// </summary>
EBC = 0x0EBC,
/// <summary>
/// AMD64 (K8)
/// </summary>
AMD64 = 0x8664,
/// <summary>
/// M32R little-endian
/// </summary>
M32R = 0x9041,
/// <summary>
/// ARMv8 in 64-bit mode
/// </summary>
ARM64 = 0xAA64,
CEE = 0xC0EE
}
[Flags]
public enum CoffHeaderCharacteristics : ushort
{
/// <summary>
/// Relocation info stripped from file.
/// </summary>
RELOCS_STRIPPED = 0x0001,
/// <summary>
/// File is executable (i.e. no unresolved external references).
/// </summary>
EXECUTABLE_IMAGE = 0x0002,
/// <summary>
/// Line nunbers stripped from file.
/// </summary>
LINE_NUMS_STRIPPED = 0x0004,
/// <summary>
/// Local symbols stripped from file.
/// </summary>
LOCAL_SYMS_STRIPPED = 0x0008,
/// <summary>
/// Agressively trim working set
/// </summary>
AGGRESIVE_WS_TRIM = 0x0010,
/// <summary>
/// App can handle >2gb addresses
/// </summary>
LARGE_ADDRESS_AWARE = 0x0020,
/// <summary>
/// public bytes of machine public ushort are reversed.
/// </summary>
REVERSED_LO = 0x0080,
/// <summary>
/// 32 bit public ushort machine.
/// </summary>
BIT32_MACHINE = 0x0100,
/// <summary>
/// Debugging info stripped from file in .DBG file
/// </summary>
DEBUG_STRIPPED = 0x0200,
/// <summary>
/// If Image is on removable media =copy and run from the swap file.
/// </summary>
REMOVABLE_RUN_FROM_SWAP = 0x0400,
/// <summary>
/// If Image is on Net =copy and run from the swap file.
/// </summary>
NET_RUN_FROM_SWAP = 0x0800,
/// <summary>
/// System File.
/// </summary>
SYSTEM = 0x1000,
/// <summary>
/// File is a DLL.
/// </summary>
DLL = 0x2000,
/// <summary>
/// File should only be run on a UP machine
/// </summary>
UP_SYSTEM_ONLY = 0x4000,
/// <summary>
/// public bytes of machine public ushort are reversed.
/// </summary>
REVERSED_HI = 0x8000
}
public class HEADER
{
public Machine Machine;
public ushort NumberOfSections;
public DateTime TimeDateStamp;
public uint PointerToSymbolTable;
public uint NumberOfSymbols;
public ushort SizeOfOptionalHeader;
public CoffHeaderCharacteristics Characteristics;
public HEADER(BinaryReader br)
{
this.Machine = (Machine)br.ReadUInt16();
this.NumberOfSections = br.ReadUInt16();
this.TimeDateStamp = new DateTime(1970, 1, 1, 0, 0, 0).AddSeconds(br.ReadUInt32());
this.PointerToSymbolTable = br.ReadUInt32();
this.NumberOfSymbols = br.ReadUInt32();
this.SizeOfOptionalHeader = br.ReadUInt16();
this.Characteristics = (CoffHeaderCharacteristics)br.ReadUInt16();
}
}
[Flags]
public enum SectionHeaderCharacteristics : uint
{
/// <summary>
/// Reserved.
/// </summary>
TYPE_NO_PAD = 0x00000008,
/// <summary>
/// Section contains code.
/// </summary>
CNT_CODE = 0x00000020,
/// <summary>
/// Section contains initialized data.
/// </summary>
CNT_INITIALIZED_DATA = 0x00000040,
/// <summary>
/// Section contains uninitialized data.
/// </summary>
CNT_UNINITIALIZED_DATA = 0x00000080,
/// <summary>
/// Section contains comments or some other type of information.
/// </summary>
LNK_INFO = 0x00000200,
/// <summary>
/// Section contents will not become part of image.
/// </summary>
LNK_REMOVE = 0x00000800,
/// <summary>
/// Section contents comdat.
/// </summary>
LNK_COMDAT = 0x00001000,
/// <summary>
/// Reset speculative exceptions handling bits in the TLB entries for this section.
/// </summary>
NO_DEFER_SPEC_EXC = 0x00004000,
/// <summary>
/// Section content can be accessed relative to GP
/// </summary>
GPREL = 0x00008000,
MEM_FARDATA = 0x00008000,
MEM_PURGEABLE = 0x00020000,
MEM_16BIT = 0x00020000,
MEM_LOCKED = 0x00040000,
MEM_PRELOAD = 0x00080000,
ALIGN_1BYTES = 0x00100000,
ALIGN_2BYTES = 0x00200000,
ALIGN_4BYTES = 0x00300000,
ALIGN_8BYTES = 0x00400000,
/// <summary>
/// Default alignment if no others are specified.
/// </summary>
ALIGN_16BYTES = 0x00500000,
ALIGN_32BYTES = 0x00600000,
ALIGN_64BYTES = 0x00700000,
ALIGN_128BYTES = 0x00800000,
ALIGN_256BYTES = 0x00900000,
ALIGN_512BYTES = 0x00A00000,
ALIGN_1024BYTES = 0x00B00000,
ALIGN_2048BYTES = 0x00C00000,
ALIGN_4096BYTES = 0x00D00000,
ALIGN_8192BYTES = 0x00E00000,
ALIGN_MASK = 0x00F00000,
/// <summary>
/// Section contains extended relocations.
/// </summary>
LNK_NRELOC_OVFL = 0x01000000,
/// <summary>
/// Section can be discarded.
/// </summary>
MEM_DISCARDABLE = 0x02000000,
/// <summary>
/// Section is not cachable.
/// </summary>
MEM_NOT_CACHED = 0x04000000,
/// <summary>
/// Section is not pageable.
/// </summary>
MEM_NOT_PAGED = 0x08000000,
/// <summary>
/// Section is shareable.
/// </summary>
MEM_SHARED = 0x10000000,
/// <summary>
/// Section is executable.
/// </summary>
MEM_EXECUTE = 0x20000000,
/// <summary>
/// Section is readable.
/// </summary>
MEM_READ = 0x40000000,
/// <summary>
/// Section is writeable.
/// </summary>
MEM_WRITE = 0x80000000
}
public enum AMD64RelocationType : ushort
{
ABSOLUTE,
ADDR64,
ADDR32,
ADDR32NB,
REL32,
REL32_1,
REL32_2,
REL32_3,
REL32_4,
REL32_5,
SECTION,
SECREL,
SECREL7,
TOKEN,
SREL32,
PAIR,
SSPAN32
}
public enum ARMRelocationType : ushort
{
ABSOLUTE,
ADDR32,
ADDR32NB,
BRANCH24,
BRANCH11,
TOKEN,
BLX24 = 0x08,
BLX11 = 0x09,
SECTION = 0x0E,
SECREL = 0x0F,
MOV32A = 0x10,
MOV32T = 0x11,
BRANCH20T = 0x12,
BRANCH24T = 0x14,
BLX23T = 0x15
}
public enum ARMv8RelocationType : ushort
{
ABSOLUTE,
ADDR32,
ADDR32NB,
BRANCH26,
PAGEBASE_REL21,
REL21,
PAGEOFFSET_12A,
PAGEOFFSET_12L,
SECREL,
SECREL_LOW12A,
SECREL_HIGH12A,
SECREL_LOW12L,
TOKEN,
SECTION,
ADDR64
}
public enum X86RelocationType : ushort
{
ABSOLUTE,
DIR16,
DIR32 = 0x06,
DIR32NB = 0x07,
SEG12 = 0x09,
SECTION = 0x0A,
SECREL = 0x0B,
TOKEN = 0x0C,
SECREL7 = 0x0D,
REL32 = 0x14
}
public class RelocationEntry
{
public uint VirtualAddress;
public uint SymbolTableIndex;
public Enum Type;
public string Name;
public RelocationEntry(BinaryReader br)
{
this.VirtualAddress = br.ReadUInt32();
this.SymbolTableIndex = br.ReadUInt32();
// Default to X86RelocationType. This will be changed once the processor type is determined
this.Type = (X86RelocationType)br.ReadUInt16();
}
}
public class SECTION_HEADER
{
public string Name;
public uint PhysicalAddress;
public uint VirtualSize;
public uint VirtualAddress;
public uint SizeOfRawData;
public uint PointerToRawData;
public uint PointerToRelocations;
public uint PointerToLinenumbers;
public ushort NumberOfRelocations;
public ushort NumberOfLinenumbers;
public SectionHeaderCharacteristics Characteristics;
public Byte[] RawData;
public RelocationEntry[] Relocations;
public SECTION_HEADER(BinaryReader br)
{
this.Name = Encoding.UTF8.GetString(br.ReadBytes(8)).Split((Char)0)[0];
this.PhysicalAddress = br.ReadUInt32();
this.VirtualSize = this.PhysicalAddress;
this.VirtualAddress = br.ReadUInt32();
this.SizeOfRawData = br.ReadUInt32();
this.PointerToRawData = br.ReadUInt32();
this.PointerToRelocations = br.ReadUInt32();
this.PointerToLinenumbers = br.ReadUInt32();
this.NumberOfRelocations = br.ReadUInt16();
this.NumberOfLinenumbers = br.ReadUInt16();
this.Characteristics = (SectionHeaderCharacteristics)br.ReadUInt32();
}
}
public enum SectionNumber : short
{
UNDEFINED,
ABSOLUTE = -1,
DEBUG = -2
}
[Flags]
public enum TypeClass : short
{
TYPE_NULL,
TYPE_VOID,
TYPE_CHAR,
TYPE_SHORT,
TYPE_INT,
TYPE_LONG,
TYPE_FLOAT,
TYPE_DOUBLE,
TYPE_STRUCT,
TYPE_UNION,
TYPE_ENUM,
TYPE_MOE,
TYPE_BYTE,
TYPE_WORD,
TYPE_UINT,
TYPE_DWORD,
DTYPE_POINTER = 0x100,
DTYPE_FUNCTION = 0x200,
DTYPE_ARRAY = 0x300,
/// <summary>
/// Technically, this is defined as 0 in the MSB
/// </summary>
DTYPE_NULL = 0x400
}
public enum StorageClass : byte
{
NULL,
AUTOMATIC,
EXTERNAL,
STATIC,
REGISTER,
EXTERNAL_DEF,
LABEL,
UNDEFINED_LABEL,
MEMBER_OF_STRUCT,
ARGUMENT,
STRUCT_TAG,
MEMBER_OF_UNION,
UNION_TAG,
TYPE_DEFINITION,
ENUM_TAG,
MEMBER_OF_ENUM,
REGISTER_PARAM,
BIT_FIELD,
BLOCK = 0x64,
FUNCTION = 0x65,
END_OF_STRUCT = 0x66,
FILE = 0x67,
SECTION = 0x68,
WEAK_EXTERNAL = 0x69,
CLR_TOKEN = 0x6B,
END_OF_FUNCTION = 0xFF
}
public class SYMBOL_TABLE
{
public string Name;
public uint Value;
public SectionNumber SectionNumber;
public TypeClass Type;
public StorageClass StorageClass;
public byte NumberOfAuxSymbols;
public Object AuxSymbols;
private readonly Byte[] NameArray;
public SYMBOL_TABLE(BinaryReader br)
{
this.NameArray = br.ReadBytes(8);
if (this.NameArray[0] == 0 && this.NameArray[1] == 0 && this.NameArray[2] == 0 && this.NameArray[3] == 0)
{
// Per specification, if the high DWORD is 0, then then low DWORD is an index into the string table
this.Name = "/" + BitConverter.ToInt32(NameArray, 4).ToString();
}
else
{
this.Name = Encoding.UTF8.GetString(NameArray).Trim((char)0);
}
this.Value = br.ReadUInt32();
this.SectionNumber = (SectionNumber)br.ReadInt16();
this.Type = (TypeClass)br.ReadInt16();
if ((((int)this.Type) & 0xff00) == 0) { this.Type = (TypeClass)Enum.Parse(typeof(TypeClass), ((int)this.Type | 0x400).ToString()); }
this.StorageClass = (StorageClass)br.ReadByte();
this.NumberOfAuxSymbols = br.ReadByte();
}
}
public class SECTION_DEFINITION
{
public uint Length;
public ushort NumberOfRelocations;
public ushort NumberOfLinenumbers;
public uint CheckSum;
public ushort Number;
public byte Selection;
public SECTION_DEFINITION(BinaryReader br)
{
this.Length = br.ReadUInt32();
this.NumberOfRelocations = br.ReadUInt16();
this.NumberOfLinenumbers = br.ReadUInt16();
this.CheckSum = br.ReadUInt32();
this.Number = br.ReadUInt16();
this.Selection = br.ReadByte();
br.ReadBytes(3);
}
}
public class ParsedObjectFile
{
public HEADER CoffHeader;
public SECTION_HEADER[] SectionHeaders;
public SYMBOL_TABLE[] SymbolTable;
}
public static class ObjectFileParser
{
public static ParsedObjectFile ParseObjectFile(string ObjectFilePath)
{
ParsedObjectFile Result = null;
// Fixed structure sizes
const int SizeofCOFFFileHeader = 20;
const int SizeofSectionHeader = 40;
const int SizeofSymbolTableEntry = 18;
const int SizeofRelocationEntry = 10;
// Open the object file for reading
using (FileStream FileStream = System.IO.File.OpenRead(ObjectFilePath))
{
long FileLength = FileStream.Length;
if (FileLength < SizeofCOFFFileHeader)
{
// You cannot parse the COFF header if the file is not big enough to contain a COFF header.
throw new Exception("ObjectFile is too small to store a COFF header.");
}
// Open a BinaryReader object for the object file
using BinaryReader BinaryReader = new(FileStream);
// Parse the COFF header
COFF.HEADER CoffHeader = new(BinaryReader);
if (CoffHeader.SizeOfOptionalHeader != 0)
{
// Per the PECOFF specification, an object file does not have an optional header
throw new Exception("Coff header indicates the existence of an optional header. An object file cannot have an optional header.");
}
if (CoffHeader.PointerToSymbolTable == 0)
{
throw new Exception("An object file is supposed to have a symbol table.");
}
if (FileLength < ((CoffHeader.NumberOfSections * SizeofSectionHeader) + SizeofCOFFFileHeader))
{
// The object file isn't big enough to store the number of sections present.
throw new Exception("ObjectFile is too small to store section header data.");
}
// A string collection used to store section header names. This collection is referenced while
// parsing the symbol table entries whose name is the same as the section header. In this case,
// the symbol entry will have a particular auxiliary symbol table entry.
System.Collections.Specialized.StringCollection SectionHeaderNames = new();
// Correlate the processor type to the relocation type. There are more relocation type defined
// in the PECOFF specification, but I don't expect those to be present. In that case, relocation
// entries default to X86RelocationType.
COFF.SECTION_HEADER[] SectionHeaders = new COFF.SECTION_HEADER[CoffHeader.NumberOfSections];
// Parse section headers
for (int i = 0; i < CoffHeader.NumberOfSections; i++)
{
SectionHeaders[i] = new COFF.SECTION_HEADER(BinaryReader);
// Add the section name to the string collection. This will be referenced during symbol table parsing.
SectionHeaderNames.Add(SectionHeaders[i].Name);
// Save the current filestream position. We are about to jump out of place.
long SavedFilePosition = FileStream.Position;
// Check to see if the raw data points beyond the actual file size
if ((SectionHeaders[i].PointerToRawData + SectionHeaders[i].SizeOfRawData) > FileLength)
{
throw new Exception("Section header's raw data exceeds the size of the object file.");
}
else
{
// Read the raw data into a byte array
FileStream.Seek(SectionHeaders[i].PointerToRawData, SeekOrigin.Begin);
SectionHeaders[i].RawData = BinaryReader.ReadBytes((int)SectionHeaders[i].SizeOfRawData);
}
// Check to see if the section has a relocation table
if ((SectionHeaders[i].PointerToRelocations != 0) && (SectionHeaders[i].NumberOfRelocations != 0))
{
// Check to see if the relocation entries point beyond the actual file size
if ((SectionHeaders[i].PointerToRelocations + (SizeofRelocationEntry * SectionHeaders[i].NumberOfRelocations)) > FileLength)
{
throw new Exception("(SectionHeaders[i].Name) section header's relocation entries exceeds the soze of the object file.");
}
FileStream.Seek(SectionHeaders[i].PointerToRelocations, SeekOrigin.Begin);
COFF.RelocationEntry[] Relocations = new COFF.RelocationEntry[SectionHeaders[i].NumberOfRelocations];
for (int j = 0; j < SectionHeaders[i].NumberOfRelocations; j++)
{
Relocations[j] = new COFF.RelocationEntry(BinaryReader);
// Cast the relocation as its respective type
switch (CoffHeader.Machine)
{
case Machine.I386:
Relocations[j].Type = (COFF.X86RelocationType)Relocations[j].Type;
break;
case Machine.AMD64:
Relocations[j].Type = (COFF.AMD64RelocationType)Relocations[j].Type;
break;
case Machine.ARMV7:
Relocations[j].Type = (COFF.ARMRelocationType)Relocations[j].Type;
break;
case Machine.ARM64:
Relocations[j].Type = (COFF.ARMv8RelocationType)Relocations[j].Type;
break;
}
}
// Add the relocation table entry to the section header
SectionHeaders[i].Relocations = Relocations;
}
// Restore the original filestream pointer
FileStream.Seek(SavedFilePosition, SeekOrigin.Begin);
}
// Retrieve the contents of the COFF string table
long SymTableSize = CoffHeader.NumberOfSymbols * SizeofSymbolTableEntry;
long StringTableOffset = CoffHeader.PointerToSymbolTable + SymTableSize;
if (StringTableOffset > FileLength)
{
throw new Exception("The string table points beyond the end of the file.");
}
FileStream.Seek(StringTableOffset, SeekOrigin.Begin);
UInt32 StringTableLength = BinaryReader.ReadUInt32();
if (StringTableLength > FileLength)
{
throw new Exception("The string table's length exceeds the length of the file.");
}
string StringTable = System.Text.Encoding.UTF8.GetString(BinaryReader.ReadBytes((int)StringTableLength));
COFF.SYMBOL_TABLE[] RawSymbolTable = new COFF.SYMBOL_TABLE[CoffHeader.NumberOfSymbols];
// Retrieve the symbol table
if (FileLength < StringTableOffset)
{
throw new Exception("Symbol table is larger than the file size.");
}
FileStream.Seek(CoffHeader.PointerToSymbolTable, SeekOrigin.Begin);
int NumberofRegularSymbols = 0;
/*
Go through each symbol table looking for auxiliary symbols to parse
Currently supported auxiliary symbol table entry formats:
1) .file
2) Entry names that match the name of a section header
*/
for (int i = 0; i < CoffHeader.NumberOfSymbols; i++)
{
// Parse the symbol tables regardless of whether they are normal or auxiliary symbols
RawSymbolTable[i] = new COFF.SYMBOL_TABLE(BinaryReader);
if (RawSymbolTable[i].NumberOfAuxSymbols == 0)
{
// This symbol table entry has no auxiliary symbols
NumberofRegularSymbols++;
}
else if (RawSymbolTable[i].Name == ".file")
{
long TempPosition = FileStream.Position; // Save filestream position
// Retrieve the file name
RawSymbolTable[i].AuxSymbols = System.Text.Encoding.UTF8.GetString(BinaryReader.ReadBytes(RawSymbolTable[i].NumberOfAuxSymbols * SizeofSymbolTableEntry)).TrimEnd((Char)0);
FileStream.Seek(TempPosition, SeekOrigin.Begin); // Restore filestream position
}
else if (SectionHeaderNames.Contains(RawSymbolTable[i].Name))
{
long TempPosition = FileStream.Position; // Save filestream position
RawSymbolTable[i].AuxSymbols = new COFF.SECTION_DEFINITION(BinaryReader);
FileStream.Seek(TempPosition, SeekOrigin.Begin); // Restore filestream position
}
}
// Create an array of symbol table entries without auxiliary table entries
COFF.SYMBOL_TABLE[] SymbolTable = new COFF.SYMBOL_TABLE[NumberofRegularSymbols];
int k = 0;
for (int i = 0; i < CoffHeader.NumberOfSymbols; i++)
{
SymbolTable[k] = RawSymbolTable[i]; // FYI, the first symbol table entry will never be an aux symbol
k++;
// Skip over the auxiliary symbols
if (RawSymbolTable[i].NumberOfAuxSymbols != 0)
{
i += RawSymbolTable[i].NumberOfAuxSymbols;
}
}
// Fix the section names if any of them point to the COFF string table
for (int i = 0; i < CoffHeader.NumberOfSections; i++)
{
if (SectionHeaders[i].Name?.IndexOf('/') == 0)
{
string StringTableIndexString = SectionHeaders[i].Name[1..];
if (int.TryParse(StringTableIndexString, out int StringTableIndex))
{
StringTableIndex -= 4;
if (StringTableIndex > (StringTableLength + 4))
{
throw new Exception("String table entry exceeds the bounds of the object file.");
}
int Length = StringTable.IndexOf((Char)0, StringTableIndex);
SectionHeaders[i].Name = StringTable.Substring(StringTableIndex, Length);
}
}
}
// Fix the symbol table names
for (int i = 0; i < SymbolTable.Length; i++)
{
if (SymbolTable[i].Name?.IndexOf('/') == 0)
{
string StringTableIndexString = SymbolTable[i].Name[1..];
if (int.TryParse(StringTableIndexString, out int StringTableIndex))
{
StringTableIndex -= 4;
int Length = StringTable.IndexOf((Char)0, StringTableIndex) - StringTableIndex;
SymbolTable[i].Name = StringTable.Substring(StringTableIndex, Length);
}
}
}
// Apply symbol names to the relocation entries
// SectionHeaders | Where-Object { _.Relocations } | % {
// _.Relocations | % { _.Name = RawSymbolTable[_.SymbolTableIndex].Name }
// }
SectionHeaders.Where(h => h.Relocations != null).ToList().ForEach(h => h.Relocations.ToList().ForEach(r => r.Name = RawSymbolTable[r.SymbolTableIndex].Name));
Result = new ParsedObjectFile
{
CoffHeader = CoffHeader,
SectionHeaders = SectionHeaders,
SymbolTable = SymbolTable
};
}
return Result;
}
}
}
+261
View File
@@ -0,0 +1,261 @@
// Copyright (c) 2018, Rene Lergner - wpinternals.net - @Heathcliff74xda
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
using System.Collections.Generic;
using System.IO;
using System.Xml;
using System.Xml.Serialization;
namespace WPinternals
{
internal class PatchEngine
{
internal List<PatchDefinition> PatchDefinitions = new();
internal readonly List<TargetRedirection> TargetRedirections = new();
internal PatchEngine() { }
internal PatchEngine(string PatchDefinitionsXmlString)
{
XmlSerializer x = new(PatchDefinitions.GetType(), null, Array.Empty<Type>(), new XmlRootAttribute("PatchDefinitions"), "");
MemoryStream s = new(System.Text.Encoding.ASCII.GetBytes(PatchDefinitionsXmlString));
PatchDefinitions = (List<PatchDefinition>)x.Deserialize(s);
}
internal void WriteDefinitions(string FilePath)
{
XmlSerializer x = new(PatchDefinitions.GetType(), null, Array.Empty<Type>(), new XmlRootAttribute("PatchDefinitions"), "");
XmlSerializerNamespaces ns = new();
ns.Add("", "");
System.IO.StreamWriter FileWriter = new(FilePath);
XmlWriter XmlWriter = XmlWriter.Create(FileWriter, new XmlWriterSettings() { OmitXmlDeclaration = true, Indent = true, NewLineHandling = NewLineHandling.Entitize });
FileWriter.WriteLine("<?xml version=\"1.0\" encoding=\"utf-8\"?>");
FileWriter.WriteLine("");
FileWriter.WriteLine("<!--");
FileWriter.WriteLine("Copyright(c) 2018, Rene Lergner - wpinternals.net - @Heathcliff74xda");
FileWriter.WriteLine("");
FileWriter.WriteLine("Permission is hereby granted, free of charge, to any person obtaining a");
FileWriter.WriteLine("copy of this software and associated documentation files(the \"Software\"),");
FileWriter.WriteLine("to deal in the Software without restriction, including without limitation");
FileWriter.WriteLine("the rights to use, copy, modify, merge, publish, distribute, sublicense,");
FileWriter.WriteLine("and / or sell copies of the Software, and to permit persons to whom the");
FileWriter.WriteLine("Software is furnished to do so, subject to the following conditions:");
FileWriter.WriteLine("");
FileWriter.WriteLine("The above copyright notice and this permission notice shall be included in");
FileWriter.WriteLine("all copies or substantial portions of the Software.");
FileWriter.WriteLine("");
FileWriter.WriteLine("THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR");
FileWriter.WriteLine("IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,");
FileWriter.WriteLine("FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE");
FileWriter.WriteLine("AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER");
FileWriter.WriteLine("LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING");
FileWriter.WriteLine("FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER");
FileWriter.WriteLine("DEALINGS IN THE SOFTWARE.");
FileWriter.WriteLine("-->");
FileWriter.WriteLine("");
x.Serialize(XmlWriter, PatchDefinitions, ns);
FileWriter.Close();
}
private string _TargetPath = null;
internal string TargetPath
{
get
{
return _TargetPath;
}
set
{
_TargetPath = value.TrimEnd(new char[] { '\\' });
}
}
}
internal class TargetRedirection
{
private string _RelativePath;
private string _TargetPath;
internal TargetRedirection(string RelativePath, string TargetPath)
{
this.RelativePath = RelativePath;
this.TargetPath = TargetPath;
}
internal string RelativePath
{
get
{
return _RelativePath;
}
set
{
_RelativePath = value.TrimStart(new char[] { '\\' }).TrimEnd(new char[] { '\\' });
}
}
internal string TargetPath
{
get
{
return _TargetPath;
}
set
{
_TargetPath = value.TrimEnd(new char[] { '\\' });
}
}
}
/// <summary>
/// Must be public to be serializable
/// </summary>
public class PatchDefinition
{
[XmlAttribute]
public string Name;
public List<TargetVersion> TargetVersions = new();
}
/// <summary>
/// Must be public to be serializable
/// </summary>
public class TargetVersion
{
[XmlAttribute]
public string Description;
public List<TargetFile> TargetFiles = new();
}
/// <summary>
/// Must be public to be serializable
/// </summary>
public class TargetFile
{
private string _Path;
[XmlAttribute]
public string Path
{
get
{
return _Path;
}
set
{
_Path = value.TrimStart(new char[] { '\\' });
}
}
[XmlIgnore]
public byte[] HashOriginal;
[XmlAttribute("HashOriginal")]
public string HashOriginalAsString
{
get
{
return Converter.ConvertHexToString(HashOriginal, "");
}
set
{
HashOriginal = Converter.ConvertStringToHex(value);
}
}
[XmlIgnore]
public byte[] HashPatched;
[XmlAttribute("HashPatched")]
public string HashPatchedAsString
{
get
{
return Converter.ConvertHexToString(HashPatched, "");
}
set
{
HashPatched = Converter.ConvertStringToHex(value);
}
}
public List<Patch> Patches = new();
public List<TargetFile> Obsolete = new();
}
/// <summary>
/// Must be public to be serializable
/// </summary>
public class Patch
{
[XmlIgnore]
public UInt32 Address;
[XmlAttribute("Address")]
public string AddressAsString
{
get
{
return "0x" + Address.ToString("X8");
}
set
{
string NewValue = value;
if (NewValue.StartsWith("0x", StringComparison.OrdinalIgnoreCase))
NewValue = NewValue[2..];
Address = Convert.ToUInt32(NewValue, 16);
}
}
[XmlIgnore]
public byte[] OriginalBytes;
[XmlAttribute("OriginalBytes")]
public string OriginalBytesAsString
{
get
{
return Converter.ConvertHexToString(OriginalBytes, "");
}
set
{
OriginalBytes = Converter.ConvertStringToHex(value);
}
}
[XmlIgnore]
public byte[] PatchedBytes;
[XmlAttribute("PatchedBytes")]
public string PatchedBytesAsString
{
get
{
return Converter.ConvertHexToString(PatchedBytes, "");
}
set
{
PatchedBytes = Converter.ConvertStringToHex(value);
}
}
}
}
+28
View File
@@ -0,0 +1,28 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net5.0-windows</TargetFramework>
<OutputType>WinExe</OutputType>
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
<UseWindowsForms>true</UseWindowsForms>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x86'">
<OutputPath>bin\x86\Debug\</OutputPath>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x86'">
<OutputPath>bin\x86\Release\</OutputPath>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
<OutputPath>bin\x64\Debug\</OutputPath>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
<OutputPath>bin\x64\Release\</OutputPath>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.CSharp" Version="4.7.0" />
<PackageReference Include="System.Data.DataSetExtensions" Version="4.5.0" />
</ItemGroup>
</Project>
+9
View File
@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup />
<ItemGroup>
<Compile Update="MainForm.cs">
<SubType>Form</SubType>
</Compile>
</ItemGroup>
</Project>
+818
View File
@@ -0,0 +1,818 @@
// Copyright (c) 2018, Rene Lergner - wpinternals.net - @Heathcliff74xda
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
// Explanation of PE header here:
// https://msdn.microsoft.com/en-us/library/ms809762.aspx
using System;
using System.Collections.Generic;
using System.IO;
using System.Runtime.InteropServices;
using System.Linq;
using WPinternals;
namespace Patcher
{
#region Structs
[StructLayout(LayoutKind.Sequential)]
public struct IMAGE_DOS_HEADER
{
public UInt16 e_magic;
public UInt16 e_cblp;
public UInt16 e_cp;
public UInt16 e_crlc;
public UInt16 e_cparhdr;
public UInt16 e_minalloc;
public UInt16 e_maxalloc;
public UInt16 e_ss;
public UInt16 e_sp;
public UInt16 e_csum;
public UInt16 e_ip;
public UInt16 e_cs;
public UInt16 e_lfarlc;
public UInt16 e_ovno;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
public UInt16[] e_res1;
public UInt16 e_oemid;
public UInt16 e_oeminfo;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 10)]
public UInt16[] e_res2;
public UInt32 e_lfanew;
}
[StructLayout(LayoutKind.Sequential)]
public struct IMAGE_NT_HEADERS
{
public UInt32 Signature;
public IMAGE_FILE_HEADER FileHeader;
public IMAGE_OPTIONAL_HEADER32 OptionalHeader32;
public IMAGE_OPTIONAL_HEADER64 OptionalHeader64;
}
[StructLayout(LayoutKind.Sequential)]
public struct IMAGE_FILE_HEADER
{
public UInt16 Machine;
public UInt16 NumberOfSections;
public UInt32 TimeDateStamp;
public UInt32 PointerToSymbolTable;
public UInt32 NumberOfSymbols;
public UInt16 SizeOfOptionalHeader;
public UInt16 Characteristics;
}
[StructLayout(LayoutKind.Sequential)]
public struct IMAGE_OPTIONAL_HEADER32
{
public UInt16 Magic;
public Byte MajorLinkerVersion;
public Byte MinorLinkerVersion;
public UInt32 SizeOfCode;
public UInt32 SizeOfInitializedData;
public UInt32 SizeOfUninitializedData;
public UInt32 AddressOfEntryPoint;
public UInt32 BaseOfCode;
public UInt32 BaseOfData;
public UInt32 ImageBase;
public UInt32 SectionAlignment;
public UInt32 FileAlignment;
public UInt16 MajorOperatingSystemVersion;
public UInt16 MinorOperatingSystemVersion;
public UInt16 MajorImageVersion;
public UInt16 MinorImageVersion;
public UInt16 MajorSubsystemVersion;
public UInt16 MinorSubsystemVersion;
public UInt32 Win32VersionValue;
public UInt32 SizeOfImage;
public UInt32 SizeOfHeaders;
public UInt32 CheckSum;
public UInt16 Subsystem;
public UInt16 DllCharacteristics;
public UInt32 SizeOfStackReserve;
public UInt32 SizeOfStackCommit;
public UInt32 SizeOfHeapReserve;
public UInt32 SizeOfHeapCommit;
public UInt32 LoaderFlags;
public UInt32 NumberOfRvaAndSizes;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)]
public IMAGE_DATA_DIRECTORY[] DataDirectory;
}
[StructLayout(LayoutKind.Sequential)]
public struct IMAGE_OPTIONAL_HEADER64
{
public UInt16 Magic;
public Byte MajorLinkerVersion;
public Byte MinorLinkerVersion;
public UInt32 SizeOfCode;
public UInt32 SizeOfInitializedData;
public UInt32 SizeOfUninitializedData;
public UInt32 AddressOfEntryPoint;
public UInt32 BaseOfCode;
public UInt64 ImageBase;
public UInt32 SectionAlignment;
public UInt32 FileAlignment;
public UInt16 MajorOperatingSystemVersion;
public UInt16 MinorOperatingSystemVersion;
public UInt16 MajorImageVersion;
public UInt16 MinorImageVersion;
public UInt16 MajorSubsystemVersion;
public UInt16 MinorSubsystemVersion;
public UInt32 Win32VersionValue;
public UInt32 SizeOfImage;
public UInt32 SizeOfHeaders;
public UInt32 CheckSum;
public UInt16 Subsystem;
public UInt16 DllCharacteristics;
public UInt64 SizeOfStackReserve;
public UInt64 SizeOfStackCommit;
public UInt64 SizeOfHeapReserve;
public UInt64 SizeOfHeapCommit;
public UInt32 LoaderFlags;
public UInt32 NumberOfRvaAndSizes;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)]
public IMAGE_DATA_DIRECTORY[] DataDirectory;
}
[StructLayout(LayoutKind.Sequential)]
public struct IMAGE_DATA_DIRECTORY
{
public UInt32 VirtualAddress;
public UInt32 Size;
}
[StructLayout(LayoutKind.Sequential)]
public struct IMAGE_SECTION_HEADER
{
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 8)]
public string Name;
public Misc Misc;
public UInt32 VirtualAddress;
public UInt32 SizeOfRawData;
public UInt32 PointerToRawData;
public UInt32 PointerToRelocations;
public UInt32 PointerToLinenumbers;
public UInt16 NumberOfRelocations;
public UInt16 NumberOfLinenumbers;
public UInt32 Characteristics;
}
[StructLayout(LayoutKind.Explicit)]
public struct Misc
{
[FieldOffset(0)]
public UInt32 PhysicalAddress;
[FieldOffset(0)]
public UInt32 VirtualSize;
}
[StructLayout(LayoutKind.Sequential)]
public struct IMAGE_EXPORT_DIRECTORY
{
public UInt32 Characteristics;
public UInt32 TimeDateStamp;
public UInt16 MajorVersion;
public UInt16 MinorVersion;
public UInt32 Name;
public UInt32 Base;
public UInt32 NumberOfFunctions;
public UInt32 NumberOfNames;
/// <summary>
/// RVA from base of image
/// </summary>
public UInt32 AddressOfFunctions;
/// <summary>
/// RVA from base of image
/// </summary>
public UInt32 AddressOfNames;
/// <summary>
/// RVA from base of image
/// </summary>
public UInt32 AddressOfNameOrdinals;
}
[StructLayout(LayoutKind.Explicit)]
public struct IMAGE_IMPORT_DESCRIPTOR
{
#region union
/// <summary>
/// CSharp doesnt really support unions, but they can be emulated by a field offset 0
/// </summary>
[FieldOffset(0)]
public uint Characteristics; // 0 for terminating null import descriptor
/// <summary>
/// RVA to original unbound IAT (PIMAGE_THUNK_DATA)
/// </summary>
[FieldOffset(0)]
public uint OriginalFirstThunk;
#endregion
[FieldOffset(4)]
public uint TimeDateStamp;
[FieldOffset(8)]
public uint ForwarderChain;
[FieldOffset(12)]
public uint Name;
[FieldOffset(16)]
public uint FirstThunk;
}
public struct RUNTIME_FUNCTION_64
{
public UInt64 RVAofBeginAddress;
public UInt64 RVAofEndAddress;
public UInt64 RVAofUnwindData;
}
public struct RUNTIME_FUNCTION_32
{
public UInt32 RVAofBeginAddress;
public UInt32 RVAofUnwindData;
}
public static class Constants
{
public static class SectionFlags
{
public const UInt32 IMAGE_SCN_CNT_CODE = 0x00000020;
}
}
internal enum ResourceType
{
/// <summary>
/// Accelerator table.
/// </summary>
RT_ACCELERATOR = 9,
/// <summary>
/// Animated cursor.
/// </summary>
RT_ANICURSOR = 21,
/// <summary>
/// Animated icon.
/// </summary>
RT_ANIICON = 22,
/// <summary>
/// Bitmap resource.
/// </summary>
RT_BITMAP = 2,
/// <summary>
/// Hardware-dependent cursor resource.
/// </summary>
RT_CURSOR = 1,
/// <summary>
/// Dialog box.
/// </summary>
RT_DIALOG = 5,
/// <summary>
/// Allows
/// </summary>
RT_DLGINCLUDE = 17,
/// <summary>
/// Font resource.
/// </summary>
RT_FONT = 8,
/// <summary>
/// Font directory resource.
/// </summary>
RT_FONTDIR = 7,
/// <summary>
/// Hardware-independent cursor resource.
/// </summary>
RT_GROUP_CURSOR = RT_CURSOR + 11,
/// <summary>
/// Hardware-independent icon resource.
/// </summary>
RT_GROUP_ICON = RT_ICON + 11,
/// <summary>
/// HTML resource.
/// </summary>
RT_HTML = 23,
/// <summary>
/// Hardware-dependent icon resource.
/// </summary>
RT_ICON = 3,
/// <summary>
/// Side-by-Side Assembly Manifest.
/// </summary>
RT_MANIFEST = 24,
/// <summary>
/// Menu resource.
/// </summary>
RT_MENU = 4,
/// <summary>
/// Message-table entry.
/// </summary>
RT_MESSAGETABLE = 11,
/// <summary>
/// Plug and Play resource.
/// </summary>
RT_PLUGPLAY = 19,
/// <summary>
/// Application-defined resource (raw data).
/// </summary>
RT_RCDATA = 10,
/// <summary>
/// String-table entry.
/// </summary>
RT_STRING = 6,
/// <summary>
/// Version resource.
/// </summary>
RT_VERSION = 16,
/// <summary>
/// VXD
/// </summary>
RT_VXD = 20,
RT_DLGINIT = 240,
RT_TOOLBAR = 241
};
#endregion
public class PeFile
{
#region Fields
public readonly IMAGE_DOS_HEADER DosHeader;
public IMAGE_NT_HEADERS NtHeaders;
private readonly IList<IMAGE_SECTION_HEADER> _sectionHeaders = new List<IMAGE_SECTION_HEADER>();
public List<Section> Sections = new();
public List<FunctionDescriptor> Exports = new();
public List<FunctionDescriptor> Imports = new();
public List<FunctionDescriptor> RuntimeFunctions = new();
public byte[] Buffer;
public UInt64 ImageBase;
public UInt64 EntryPoint;
public UInt64 ExportDirectoryVirtualOffset;
public UInt64 ImportDirectoryVirtualOffset;
public UInt64 RuntimeDirectoryVirtualOffset;
public UInt32 RuntimeDirectorySize;
#endregion
public PeFile(string Path): this(File.ReadAllBytes(Path))
{
}
public PeFile(byte[] Buffer)
{
int P = 0;
this.Buffer = Buffer;
// Read MS-DOS header section
DosHeader = MarshalBytesTo<IMAGE_DOS_HEADER>(Buffer, P);
// MS-DOS magic number should read 'MZ'
if (DosHeader.e_magic != 0x5a4d)
{
throw new InvalidOperationException("File is not a portable executable.");
}
// Read NT Headers
P = (int)DosHeader.e_lfanew;
NtHeaders.Signature = MarshalBytesTo<UInt32>(Buffer, P);
// Make sure we have 'PE' in the pe signature
if (NtHeaders.Signature != 0x4550)
{
throw new InvalidOperationException("Invalid portable executable signature in NT header.");
}
P += sizeof(UInt32);
NtHeaders.FileHeader = MarshalBytesTo<IMAGE_FILE_HEADER>(Buffer, P);
// Read optional headers
P += Marshal.SizeOf(typeof(IMAGE_FILE_HEADER));
if (Is32bitAssembly())
{
Load32bitOptionalHeaders(Buffer, P);
ImageBase = NtHeaders.OptionalHeader32.ImageBase;
EntryPoint = NtHeaders.OptionalHeader32.AddressOfEntryPoint;
ExportDirectoryVirtualOffset = NtHeaders.OptionalHeader32.DataDirectory[0].VirtualAddress;
ImportDirectoryVirtualOffset = NtHeaders.OptionalHeader32.DataDirectory[1].VirtualAddress;
RuntimeDirectoryVirtualOffset = NtHeaders.OptionalHeader32.DataDirectory[3].VirtualAddress;
RuntimeDirectorySize = NtHeaders.OptionalHeader32.DataDirectory[3].Size;
}
else
{
Load64bitOptionalHeaders(Buffer, P);
ImageBase = NtHeaders.OptionalHeader64.ImageBase;
EntryPoint = NtHeaders.OptionalHeader64.AddressOfEntryPoint;
ExportDirectoryVirtualOffset = NtHeaders.OptionalHeader64.DataDirectory[0].VirtualAddress;
ImportDirectoryVirtualOffset = NtHeaders.OptionalHeader64.DataDirectory[1].VirtualAddress;
RuntimeDirectoryVirtualOffset = NtHeaders.OptionalHeader64.DataDirectory[3].VirtualAddress;
RuntimeDirectorySize = NtHeaders.OptionalHeader64.DataDirectory[3].Size;
}
// Read Sections
_sectionHeaders.ToList().ForEach(s =>
{
byte[] RawCode = new byte[s.SizeOfRawData];
System.Buffer.BlockCopy(Buffer, (int)s.PointerToRawData, RawCode, 0, (int)s.SizeOfRawData);
Sections.Add(new Section { Header = s, Buffer = RawCode, VirtualAddress = s.VirtualAddress + (UInt32)ImageBase, VirtualSize = s.Misc.VirtualSize, IsCode = (s.Characteristics & (uint)Constants.SectionFlags.IMAGE_SCN_CNT_CODE) != 0 });
});
// Read Exports
// TODO: Proper support for 64-bit files
if (ExportDirectoryVirtualOffset != 0)
{
IMAGE_EXPORT_DIRECTORY ExportDirectory = MarshalBytesTo<IMAGE_EXPORT_DIRECTORY>(Buffer, (int)ConvertVirtualOffsetToRawOffset((uint)ExportDirectoryVirtualOffset));
if (ExportDirectory.AddressOfNames != 0)
{
Section ExportsSection = GetSectionForVirtualAddress((uint)(ImageBase + ExportDirectory.AddressOfNames));
UInt32 OffsetNames = (UInt32)(ImageBase + ExportDirectory.AddressOfNames - ExportsSection.VirtualAddress);
UInt32 OffsetOrdinals = (UInt32)(ImageBase + ExportDirectory.AddressOfNameOrdinals - ExportsSection.VirtualAddress);
UInt32 OffsetFunctions = (UInt32)(ImageBase + ExportDirectory.AddressOfFunctions - ExportsSection.VirtualAddress);
string[] ExportNames = new string[ExportDirectory.NumberOfNames];
UInt16[] Ordinals = new UInt16[ExportDirectory.NumberOfNames];
UInt32[] VirtualAddresses = new UInt32[ExportDirectory.NumberOfFunctions];
for (int i = 0; i < ExportDirectory.NumberOfNames; i++)
{
UInt32 NamesRVA = ByteOperations.ReadUInt32(ExportsSection.Buffer, (UInt32)(OffsetNames + (i * sizeof(UInt32))));
UInt32 NameOffset = (UInt32)(NamesRVA + ImageBase - ExportsSection.VirtualAddress);
ExportNames[i] = ByteOperations.ReadAsciiString(ExportsSection.Buffer, NameOffset);
Ordinals[i] = ByteOperations.ReadUInt16(ExportsSection.Buffer, (UInt32)(OffsetOrdinals + (i * sizeof(UInt16))));
}
for (int i = 0; i < ExportDirectory.NumberOfFunctions; i++)
{
VirtualAddresses[i] = ByteOperations.ReadUInt32(ExportsSection.Buffer, (UInt32)(OffsetFunctions + (i * sizeof(UInt32))));
VirtualAddresses[i] -= VirtualAddresses[i] % 2; // Round down for Thumb2
}
for (int i = 0; i < ExportDirectory.NumberOfNames; i++)
{
Exports.Add(new FunctionDescriptor() { Name = ExportNames[i], VirtualAddress = (UInt32)(ImageBase + VirtualAddresses[Ordinals[i]]) });
}
}
}
// Read Imports
// TODO: Proper support for 64-bit files
if (ImportDirectoryVirtualOffset != 0)
{
Section ImportsSection = GetSectionForVirtualAddress((uint)(ImageBase + ImportDirectoryVirtualOffset));
IMAGE_IMPORT_DESCRIPTOR ImportDirectory;
do
{
ImportDirectory = MarshalBytesTo<IMAGE_IMPORT_DESCRIPTOR>(ImportsSection.Buffer, (int)(ImportDirectoryVirtualOffset - (ImportsSection.VirtualAddress - ImageBase)));
if (ImportDirectory.OriginalFirstThunk != 0)
{
// ImportDirectory.OriginalFirstThunk is the VirtualOffset to an array of VirtualOffsets. They point to a struct with a word-value, followed by a zero-terminated ascii-string, which is the name of the import.
// ImportDirectory.FirstThunk points to an array pointers which is the actual import table.
UInt32 NameArrayOffset = ImportDirectory.OriginalFirstThunk - (ImportsSection.VirtualAddress - (UInt32)ImageBase);
UInt32 NameOffset;
int i = 0;
do
{
NameOffset = ByteOperations.ReadUInt32(ImportsSection.Buffer, NameArrayOffset);
if ((NameOffset < (ImportsSection.VirtualAddress - ImageBase)) || (NameOffset >= (ImportsSection.VirtualAddress + ImportsSection.VirtualSize - ImageBase)))
NameOffset = 0; // ImportDirectory.OriginalFirstThunk seems to contain Characteristics, not an offset to an array.
NameArrayOffset += sizeof(UInt32);
if (NameOffset != 0)
{
string Name = ByteOperations.ReadAsciiString(ImportsSection.Buffer, NameOffset + 2 - (ImportsSection.VirtualAddress - (UInt32)ImageBase));
Imports.Add(new FunctionDescriptor() { Name = Name, VirtualAddress = ImportDirectory.FirstThunk + (UInt32)ImageBase + (UInt32)(i * sizeof(UInt32)) });
i++;
}
}
while (NameOffset != 0);
ImportDirectoryVirtualOffset += (UInt64)Marshal.SizeOf(typeof(IMAGE_IMPORT_DESCRIPTOR));
}
}
while (ImportDirectory.OriginalFirstThunk != 0);
}
// Read Runtime functions
// TODO: Proper support for 64-bit files
if (RuntimeDirectoryVirtualOffset != 0)
{
Section RuntimeSection = GetSectionForVirtualAddress((uint)(ImageBase + RuntimeDirectoryVirtualOffset));
RUNTIME_FUNCTION_32 RuntimeFunction;
for (int i = 0; i < (RuntimeDirectorySize / Marshal.SizeOf(typeof(RUNTIME_FUNCTION_32))); i++)
{
RuntimeFunction = MarshalBytesTo<RUNTIME_FUNCTION_32>(RuntimeSection.Buffer, (int)(RuntimeDirectoryVirtualOffset - (RuntimeSection.VirtualAddress - ImageBase)) + (i * Marshal.SizeOf(typeof(RUNTIME_FUNCTION_32))));
RuntimeFunctions.Add(new FunctionDescriptor() { Name = null, VirtualAddress = (UInt32)(RuntimeFunction.RVAofBeginAddress + ImageBase) });
}
}
}
public UInt32 GetChecksumOffset()
{
return ByteOperations.ReadUInt32(Buffer, 0x3C) + +0x58;
}
internal UInt32 CalculateChecksum()
{
UInt32 Checksum = 0;
UInt32 Hi;
// Clear file checksum
// ByteOperations.WriteUInt32(PEFile, GetChecksumOffset(), 0);
UInt32 ChecksumOffset = GetChecksumOffset();
for (UInt32 i = 0; i < ((UInt32)Buffer.Length & 0xfffffffe); i += 2)
{
if ((i < ChecksumOffset) || (i >= (ChecksumOffset + 4)))
Checksum += ByteOperations.ReadUInt16(Buffer, i);
Hi = Checksum >> 16;
if (Hi != 0)
{
Checksum = Hi + (Checksum & 0xFFFF);
}
}
if ((Buffer.Length % 2) != 0)
{
Checksum += (UInt32)ByteOperations.ReadUInt8(Buffer, (UInt32)Buffer.Length - 1);
Hi = Checksum >> 16;
if (Hi != 0)
{
Checksum = Hi + (Checksum & 0xFFFF);
}
}
Checksum += (UInt32)Buffer.Length;
// Write file checksum
// ByteOperations.WriteUInt32(Buffer, GetChecksumOffset(), Checksum);
return Checksum;
}
public IMAGE_DOS_HEADER GetDOSHeader()
{
return DosHeader;
}
public UInt32 GetPESignature()
{
return NtHeaders.Signature;
}
public IMAGE_FILE_HEADER GetFileHeader()
{
return NtHeaders.FileHeader;
}
public IMAGE_OPTIONAL_HEADER32 GetOptionalHeaders32()
{
return NtHeaders.OptionalHeader32;
}
public IMAGE_OPTIONAL_HEADER64 GetOptionalHeaders64()
{
return NtHeaders.OptionalHeader64;
}
public IList<IMAGE_SECTION_HEADER> GetSectionHeaders()
{
return _sectionHeaders;
}
public bool Is32bitAssembly()
{
return (NtHeaders.FileHeader.Characteristics & 0x0100) == 0x0100;
}
private void Load64bitOptionalHeaders(byte[] Buffer, int Offset)
{
NtHeaders.OptionalHeader64 = MarshalBytesTo<IMAGE_OPTIONAL_HEADER64>(Buffer, Offset);
// Should have 10 data directories
if (NtHeaders.OptionalHeader64.NumberOfRvaAndSizes != 0x10)
{
throw new InvalidOperationException("Invalid number of data directories in NT header");
}
Offset += Marshal.SizeOf(typeof(IMAGE_OPTIONAL_HEADER64));
for (int i = 0; i < NtHeaders.FileHeader.NumberOfSections; i++)
{
_sectionHeaders.Add(MarshalBytesTo<IMAGE_SECTION_HEADER>(Buffer, Offset));
Offset += Marshal.SizeOf(typeof(IMAGE_SECTION_HEADER));
}
}
private void Load32bitOptionalHeaders(byte[] Buffer, int Offset)
{
NtHeaders.OptionalHeader32 = MarshalBytesTo<IMAGE_OPTIONAL_HEADER32>(Buffer, Offset);
// Should have 10 data directories
if (NtHeaders.OptionalHeader32.NumberOfRvaAndSizes != 0x10)
{
throw new InvalidOperationException("Invalid number of data directories in NT header");
}
Offset += Marshal.SizeOf(typeof(IMAGE_OPTIONAL_HEADER32));
for (int i = 0; i < NtHeaders.FileHeader.NumberOfSections; i++)
{
_sectionHeaders.Add(MarshalBytesTo<IMAGE_SECTION_HEADER>(Buffer, Offset));
Offset += Marshal.SizeOf(typeof(IMAGE_SECTION_HEADER));
}
}
public UInt32 ConvertVirtualOffsetToRawOffset(UInt32 VirtualOffset)
{
// TODO: Add 64-bit support
if (VirtualOffset < (Sections.OrderBy(s => s.VirtualAddress).First().VirtualAddress - GetOptionalHeaders32().ImageBase))
return VirtualOffset;
IMAGE_SECTION_HEADER? SectionHeaderSelection = _sectionHeaders.FirstOrDefault(h => (h.VirtualAddress <= VirtualOffset) && ((h.VirtualAddress + h.SizeOfRawData) > VirtualOffset));
if (SectionHeaderSelection == null)
throw new ArgumentOutOfRangeException();
IMAGE_SECTION_HEADER SectionHeader = (IMAGE_SECTION_HEADER)SectionHeaderSelection;
if (string.IsNullOrEmpty(SectionHeader.Name) || (SectionHeader.SizeOfRawData == 0))
throw new ArgumentOutOfRangeException();
return SectionHeader.PointerToRawData + (VirtualOffset - SectionHeader.VirtualAddress);
}
public UInt32 ConvertVirtualAddressToRawOffset(UInt32 VirtualAddress)
{
return ConvertVirtualOffsetToRawOffset((UInt32)(VirtualAddress - ImageBase));
}
internal uint ConvertRawOffsetToVirtualAddress(uint RawOffset)
{
// TODO: Add 64-bit support
if (RawOffset < Sections.OrderBy(s => s.VirtualAddress).First().Header.PointerToRawData)
return RawOffset + GetOptionalHeaders32().ImageBase;
IMAGE_SECTION_HEADER? SectionHeaderSelection = _sectionHeaders.FirstOrDefault(h => (h.PointerToRawData <= RawOffset) && ((h.PointerToRawData + h.SizeOfRawData) > RawOffset));
if (SectionHeaderSelection == null)
throw new ArgumentOutOfRangeException();
IMAGE_SECTION_HEADER SectionHeader = (IMAGE_SECTION_HEADER)SectionHeaderSelection;
if (string.IsNullOrEmpty(SectionHeader.Name) || (SectionHeader.SizeOfRawData == 0))
throw new ArgumentOutOfRangeException();
return RawOffset - SectionHeader.PointerToRawData + SectionHeader.VirtualAddress + GetOptionalHeaders32().ImageBase;
}
public Section GetSectionForVirtualAddress(UInt32 VirtualAddress)
{
return Sections.Find(s => (VirtualAddress >= s.VirtualAddress) && (VirtualAddress < (s.VirtualAddress + s.VirtualSize)));
}
private static T MarshalBytesTo<T>(BinaryReader reader)
{
// Unmanaged data
byte[] bytes = reader.ReadBytes(Marshal.SizeOf(typeof(T)));
// Create a pointer to the unmanaged data pinned in memory to be accessed by unmanaged code
GCHandle handle = GCHandle.Alloc(bytes, GCHandleType.Pinned);
// Use our previously created pointer to unmanaged data and marshal to the specified type
T theStructure = (T)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(T));
// Deallocate pointer
handle.Free();
return theStructure;
}
private static T MarshalBytesTo<T>(byte[] Binary, int Offset)
{
// Unmanaged data
byte[] bytes = new byte[Marshal.SizeOf(typeof(T))];
System.Buffer.BlockCopy(Binary, Offset, bytes, 0, Marshal.SizeOf(typeof(T)));
// Create a pointer to the unmanaged data pinned in memory to be accessed by unmanaged code
GCHandle handle = GCHandle.Alloc(bytes, GCHandleType.Pinned);
// Use our previously created pointer to unmanaged data and marshal to the specified type
T theStructure = (T)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(T));
// Deallocate pointer
handle.Free();
return theStructure;
}
internal byte[] GetResource(int[] Index)
{
UInt32 PEPointer = ByteOperations.ReadUInt32(Buffer, 0x3C);
UInt16 OptionalHeaderSize = ByteOperations.ReadUInt16(Buffer, PEPointer + 0x14);
UInt32 SectionTablePointer = PEPointer + 0x18 + OptionalHeaderSize;
UInt16 SectionCount = ByteOperations.ReadUInt16(Buffer, PEPointer + 0x06);
UInt32? ResourceSectionEntryPointer = null;
for (int i = 0; i < SectionCount; i++)
{
string SectionName = ByteOperations.ReadAsciiString(Buffer, (UInt32)(SectionTablePointer + (i * 0x28)), 8);
int e = SectionName.IndexOf('\0');
if (e >= 0)
SectionName = SectionName.Substring(0, e);
if (SectionName == ".rsrc")
{
ResourceSectionEntryPointer = (UInt32)(SectionTablePointer + (i * 0x28));
break;
}
}
if (ResourceSectionEntryPointer == null)
throw new Exception("Resource-section not found");
UInt32 ResourceRawSize = ByteOperations.ReadUInt32(Buffer, (UInt32)ResourceSectionEntryPointer + 0x10);
UInt32 ResourceRawPointer = ByteOperations.ReadUInt32(Buffer, (UInt32)ResourceSectionEntryPointer + 0x14);
UInt32 ResourceVirtualPointer = ByteOperations.ReadUInt32(Buffer, (UInt32)ResourceSectionEntryPointer + 0x0C);
UInt32 p = ResourceRawPointer;
for (int i = 0; i < Index.Length; i++)
{
UInt16 ResourceNamedEntryCount = ByteOperations.ReadUInt16(Buffer, p + 0x0c);
UInt16 ResourceIdEntryCount = ByteOperations.ReadUInt16(Buffer, p + 0x0e);
for (int j = ResourceNamedEntryCount; j < ResourceNamedEntryCount + ResourceIdEntryCount; j++)
{
UInt32 ResourceID = ByteOperations.ReadUInt32(Buffer, (UInt32)(p + 0x10 + (j * 8)));
UInt32 NextPointer = ByteOperations.ReadUInt32(Buffer, (UInt32)(p + 0x10 + (j * 8) + 4));
if (ResourceID == (UInt32)Index[i])
{
// Check high bit
if ((NextPointer & 0x80000000) == 0 != (i == (Index.Length - 1)))
throw new Exception("Bad resource path");
p = ResourceRawPointer + (NextPointer & 0x7fffffff);
break;
}
}
}
UInt32 ResourceValuePointer = ByteOperations.ReadUInt32(Buffer, p) - ResourceVirtualPointer + ResourceRawPointer;
UInt32 ResourceValueSize = ByteOperations.ReadUInt32(Buffer, p + 4);
byte[] ResourceValue = new byte[ResourceValueSize];
Array.Copy(Buffer, ResourceValuePointer, ResourceValue, 0, ResourceValueSize);
return ResourceValue;
}
internal Version GetFileVersion()
{
byte[] version = GetResource(new int[] { (int)ResourceType.RT_VERSION, 1, 1033 });
// RT_VERSION format:
// https://msdn.microsoft.com/en-us/library/windows/desktop/ms647001(v=vs.85).aspx
// https://msdn.microsoft.com/en-us/library/windows/desktop/ms646997(v=vs.85).aspx
const UInt32 FixedFileInfoPointer = 0x28;
UInt16 Major = ByteOperations.ReadUInt16(version, FixedFileInfoPointer + 0x0A);
UInt16 Minor = ByteOperations.ReadUInt16(version, FixedFileInfoPointer + 0x08);
UInt16 Build = ByteOperations.ReadUInt16(version, FixedFileInfoPointer + 0x0E);
UInt16 Revision = ByteOperations.ReadUInt16(version, FixedFileInfoPointer + 0x0C);
return new Version(Major, Minor, Build, Revision);
}
internal Version GetProductVersion()
{
byte[] version = GetResource(new int[] { (int)ResourceType.RT_VERSION, 1, 1033 });
// RT_VERSION format:
// https://msdn.microsoft.com/en-us/library/windows/desktop/ms647001(v=vs.85).aspx
// https://msdn.microsoft.com/en-us/library/windows/desktop/ms646997(v=vs.85).aspx
const UInt32 FixedFileInfoPointer = 0x28;
UInt16 Major = ByteOperations.ReadUInt16(version, FixedFileInfoPointer + 0x12);
UInt16 Minor = ByteOperations.ReadUInt16(version, FixedFileInfoPointer + 0x10);
UInt16 Build = ByteOperations.ReadUInt16(version, FixedFileInfoPointer + 0x16);
UInt16 Revision = ByteOperations.ReadUInt16(version, FixedFileInfoPointer + 0x14);
return new Version(Major, Minor, Build, Revision);
}
}
public class Section
{
public IMAGE_SECTION_HEADER Header;
public byte[] Buffer;
public UInt32 VirtualAddress;
public UInt32 VirtualSize;
public bool IsCode;
}
public class FunctionDescriptor
{
public string Name;
public UInt32 VirtualAddress;
}
}
+39
View File
@@ -0,0 +1,39 @@
// Copyright (c) 2018, Rene Lergner - wpinternals.net - @Heathcliff74xda
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
using System.Windows.Forms;
namespace Patcher
{
internal static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
private static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new MainForm());
}
}
}
@@ -0,0 +1,35 @@
using System.Reflection;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("ARM Patcher")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("WPinternals.net")]
[assembly: AssemblyProduct("ARM Patcher")]
[assembly: AssemblyCopyright("Copyright © 2018 by Rene Lergner")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("b9aebca3-bcf8-4e4a-bf0e-5e764867be07")]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]
+71
View File
@@ -0,0 +1,71 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:4.0.30319.42000
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace Patcher.Properties
{
/// <summary>
/// A strongly-typed resource class, for looking up localized strings, etc.
/// </summary>
// This class was auto-generated by the StronglyTypedResourceBuilder
// class via a tool like ResGen or Visual Studio.
// To add or remove a member, edit your .ResX file then rerun ResGen
// with the /str option, or rebuild your VS project.
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
internal class Resources
{
private static global::System.Resources.ResourceManager resourceMan;
private static global::System.Globalization.CultureInfo resourceCulture;
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
internal Resources()
{
}
/// <summary>
/// Returns the cached ResourceManager instance used by this class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Resources.ResourceManager ResourceManager
{
get
{
if ((resourceMan == null))
{
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Patcher.Properties.Resources", typeof(Resources).Assembly);
resourceMan = temp;
}
return resourceMan;
}
}
/// <summary>
/// Overrides the current thread's CurrentUICulture property for all
/// resource lookups using this strongly typed resource class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Globalization.CultureInfo Culture
{
get
{
return resourceCulture;
}
set
{
resourceCulture = value;
}
}
}
}
+117
View File
@@ -0,0 +1,117 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>
+30
View File
@@ -0,0 +1,30 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:4.0.30319.42000
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace Patcher.Properties
{
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "11.0.0.0")]
internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase
{
private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
public static Settings Default
{
get
{
return defaultInstance;
}
}
}
}
@@ -0,0 +1,7 @@
<?xml version='1.0' encoding='utf-8'?>
<SettingsFile xmlns="http://schemas.microsoft.com/VisualStudio/2004/01/settings" CurrentProfile="(Default)">
<Profiles>
<Profile Name="(Default)" />
</Profiles>
<Settings />
</SettingsFile>
+11
View File
@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Workaround for intermittent issue
https://developercommunity.visualstudio.com/content/problem/983843/dotnet-build-task-does-not-use-nugetorg-for-one-pr.html
-->
<configuration>
<packageSources>
<clear />
<add key="nuget" value="https://api.nuget.org/v3/index.json" />
</packageSources>
</configuration>