32 Commits
Author SHA1 Message Date
Gustave Monce d270cace79 Fix: device being null 2026-04-22 18:36:50 +02:00
Gustave Monce af61c9ad29 Preliminary support for UFP 2026-04-16 18:46:00 +02:00
Gustave Monce de4d5e577a Add preliminary SimpleIO support 2026-04-16 18:11:13 +02:00
Gustave Monce df02025a31 Update timebomb 2026-01-03 23:26:37 +01:00
Gustave Monce ad92ecdab3 Restructure assets into their own dedicated folders 2025-11-01 11:06:33 +01:00
Gustave Monce b3b037a3c8 Remove deprecated download command line options 2025-11-01 11:06:17 +01:00
Gustave Monce be15155c39 Deprecate MSR download fully as the MSR and repair avoidance services are fully deprecated as of 2025 2025-11-01 11:06:02 +01:00
Gustave Monce a17dae3931 Update project structure 2025-11-01 09:44:23 +01:00
Gustave Monce 7646e3fc76 Bump timebomb date 2025-11-01 09:42:59 +01:00
Gustave Monce 933e9e53b6 Migrate DiscUtils fat code to a standalone project dependency 2025-11-01 09:42:52 +01:00
Gustave Monce e838168127 Migrate 7zip code to a standalone project dependency 2025-11-01 09:31:14 +01:00
Gustave Monce 058cde0d91 Migrate WinUSBNet code to a standalone project dependency 2025-11-01 09:28:08 +01:00
Gustave Monce 1cc7a5cee4 Update Timebomb 2024-12-23 15:14:30 +01:00
Gustave Monce 132e21e58a Patcher: fix: broken go to labels in script engine 2024-10-22 21:22:30 +02:00
Gustave Monce 1e5da5452b Small fixes 2024-10-21 23:52:08 +02:00
Gustave Monce 6992ed3f70 Remove references to dead website 2024-10-21 23:30:50 +02:00
Gustave Monce bb9702a3c3 Patcher: fix compilation with dotnet 8 2024-10-21 23:25:50 +02:00
Gustave Monce 3c66688303 Add Patcher Project
The other Patcher repository is locked from future modifications
2024-10-21 08:57:39 +02:00
Gustave Monce bc77e8b589 Fixes 2024-10-21 08:56:11 +02:00
Gustave Monce 6be24faee0 Update ci.yml 2024-10-13 00:26:53 +02:00
Gustave Monce e078bb10ed Fixes for Spec A unlocking
In memories of the cyan RM-821 from a fellow care center

Rest in peace, 12th of October 2024
2024-10-13 00:25:01 +02:00
Gustave Monce 605b19aede Fixes 2024-10-12 21:22:07 +02:00
Gustave Monce d9da49915e Some changes 2024-10-12 19:44:11 +02:00
Gustave Monce 7c18a168fa Various Fixes 2024-10-12 19:15:41 +02:00
Gustave Monce 303c2d4b5a Some cleanup 2024-10-12 18:38:39 +02:00
Gustave Monce d700ae5911 Add the ability to add Secure WIMs to the store 2024-10-12 17:19:47 +02:00
Gustave Monce 14bf607111 Remove Defunct MSR Downloads 2024-10-12 17:14:06 +02:00
Gustave Monce 57c9595d86 Some cleanup 2024-10-12 16:56:36 +02:00
Gustave Monce 7fc332e912 Cleanup using directives 2024-10-12 13:46:34 +02:00
Gustave Monce bcec0a72e6 Nokia Flash Model -> Nokia UEFI Model 2024-10-12 13:45:51 +02:00
Gustave Monce 00407d6f24 Cleanup 2024-10-12 13:40:24 +02:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2d5b0fd3db Bump System.Text.Json from 8.0.4 to 8.0.5 in /WPinternals (#79)
Bumps [System.Text.Json](https://github.com/dotnet/runtime) from 8.0.4 to 8.0.5.
- [Release notes](https://github.com/dotnet/runtime/releases)
- [Commits](https://github.com/dotnet/runtime/compare/v8.0.4...v8.0.5)

---
updated-dependencies:
- dependency-name: System.Text.Json
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-10-09 09:03:31 +02:00
315 changed files with 21729 additions and 7115 deletions
+2 -2
View File
@@ -15,7 +15,7 @@ jobs:
platform: [win]
steps:
- name: Checkout
uses: actions/checkout@v2
uses: actions/checkout@v4
- name: Install .NET SDK
uses: actions/setup-dotnet@v1
@@ -31,7 +31,7 @@ jobs:
msbuild /m /t:restore,wpinternals:publish /p:Platform=${{ matrix.architecture }} /p:RuntimeIdentifier=${{ matrix.platform }}-${{ matrix.architecture }} /p:PublishDir=${{ github.workspace }}/artifacts/${{ matrix.platform }}-${{ matrix.architecture }} /p:PublishSingleFile=true /p:PublishTrimmed=false WPinternals.sln
- name: Upload artifact
uses: actions/upload-artifact@v2
uses: actions/upload-artifact@v4
with:
name: ${{ matrix.platform }}-${{ matrix.architecture }}
path: ${{ github.workspace }}/artifacts/${{ matrix.platform }}-${{ matrix.architecture }}
+10
View File
@@ -0,0 +1,10 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<RootNamespace>_7zip</RootNamespace>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
</Project>
@@ -47,7 +47,7 @@ namespace SevenZip.CommandLineParser
{
public bool ThereIs;
public bool WithMinus;
public ArrayList PostStrings = new();
public ArrayList PostStrings = [];
public int PostCharIndex;
public SwitchResult()
{
@@ -57,7 +57,7 @@ namespace SevenZip.CommandLineParser
public class Parser
{
public ArrayList NonSwitchStrings = new();
public ArrayList NonSwitchStrings = [];
private readonly SwitchResult[] _switches;
public Parser(int numSwitches)
@@ -4,7 +4,7 @@ using System.Text;
namespace DiscUtils.CoreCompat
{
internal static class EncodingHelper
public static class EncodingHelper
{
private static bool _registered;
@@ -0,0 +1,13 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="DiscUtils.Core" Version="0.16.13" />
</ItemGroup>
</Project>
@@ -28,7 +28,7 @@ using System.Text.RegularExpressions;
namespace DiscUtils.Internal
{
internal static class Utilities
public static class Utilities
{
/// <summary>
/// Converts between two arrays.
@@ -61,7 +61,7 @@ namespace DiscUtils.Internal
/// <returns>The resultant array.</returns>
public static U[] Map<T, U>(IEnumerable<T> source, Func<T, U> func)
{
List<U> result = new();
List<U> result = [];
foreach (T sVal in source)
{
@@ -48,15 +48,7 @@ namespace DiscUtils.Fat
_fat = fileSystem.Fat;
_length = length;
_knownClusters = new List<uint>();
if (firstCluster != 0)
{
_knownClusters.Add(firstCluster);
}
else
{
_knownClusters.Add(FatBuffer.EndOfChain);
}
_knownClusters = [firstCluster != 0 ? firstCluster : FatBuffer.EndOfChain];
if (_length == uint.MaxValue)
{
@@ -0,0 +1,13 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\DiscUtils.Core\DiscUtils.Core.WPI.csproj" />
</ItemGroup>
</Project>
@@ -64,7 +64,7 @@ namespace DiscUtils.Fat
{
_type = type;
_buffer = buffer;
_dirtySectors = new Dictionary<uint, uint>();
_dirtySectors = [];
}
internal int NumEntries
@@ -220,7 +220,7 @@ namespace DiscUtils.Fat
internal List<uint> GetChain(uint head)
{
List<uint> result = new();
List<uint> result = [];
if (head != 0)
{
@@ -452,8 +452,8 @@ namespace DiscUtils.Fat
private void LoadEntries()
{
_entries = new Dictionary<long, DirectoryEntry>();
_freeEntries = new List<long>();
_entries = [];
_freeEntries = [];
_selfEntryLocation = -1;
_parentEntryLocation = -1;
@@ -94,7 +94,7 @@ namespace DiscUtils.Fat
public FatFileSystem(Stream data)
: base(new FatFileSystemOptions())
{
_dirCache = new Dictionary<uint, Directory>();
_dirCache = [];
_timeConverter = DefaultTimeConverter;
Initialize(data);
}
@@ -111,7 +111,7 @@ namespace DiscUtils.Fat
public FatFileSystem(Stream data, Ownership ownsData)
: base(new FatFileSystemOptions())
{
_dirCache = new Dictionary<uint, Directory>();
_dirCache = [];
_timeConverter = DefaultTimeConverter;
Initialize(data);
_ownsData = ownsData;
@@ -125,7 +125,7 @@ namespace DiscUtils.Fat
public FatFileSystem(Stream data, TimeConverter timeConverter)
: base(new FatFileSystemOptions())
{
_dirCache = new Dictionary<uint, Directory>();
_dirCache = [];
_timeConverter = timeConverter;
Initialize(data);
}
@@ -140,7 +140,7 @@ namespace DiscUtils.Fat
public FatFileSystem(Stream data, Ownership ownsData, TimeConverter timeConverter)
: base(new FatFileSystemOptions())
{
_dirCache = new Dictionary<uint, Directory>();
_dirCache = [];
_timeConverter = timeConverter;
Initialize(data);
_ownsData = ownsData;
@@ -156,7 +156,7 @@ namespace DiscUtils.Fat
public FatFileSystem(Stream data, Ownership ownsData, FileSystemParameters parameters)
: base(new FatFileSystemOptions(parameters))
{
_dirCache = new Dictionary<uint, Directory>();
_dirCache = [];
if (parameters?.TimeConverter != null)
{
@@ -1273,7 +1273,7 @@ namespace DiscUtils.Fat
{
Regex re = Utilities.ConvertWildcardsToRegEx(searchPattern);
List<string> dirs = new();
List<string> dirs = [];
DoSearch(dirs, path, re, searchOption == SearchOption.AllDirectories, true, false);
return [.. dirs];
}
@@ -1309,7 +1309,7 @@ namespace DiscUtils.Fat
{
Regex re = Utilities.ConvertWildcardsToRegEx(searchPattern);
List<string> results = new();
List<string> results = [];
DoSearch(results, path, re, searchOption == SearchOption.AllDirectories, false, true);
return [.. results];
}
+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 - @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;
}
}
+39
View File
@@ -0,0 +1,39 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0-windows</TargetFramework>
<OutputType>WinExe</OutputType>
<RootNamespace>Patcher</RootNamespace>
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
<UseWindowsForms>true</UseWindowsForms>
<Platforms>x86</Platforms>
</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" />
</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 - @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"
// Phase 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"
// Phase 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 definitions 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 - @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 - @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 Auto-patcher")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("WPinternals.net")]
[assembly: AssemblyProduct("ARM Auto-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("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
+41
View File
@@ -0,0 +1,41 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.12.35323.107
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|x86 = .NET45Debug|x86
.NET45Release|x86 = .NET45Release|x86
Debug|x86 = Debug|x86
Release|x86 = Release|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{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|x86.ActiveCfg = Release|x86
{B67C62AE-86C4-4C18-99AB-4E94A3E09D36}..NET45Release|x86.Build.0 = Release|x86
{B67C62AE-86C4-4C18-99AB-4E94A3E09D36}.Debug|x86.ActiveCfg = Debug|x86
{B67C62AE-86C4-4C18-99AB-4E94A3E09D36}.Debug|x86.Build.0 = Debug|x86
{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|x86.ActiveCfg = Debug|x86
{95CF9509-C1C4-40F5-A60E-9D93EA6F438C}..NET45Debug|x86.Build.0 = Debug|x86
{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|x86.ActiveCfg = Debug|x86
{95CF9509-C1C4-40F5-A60E-9D93EA6F438C}.Debug|x86.Build.0 = Debug|x86
{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 - @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 - @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 - @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 - @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 definitions 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 definition 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 Definition 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 - @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 - @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="PatchDefinitionsXmlPath"></param>
public static void AddPatch(string InputFilePath, string OutputFilePath, string PatchDefinitionName, string TargetVersionDescription, string TargetFilePath, string PathToVisualStudioWithWP8SDK, UInt32 VirtualAddress, CodeType CodeType, string ArmCodeFragment, string PatchDefinitionsXmlPath)
{
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 PatchDefinitionsXml = File.ReadAllText(PatchDefinitionsXmlPath);
PatchEngine PatchEngine = new(PatchDefinitionsXml);
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 PatchDefinitions
PatchEngine.WriteDefinitions(PatchDefinitionsXmlPath);
}
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 - @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 - @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 - @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);
}
}
}
}
+12
View File
@@ -0,0 +1,12 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0-windows</TargetFramework>
<OutputType>WinExe</OutputType>
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
<UseWindowsForms>true</UseWindowsForms>
<Platforms>x86</Platforms>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\AutoPatcher\AutoPatcher.csproj" />
</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 - @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 - @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>
+1789 -3
View File
File diff suppressed because it is too large Load Diff
+4 -3
View File
@@ -20,9 +20,10 @@
using System;
using System.IO;
using System.Linq;
using System.Threading;
using System.Windows;
using WPinternals.HelperClasses;
using WPinternals.Config;
namespace WPinternals
{
@@ -76,14 +77,14 @@ namespace WPinternals
Registration.CheckExpiration();
string PatchDefintionsXml;
string PatchDefintionsPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "PatchDefintions.xml");
string PatchDefintionsPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Assets", "PatchDefintions.xml");
if (File.Exists(PatchDefintionsPath))
{
PatchDefintionsXml = File.ReadAllText(PatchDefintionsPath);
}
else
{
using Stream stream = System.Reflection.Assembly.GetEntryAssembly().GetManifestResourceStream("WPinternals.PatchDefinitions.xml");
using Stream stream = System.Reflection.Assembly.GetEntryAssembly().GetManifestResourceStream("WPinternals.Assets.PatchDefinitions.xml");
using StreamReader sr = new(stream);
PatchDefintionsXml = sr.ReadToEnd();
}

Before

Width:  |  Height:  |  Size: 9.9 KiB

After

Width:  |  Height:  |  Size: 9.9 KiB

Before

Width:  |  Height:  |  Size: 75 KiB

After

Width:  |  Height:  |  Size: 75 KiB

Before

Width:  |  Height:  |  Size: 50 KiB

After

Width:  |  Height:  |  Size: 50 KiB

Before

Width:  |  Height:  |  Size: 64 KiB

After

Width:  |  Height:  |  Size: 64 KiB

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 12 KiB

+26 -754
View File
@@ -26,6 +26,11 @@ using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using WPinternals.Config;
using WPinternals.HelperClasses;
using WPinternals.Models.Lumia.NCSd;
using WPinternals.Models.UEFIApps.BootMgr;
using WPinternals.Models.UEFIApps.Flash;
namespace WPinternals
{
@@ -85,20 +90,14 @@ namespace WPinternals
PhoneNotifierViewModel Notifier;
LumiaFlashAppModel FlashModel;
LumiaBootManagerAppModel BootMgrModel;
LumiaPhoneInfoAppModel PhoneInfoModel;
NokiaPhoneModel NormalModel;
NokiaCareSuiteModel NormalModel;
LumiaFlashAppPhoneInfo FlashInfo;
LumiaPhoneInfoAppPhoneInfo PhoneInfo;
LumiaBootManagerPhoneInfo BootManagerInfo;
string ProductType;
string ProductCode;
string OperatorCode;
string DownloadFolder;
string FFUFilePath;
string URL;
string[] URLs;
Uri URI;
string FFUFileName;
string EmergencyFileName;
string EmergencyFilePath;
string ProgrammerPath = "";
@@ -156,8 +155,12 @@ namespace WPinternals
? Convert.ToUInt64(args[2][2..], 16)
: Convert.ToUInt64(args[2], 10);
}
catch
catch (Exception ex)
{
LogFile.Log("An unexpected error happened", LogType.FileAndConsole);
LogFile.Log(ex.GetType().ToString(), LogType.FileAndConsole);
LogFile.Log(ex.Message, LogType.FileAndConsole);
LogFile.Log(ex.StackTrace, LogType.FileAndConsole);
LogFile.Log("Bad start sector", LogType.ConsoleOnly);
break;
}
@@ -185,10 +188,8 @@ namespace WPinternals
{
Notifier = new PhoneNotifierViewModel();
UIContext.Send(s => Notifier.Start(), null);
BootMgrModel = (LumiaBootManagerAppModel)await SwitchModeViewModel.SwitchTo(Notifier, PhoneInterfaces.Lumia_Bootloader); // This also works for Bootloader Spec A
GPT GPT = BootMgrModel.ReadGPT(); // May throw NotSupportedException
await SwitchModeViewModel.SwitchTo(Notifier, PhoneInterfaces.Lumia_Bootloader);
GPT GPT = await LumiaUnlockBootloaderViewModel.ReadGPTFromFlashOrBootMgr(Notifier);
foreach (Partition Partition in GPT.Partitions)
{
LogFile.Log(Partition.Name.PadRight(20) + "0x" + Partition.FirstSector.ToString("X8") + " - 0x" + Partition.LastSector.ToString("X8") + " " + Partition.Volume, LogType.ConsoleOnly);
@@ -216,8 +217,8 @@ namespace WPinternals
{
Notifier = new PhoneNotifierViewModel();
UIContext.Send(s => Notifier.Start(), null);
BootMgrModel = (LumiaBootManagerAppModel)await SwitchModeViewModel.SwitchTo(Notifier, PhoneInterfaces.Lumia_Bootloader);
GPT GPT = BootMgrModel.ReadGPT(); // May throw NotSupportedException
await SwitchModeViewModel.SwitchTo(Notifier, PhoneInterfaces.Lumia_Bootloader);
GPT GPT = await LumiaUnlockBootloaderViewModel.ReadGPTFromFlashOrBootMgr(Notifier);
string DirPath = Path.GetDirectoryName(args[2]);
if (!string.IsNullOrEmpty(DirPath) && !Directory.Exists(DirPath))
{
@@ -244,7 +245,7 @@ namespace WPinternals
LogFile.BeginAction("ConvertGPT");
try
{
using var stream = File.OpenRead(args[2]);
using FileStream stream = File.OpenRead(args[2]);
byte[] GPTBuffer = new byte[34 * 0x200];
stream.Read(GPTBuffer, 0, 34 * 0x200);
GPT GPT = new(GPTBuffer);// May throw NotSupportedException
@@ -275,8 +276,7 @@ namespace WPinternals
{
Notifier = new PhoneNotifierViewModel();
UIContext.Send(s => Notifier.Start(), null);
BootMgrModel = (LumiaBootManagerAppModel)await SwitchModeViewModel.SwitchTo(Notifier, PhoneInterfaces.Lumia_Bootloader);
byte[] GptChunk = BootMgrModel.GetGptChunk(0x20000);
byte[] GptChunk = await LumiaUnlockBootloaderViewModel.GetGptChunkFromFlashOrBootMgr(Notifier, 0x20000);
GPT GPT = new(GptChunk);
string Xml = File.ReadAllText(args[2]);
GPT.MergePartitions(Xml, false);
@@ -1267,740 +1267,6 @@ namespace WPinternals
LogFile.Log("Root access enabled on image", LogType.FileAndConsole);
break;
case "downloadffu":
LogFile.Log("Command: Download FFU", LogType.FileAndConsole);
Notifier = new PhoneNotifierViewModel();
UIContext.Send(s => Notifier.Start(), null);
if (Notifier.CurrentInterface == PhoneInterfaces.Lumia_Normal)
{
NormalModel = (NokiaPhoneModel)Notifier.CurrentModel;
ProductCode = NormalModel.ExecuteJsonMethodAsString("ReadProductCode", "ProductCode");
}
else if (Notifier.CurrentInterface == PhoneInterfaces.Lumia_Bootloader)
{
(Notifier.CurrentModel as LumiaBootManagerAppModel).SwitchToPhoneInfoAppContext();
if (Notifier.CurrentInterface != PhoneInterfaces.Lumia_PhoneInfo)
{
await Notifier.WaitForArrival();
}
if (Notifier.CurrentInterface != PhoneInterfaces.Lumia_PhoneInfo)
{
throw new WPinternalsException("Unexpected Mode");
}
PhoneInfoModel = (LumiaPhoneInfoAppModel)Notifier.CurrentModel;
PhoneInfo = PhoneInfoModel.ReadPhoneInfo();
ProductCode = PhoneInfo.ProductCode;
}
else if (Notifier.CurrentInterface == PhoneInterfaces.Lumia_PhoneInfo)
{
PhoneInfoModel = (LumiaPhoneInfoAppModel)Notifier.CurrentModel;
PhoneInfo = PhoneInfoModel.ReadPhoneInfo();
ProductCode = PhoneInfo.ProductCode;
}
else if (Notifier.CurrentInterface == PhoneInterfaces.Lumia_Flash)
{
bool ModernFlashApp = ((LumiaFlashAppModel)Notifier.CurrentModel).ReadPhoneInfo().FlashAppProtocolVersionMajor >= 2;
if (ModernFlashApp)
{
((LumiaFlashAppModel)Notifier.CurrentModel).SwitchToPhoneInfoAppContext();
}
else
{
((LumiaFlashAppModel)Notifier.CurrentModel).SwitchToPhoneInfoAppContextLegacy();
}
if (Notifier.CurrentInterface != PhoneInterfaces.Lumia_PhoneInfo)
{
await Notifier.WaitForArrival();
}
if (Notifier.CurrentInterface != PhoneInterfaces.Lumia_PhoneInfo)
{
throw new WPinternalsException("Unexpected Mode");
}
PhoneInfoModel = (LumiaPhoneInfoAppModel)Notifier.CurrentModel;
PhoneInfo = PhoneInfoModel.ReadPhoneInfo();
ProductCode = PhoneInfo.ProductCode;
}
else
{
NormalModel = (NokiaPhoneModel)await SwitchModeViewModel.SwitchTo(Notifier, PhoneInterfaces.Lumia_Normal);
ProductCode = NormalModel.ExecuteJsonMethodAsString("ReadProductCode", "ProductCode");
}
URL = LumiaDownloadModel.SearchFFU(null, ProductCode, null, out ProductType);
DownloadFolder = args.Length >= 3
? args[4]
: Environment.ExpandEnvironmentVariables("%ALLUSERSPROFILE%\\WPInternals\\Repository\\" + ProductType.ToUpper());
if (!Directory.Exists(DownloadFolder))
{
Directory.CreateDirectory(DownloadFolder);
}
LogFile.Log("Download folder: " + DownloadFolder, LogType.FileAndConsole);
LogFile.Log("URL: " + URL, LogType.FileAndConsole);
URI = new Uri(URL);
FFUFileName = Path.GetFileName(URI.LocalPath);
LogFile.Log("File: " + FFUFileName, LogType.FileAndConsole);
FFUFilePath = Path.Combine(DownloadFolder, FFUFileName);
LogFile.Log("Downloading...", LogType.FileAndConsole);
using (System.Net.WebClient myWebClient = new())
{
await myWebClient.DownloadFileTaskAsync(URL, FFUFilePath);
}
LogFile.Log("Download finished", LogType.FileAndConsole);
App.Config.AddFfuToRepository(FFUFilePath);
Notifier.Stop();
break;
case "downloadffubyoperatorcode":
LogFile.Log("Command: Download FFU by Operator Code", LogType.FileAndConsole);
if (args.Length < 4)
{
throw new ArgumentException("Wrong number of arguments. Usage: WPinternals.exe -DownloadFFUbyOperatorCode <Product type> <Operator code> <Optional: Download folder>");
}
ProductType = args[2];
LogFile.Log("Product type: " + ProductType, LogType.FileAndConsole);
OperatorCode = args[3];
LogFile.Log("Operator code: " + OperatorCode, LogType.FileAndConsole);
DownloadFolder = args.Length >= 5
? args[4]
: Environment.ExpandEnvironmentVariables("%ALLUSERSPROFILE%\\WPInternals\\Repository\\" + ProductType.ToUpper());
if (!Directory.Exists(DownloadFolder))
{
Directory.CreateDirectory(DownloadFolder);
}
LogFile.Log("Download folder: " + DownloadFolder, LogType.FileAndConsole);
URL = LumiaDownloadModel.SearchFFU(ProductType, null, OperatorCode);
LogFile.Log("URL: " + URL, LogType.FileAndConsole);
URI = new Uri(URL);
FFUFileName = Path.GetFileName(URI.LocalPath);
LogFile.Log("File: " + FFUFileName, LogType.FileAndConsole);
FFUFilePath = Path.Combine(DownloadFolder, FFUFileName);
LogFile.Log("Downloading...", LogType.FileAndConsole);
using (System.Net.WebClient myWebClient = new())
{
await myWebClient.DownloadFileTaskAsync(URL, FFUFilePath);
}
LogFile.Log("Download finished", LogType.FileAndConsole);
App.Config.AddFfuToRepository(FFUFilePath);
break;
case "downloadffubyproductcode":
LogFile.Log("Command: Download FFU by Product Code", LogType.FileAndConsole);
if (args.Length < 3)
{
throw new ArgumentException("Wrong number of arguments. Usage: WPinternals.exe -DownloadFFUbyProductCode <Product code> <Optional: Download folder>");
}
ProductCode = args[2];
LogFile.Log("Product code: " + ProductCode, LogType.FileAndConsole);
URL = LumiaDownloadModel.SearchFFU(null, ProductCode, null, out ProductType);
DownloadFolder = args.Length >= 4
? args[3]
: Environment.ExpandEnvironmentVariables("%ALLUSERSPROFILE%\\WPInternals\\Repository\\" + ProductType.ToUpper());
if (!Directory.Exists(DownloadFolder))
{
Directory.CreateDirectory(DownloadFolder);
}
LogFile.Log("Download folder: " + DownloadFolder, LogType.FileAndConsole);
LogFile.Log("URL: " + URL, LogType.FileAndConsole);
URI = new Uri(URL);
FFUFileName = Path.GetFileName(URI.LocalPath);
LogFile.Log("File: " + FFUFileName, LogType.FileAndConsole);
FFUFilePath = Path.Combine(DownloadFolder, FFUFileName);
LogFile.Log("Downloading...", LogType.FileAndConsole);
using (System.Net.WebClient myWebClient = new())
{
await myWebClient.DownloadFileTaskAsync(URL, FFUFilePath);
}
LogFile.Log("Download finished", LogType.FileAndConsole);
App.Config.AddFfuToRepository(FFUFilePath);
break;
case "downloadffubyproducttype":
LogFile.Log("Command: Download FFU by Product Type", LogType.FileAndConsole);
if (args.Length < 3)
{
throw new ArgumentException("Wrong number of arguments. Usage: WPinternals.exe -DownloadFFUbyProductType <Product type> <Optional: Download folder>");
}
ProductType = args[2];
LogFile.Log("Product type: " + ProductType, LogType.FileAndConsole);
DownloadFolder = args.Length >= 4
? args[3]
: Environment.ExpandEnvironmentVariables("%ALLUSERSPROFILE%\\WPInternals\\Repository\\" + ProductType.ToUpper());
if (!Directory.Exists(DownloadFolder))
{
Directory.CreateDirectory(DownloadFolder);
}
LogFile.Log("Download folder: " + DownloadFolder, LogType.FileAndConsole);
URL = LumiaDownloadModel.SearchFFU(ProductType, null, null);
LogFile.Log("URL: " + URL, LogType.FileAndConsole);
URI = new Uri(URL);
FFUFileName = Path.GetFileName(URI.LocalPath);
LogFile.Log("File: " + FFUFileName, LogType.FileAndConsole);
FFUFilePath = Path.Combine(DownloadFolder, FFUFileName);
LogFile.Log("Downloading...", LogType.FileAndConsole);
using (System.Net.WebClient myWebClient = new())
{
await myWebClient.DownloadFileTaskAsync(URL, FFUFilePath);
}
LogFile.Log("Download finished", LogType.FileAndConsole);
App.Config.AddFfuToRepository(FFUFilePath);
break;
case "searchffubyproducttype":
LogFile.Log("Command: Search FFU by Product Type", LogType.FileAndConsole);
if (args.Length < 3)
{
throw new ArgumentException("Wrong number of arguments. Usage: WPinternals.exe -SearchFFUbyProductType <Lumia model>");
}
ProductType = args[2];
LogFile.Log("Lumia model: " + ProductType, LogType.FileAndConsole);
URL = LumiaDownloadModel.SearchFFU(ProductType, null, null);
LogFile.Log("URL: " + URL, LogType.FileAndConsole);
URI = new Uri(URL);
FFUFileName = Path.GetFileName(URI.LocalPath);
LogFile.Log("File: " + FFUFileName, LogType.FileAndConsole);
break;
case "downloademergency":
LogFile.Log("Command: Download Emergency files", LogType.FileAndConsole);
Notifier = new PhoneNotifierViewModel();
UIContext.Send(s => Notifier.Start(), null);
if (Notifier.CurrentInterface == PhoneInterfaces.Lumia_Normal)
{
NormalModel = (NokiaPhoneModel)Notifier.CurrentModel;
ProductType = NormalModel.ExecuteJsonMethodAsString("ReadManufacturerModelName", "ManufacturerModelName");
if (ProductType.Contains('_'))
{
ProductType = ProductType.Substring(0, ProductType.IndexOf('_'));
}
}
else if (Notifier.CurrentInterface == PhoneInterfaces.Lumia_Bootloader)
{
BootMgrModel = (LumiaBootManagerAppModel)Notifier.CurrentModel;
BootManagerInfo = BootMgrModel.ReadPhoneInfo();
//ProductType = BootManagerInfo.Type; // TODO: FIXME
ProductType = "";
}
else if (Notifier.CurrentInterface == PhoneInterfaces.Lumia_Flash)
{
FlashModel = (LumiaFlashAppModel)Notifier.CurrentModel;
FlashInfo = FlashModel.ReadPhoneInfo();
//ProductType = FlashInfo.Type; // TODO: FIXME
ProductType = "";
}
else
{
NormalModel = (NokiaPhoneModel)await SwitchModeViewModel.SwitchTo(Notifier, PhoneInterfaces.Lumia_Normal);
ProductType = NormalModel.ExecuteJsonMethodAsString("ReadManufacturerModelName", "ManufacturerModelName");
if (ProductType.Contains('_'))
{
ProductType = ProductType.Substring(0, ProductType.IndexOf('_'));
}
}
URLs = LumiaDownloadModel.SearchEmergencyFiles(ProductType);
if (URLs != null)
{
DownloadFolder = args.Length >= 3
? args[2]
: Environment.ExpandEnvironmentVariables("%ALLUSERSPROFILE%\\WPInternals\\Repository\\" + ProductType.ToUpper());
if (!Directory.Exists(DownloadFolder))
{
Directory.CreateDirectory(DownloadFolder);
}
LogFile.Log("Download folder: " + DownloadFolder, LogType.FileAndConsole);
for (int i = 0; i < URLs.Length; i++)
{
LogFile.Log("URL: " + URLs[i], LogType.FileAndConsole);
URI = new Uri(URLs[i]);
EmergencyFileName = Path.GetFileName(URI.LocalPath);
LogFile.Log("File: " + EmergencyFileName, LogType.FileAndConsole);
EmergencyFilePath = Path.Combine(DownloadFolder, EmergencyFileName);
if (i == 0)
{
ProgrammerPath = EmergencyFilePath;
}
else
{
PayloadPath = EmergencyFilePath;
}
LogFile.Log("Downloading...", LogType.FileAndConsole);
using (System.Net.WebClient myWebClient = new())
{
await myWebClient.DownloadFileTaskAsync(URLs[i], EmergencyFilePath);
}
LogFile.Log("Download finished", LogType.FileAndConsole);
}
App.Config.AddEmergencyToRepository(ProductType, ProgrammerPath, PayloadPath);
}
Notifier.Stop();
break;
case "downloademergencybyproducttype":
LogFile.Log("Command: Download Emergency files", LogType.FileAndConsole);
if (args.Length < 3)
{
throw new WPinternalsException("Wrong number of arguments. Usage: WPinternals.exe -DownloadEmergencyByProductType <Product type> <Optional: Download folder>");
}
ProductType = args[2];
URLs = LumiaDownloadModel.SearchEmergencyFiles(ProductType);
if (URLs != null)
{
DownloadFolder = args.Length >= 4
? args[3]
: Environment.ExpandEnvironmentVariables("%ALLUSERSPROFILE%\\WPInternals\\Repository\\" + ProductType.ToUpper());
if (!Directory.Exists(DownloadFolder))
{
Directory.CreateDirectory(DownloadFolder);
}
LogFile.Log("Download folder: " + DownloadFolder, LogType.FileAndConsole);
for (int i = 0; i < URLs.Length; i++)
{
LogFile.Log("URL: " + URLs[i], LogType.FileAndConsole);
URI = new Uri(URLs[i]);
EmergencyFileName = Path.GetFileName(URI.LocalPath);
LogFile.Log("File: " + EmergencyFileName, LogType.FileAndConsole);
EmergencyFilePath = Path.Combine(DownloadFolder, EmergencyFileName);
if (i == 0)
{
ProgrammerPath = EmergencyFilePath;
}
else
{
PayloadPath = EmergencyFilePath;
}
LogFile.Log("Downloading...", LogType.FileAndConsole);
using (System.Net.WebClient myWebClient = new())
{
await myWebClient.DownloadFileTaskAsync(URLs[i], EmergencyFilePath);
}
LogFile.Log("Download finished", LogType.FileAndConsole);
}
App.Config.AddEmergencyToRepository(ProductType, ProgrammerPath, PayloadPath);
}
break;
case "downloadall":
LogFile.Log("Command: Download all", LogType.FileAndConsole);
Notifier = new PhoneNotifierViewModel();
UIContext.Send(s => Notifier.Start(), null);
if (Notifier.CurrentInterface == PhoneInterfaces.Lumia_Normal)
{
NormalModel = (NokiaPhoneModel)Notifier.CurrentModel;
ProductCode = NormalModel.ExecuteJsonMethodAsString("ReadProductCode", "ProductCode");
}
else if (Notifier.CurrentInterface == PhoneInterfaces.Lumia_Bootloader)
{
BootMgrModel = (LumiaBootManagerAppModel)Notifier.CurrentModel;
BootManagerInfo = BootMgrModel.ReadPhoneInfo();
//ProductCode = BootManagerInfo.ProductCode; // TODO: FIXME
ProductCode = "";
}
else if (Notifier.CurrentInterface == PhoneInterfaces.Lumia_Flash)
{
FlashModel = (LumiaFlashAppModel)Notifier.CurrentModel;
FlashInfo = FlashModel.ReadPhoneInfo();
//ProductCode = FlashInfo.ProductCode; // TODO: FIXME
ProductCode = "";
}
else
{
NormalModel = (NokiaPhoneModel)await SwitchModeViewModel.SwitchTo(Notifier, PhoneInterfaces.Lumia_Normal);
ProductCode = NormalModel.ExecuteJsonMethodAsString("ReadProductCode", "ProductCode");
}
URL = LumiaDownloadModel.SearchFFU(null, ProductCode, null, out ProductType);
DownloadFolder = args.Length >= 3
? args[2]
: Environment.ExpandEnvironmentVariables("%ALLUSERSPROFILE%\\WPInternals\\Repository\\" + ProductType.ToUpper());
if (!Directory.Exists(DownloadFolder))
{
Directory.CreateDirectory(DownloadFolder);
}
LogFile.Log("Download folder: " + DownloadFolder, LogType.FileAndConsole);
LogFile.Log("URL: " + URL, LogType.FileAndConsole);
URI = new Uri(URL);
FFUFileName = Path.GetFileName(URI.LocalPath);
LogFile.Log("File: " + FFUFileName, LogType.FileAndConsole);
FFUFilePath = Path.Combine(DownloadFolder, FFUFileName);
LogFile.Log("Downloading...", LogType.FileAndConsole);
using (System.Net.WebClient myWebClient = new())
{
await myWebClient.DownloadFileTaskAsync(URL, FFUFilePath);
}
LogFile.Log("Download finished", LogType.FileAndConsole);
App.Config.AddFfuToRepository(FFUFilePath);
URLs = LumiaDownloadModel.SearchEmergencyFiles(ProductType);
if (URLs != null)
{
for (int i = 0; i < URLs.Length; i++)
{
LogFile.Log("URL: " + URLs[i], LogType.FileAndConsole);
URI = new Uri(URLs[i]);
EmergencyFileName = Path.GetFileName(URI.LocalPath);
LogFile.Log("File: " + EmergencyFileName, LogType.FileAndConsole);
EmergencyFilePath = Path.Combine(DownloadFolder, EmergencyFileName);
if (i == 0)
{
ProgrammerPath = EmergencyFilePath;
}
else
{
PayloadPath = EmergencyFilePath;
}
LogFile.Log("Downloading...", LogType.FileAndConsole);
using (System.Net.WebClient myWebClient = new())
{
await myWebClient.DownloadFileTaskAsync(URLs[i], EmergencyFilePath);
}
LogFile.Log("Download finished", LogType.FileAndConsole);
}
App.Config.AddEmergencyToRepository(ProductType, ProgrammerPath, PayloadPath);
}
if (!App.Config.FFURepository.Any(e => App.PatchEngine.PatchDefinitions.First(p => p.Name == "SecureBootHack-V2-EFIESP").TargetVersions.Any(v => v.Description == e.OSVersion)))
{
ProductType = "RM-1085";
URL = LumiaDownloadModel.SearchFFU(ProductType, null, null);
DownloadFolder = args.Length >= 3
? args[2]
: Environment.ExpandEnvironmentVariables("%ALLUSERSPROFILE%\\WPInternals\\Repository\\" + ProductType.ToUpper());
if (!Directory.Exists(DownloadFolder))
{
Directory.CreateDirectory(DownloadFolder);
}
LogFile.Log("Download folder: " + DownloadFolder, LogType.FileAndConsole);
LogFile.Log("URL: " + URL, LogType.FileAndConsole);
URI = new Uri(URL);
FFUFileName = Path.GetFileName(URI.LocalPath);
LogFile.Log("File: " + FFUFileName, LogType.FileAndConsole);
FFUFilePath = Path.Combine(DownloadFolder, FFUFileName);
LogFile.Log("Downloading...", LogType.FileAndConsole);
using (System.Net.WebClient myWebClient = new())
{
await myWebClient.DownloadFileTaskAsync(URL, FFUFilePath);
}
LogFile.Log("Download finished", LogType.FileAndConsole);
App.Config.AddFfuToRepository(FFUFilePath);
if (!App.Config.FFURepository.Any(e => App.PatchEngine.PatchDefinitions.First(p => p.Name == "SecureBootHack-V2-EFIESP").TargetVersions.Any(v => v.Description == e.OSVersion)))
{
throw new WPinternalsException("Unable to find compatible FFU", "No donor-FFU has been found in the repository with a supported OS version. You can add a donor-FFU within the download section of the tool or by using the command line. A donor-FFU can be for a different device and a different CPU than your device. It is only used to gather Operating System specific binaries to be patched and used as part of the unlock process.");
}
}
Notifier.Stop();
break;
case "downloadallbyproducttype":
LogFile.Log("Command: Download all by Product Type", LogType.FileAndConsole);
if (args.Length < 3)
{
throw new ArgumentException("Wrong number of arguments. Usage: WPinternals.exe -DownloadAllByProductType <Product type> <Optional: Download folder>");
}
ProductType = args[2];
LogFile.Log("Product type: " + ProductType, LogType.FileAndConsole);
DownloadFolder = args.Length >= 4
? args[3]
: Environment.ExpandEnvironmentVariables("%ALLUSERSPROFILE%\\WPInternals\\Repository\\" + ProductType.ToUpper());
if (!Directory.Exists(DownloadFolder))
{
Directory.CreateDirectory(DownloadFolder);
}
LogFile.Log("Download folder: " + DownloadFolder, LogType.FileAndConsole);
URL = LumiaDownloadModel.SearchFFU(ProductType, null, null);
LogFile.Log("URL: " + URL, LogType.FileAndConsole);
URI = new Uri(URL);
FFUFileName = Path.GetFileName(URI.LocalPath);
LogFile.Log("File: " + FFUFileName, LogType.FileAndConsole);
FFUFilePath = Path.Combine(DownloadFolder, FFUFileName);
LogFile.Log("Downloading...", LogType.FileAndConsole);
using (System.Net.WebClient myWebClient = new())
{
await myWebClient.DownloadFileTaskAsync(URL, FFUFilePath);
}
LogFile.Log("Download finished", LogType.FileAndConsole);
App.Config.AddFfuToRepository(FFUFilePath);
URLs = LumiaDownloadModel.SearchEmergencyFiles(ProductType);
if (URLs != null)
{
for (int i = 0; i < URLs.Length; i++)
{
LogFile.Log("URL: " + URLs[i], LogType.FileAndConsole);
URI = new Uri(URLs[i]);
EmergencyFileName = Path.GetFileName(URI.LocalPath);
LogFile.Log("File: " + EmergencyFileName, LogType.FileAndConsole);
EmergencyFilePath = Path.Combine(DownloadFolder, EmergencyFileName);
if (i == 0)
{
ProgrammerPath = EmergencyFilePath;
}
else
{
PayloadPath = EmergencyFilePath;
}
LogFile.Log("Downloading...", LogType.FileAndConsole);
using (System.Net.WebClient myWebClient = new())
{
await myWebClient.DownloadFileTaskAsync(URLs[i], EmergencyFilePath);
}
LogFile.Log("Download finished", LogType.FileAndConsole);
}
App.Config.AddEmergencyToRepository(ProductType, ProgrammerPath, PayloadPath);
}
if (!App.Config.FFURepository.Any(e => App.PatchEngine.PatchDefinitions.First(p => p.Name == "SecureBootHack-V2-EFIESP").TargetVersions.Any(v => v.Description == e.OSVersion)))
{
ProductType = "RM-1085";
URL = LumiaDownloadModel.SearchFFU(ProductType, null, null);
DownloadFolder = args.Length >= 4
? args[3]
: Environment.ExpandEnvironmentVariables("%ALLUSERSPROFILE%\\WPInternals\\Repository\\" + ProductType.ToUpper());
if (!Directory.Exists(DownloadFolder))
{
Directory.CreateDirectory(DownloadFolder);
}
LogFile.Log("Download folder: " + DownloadFolder, LogType.FileAndConsole);
LogFile.Log("URL: " + URL, LogType.FileAndConsole);
URI = new Uri(URL);
FFUFileName = Path.GetFileName(URI.LocalPath);
LogFile.Log("File: " + FFUFileName, LogType.FileAndConsole);
FFUFilePath = Path.Combine(DownloadFolder, FFUFileName);
LogFile.Log("Downloading...", LogType.FileAndConsole);
using (System.Net.WebClient myWebClient = new())
{
await myWebClient.DownloadFileTaskAsync(URL, FFUFilePath);
}
LogFile.Log("Download finished", LogType.FileAndConsole);
App.Config.AddFfuToRepository(FFUFilePath);
if (!App.Config.FFURepository.Any(e => App.PatchEngine.PatchDefinitions.First(p => p.Name == "SecureBootHack-V2-EFIESP").TargetVersions.Any(v => v.Description == e.OSVersion)))
{
throw new WPinternalsException("Unable to find compatible FFU", "No donor-FFU has been found in the repository with a supported OS version. You can add a donor-FFU within the download section of the tool or by using the command line. A donor-FFU can be for a different device and a different CPU than your device. It is only used to gather Operating System specific binaries to be patched and used as part of the unlock process.");
}
}
break;
case "downloadallbyproductcode":
LogFile.Log("Command: Download all by Product Code", LogType.FileAndConsole);
if (args.Length < 3)
{
throw new ArgumentException("Wrong number of arguments. Usage: WPinternals.exe -DownloadAllByProductCode <Product code> <Optional: Download folder>");
}
ProductCode = args[2];
LogFile.Log("Product code: " + ProductCode, LogType.FileAndConsole);
URL = LumiaDownloadModel.SearchFFU(null, ProductCode, null, out ProductType);
DownloadFolder = args.Length >= 4
? args[3]
: Environment.ExpandEnvironmentVariables("%ALLUSERSPROFILE%\\WPInternals\\Repository\\" + ProductType.ToUpper());
if (!Directory.Exists(DownloadFolder))
{
Directory.CreateDirectory(DownloadFolder);
}
LogFile.Log("Download folder: " + DownloadFolder, LogType.FileAndConsole);
LogFile.Log("URL: " + URL, LogType.FileAndConsole);
URI = new Uri(URL);
FFUFileName = Path.GetFileName(URI.LocalPath);
LogFile.Log("File: " + FFUFileName, LogType.FileAndConsole);
FFUFilePath = Path.Combine(DownloadFolder, FFUFileName);
LogFile.Log("Downloading...", LogType.FileAndConsole);
using (System.Net.WebClient myWebClient = new())
{
await myWebClient.DownloadFileTaskAsync(URL, FFUFilePath);
}
LogFile.Log("Download finished", LogType.FileAndConsole);
App.Config.AddFfuToRepository(FFUFilePath);
URLs = LumiaDownloadModel.SearchEmergencyFiles(ProductType);
if (URLs != null)
{
for (int i = 0; i < URLs.Length; i++)
{
LogFile.Log("URL: " + URLs[i], LogType.FileAndConsole);
URI = new Uri(URLs[i]);
EmergencyFileName = Path.GetFileName(URI.LocalPath);
LogFile.Log("File: " + EmergencyFileName, LogType.FileAndConsole);
EmergencyFilePath = Path.Combine(DownloadFolder, EmergencyFileName);
if (i == 0)
{
ProgrammerPath = EmergencyFilePath;
}
else
{
PayloadPath = EmergencyFilePath;
}
LogFile.Log("Downloading...", LogType.FileAndConsole);
using (System.Net.WebClient myWebClient = new())
{
await myWebClient.DownloadFileTaskAsync(URLs[i], EmergencyFilePath);
}
LogFile.Log("Download finished", LogType.FileAndConsole);
}
App.Config.AddEmergencyToRepository(ProductType, ProgrammerPath, PayloadPath);
}
if (!App.Config.FFURepository.Any(e => App.PatchEngine.PatchDefinitions.First(p => p.Name == "SecureBootHack-V2-EFIESP").TargetVersions.Any(v => v.Description == e.OSVersion)))
{
ProductType = "RM-1085";
URL = LumiaDownloadModel.SearchFFU(ProductType, null, null);
DownloadFolder = args.Length >= 4
? args[3]
: Environment.ExpandEnvironmentVariables("%ALLUSERSPROFILE%\\WPInternals\\Repository\\" + ProductType.ToUpper());
if (!Directory.Exists(DownloadFolder))
{
Directory.CreateDirectory(DownloadFolder);
}
LogFile.Log("Download folder: " + DownloadFolder, LogType.FileAndConsole);
LogFile.Log("URL: " + URL, LogType.FileAndConsole);
URI = new Uri(URL);
FFUFileName = Path.GetFileName(URI.LocalPath);
LogFile.Log("File: " + FFUFileName, LogType.FileAndConsole);
FFUFilePath = Path.Combine(DownloadFolder, FFUFileName);
LogFile.Log("Downloading...", LogType.FileAndConsole);
using (System.Net.WebClient myWebClient = new())
{
await myWebClient.DownloadFileTaskAsync(URL, FFUFilePath);
}
LogFile.Log("Download finished", LogType.FileAndConsole);
App.Config.AddFfuToRepository(FFUFilePath);
if (!App.Config.FFURepository.Any(e => App.PatchEngine.PatchDefinitions.First(p => p.Name == "SecureBootHack-V2-EFIESP").TargetVersions.Any(v => v.Description == e.OSVersion)))
{
throw new WPinternalsException("Unable to find compatible FFU", "No donor-FFU has been found in the repository with a supported OS version. You can add a donor-FFU within the download section of the tool or by using the command line. A donor-FFU can be for a different device and a different CPU than your device. It is only used to gather Operating System specific binaries to be patched and used as part of the unlock process.");
}
}
break;
case "downloadallbyoperatorcode":
LogFile.Log("Command: Download FFU by Operator Code", LogType.FileAndConsole);
if (args.Length < 4)
{
throw new ArgumentException("Wrong number of arguments. Usage: WPinternals.exe -DownloadFFUbyOperatorCode <Product type> <Operator code> <Optional: Download folder>");
}
ProductType = args[2];
LogFile.Log("Product type: " + ProductType, LogType.FileAndConsole);
OperatorCode = args[3];
LogFile.Log("Operator code: " + OperatorCode, LogType.FileAndConsole);
DownloadFolder = args.Length >= 5
? args[4]
: Environment.ExpandEnvironmentVariables("%ALLUSERSPROFILE%\\WPInternals\\Repository\\" + ProductType.ToUpper());
if (!Directory.Exists(DownloadFolder))
{
Directory.CreateDirectory(DownloadFolder);
}
LogFile.Log("Download folder: " + DownloadFolder, LogType.FileAndConsole);
URL = LumiaDownloadModel.SearchFFU(ProductType, null, OperatorCode);
LogFile.Log("URL: " + URL, LogType.FileAndConsole);
URI = new Uri(URL);
FFUFileName = Path.GetFileName(URI.LocalPath);
LogFile.Log("File: " + FFUFileName, LogType.FileAndConsole);
FFUFilePath = Path.Combine(DownloadFolder, FFUFileName);
LogFile.Log("Downloading...", LogType.FileAndConsole);
using (System.Net.WebClient myWebClient = new())
{
await myWebClient.DownloadFileTaskAsync(URL, FFUFilePath);
}
LogFile.Log("Download finished", LogType.FileAndConsole);
App.Config.AddFfuToRepository(FFUFilePath);
URLs = LumiaDownloadModel.SearchEmergencyFiles(ProductType);
if (URLs != null)
{
for (int i = 0; i < URLs.Length; i++)
{
LogFile.Log("URL: " + URLs[i], LogType.FileAndConsole);
URI = new Uri(URLs[i]);
EmergencyFileName = Path.GetFileName(URI.LocalPath);
LogFile.Log("File: " + EmergencyFileName, LogType.FileAndConsole);
EmergencyFilePath = Path.Combine(DownloadFolder, EmergencyFileName);
if (i == 0)
{
ProgrammerPath = EmergencyFilePath;
}
else
{
PayloadPath = EmergencyFilePath;
}
LogFile.Log("Downloading...", LogType.FileAndConsole);
using (System.Net.WebClient myWebClient = new())
{
await myWebClient.DownloadFileTaskAsync(URLs[i], EmergencyFilePath);
}
LogFile.Log("Download finished", LogType.FileAndConsole);
}
App.Config.AddEmergencyToRepository(ProductType, ProgrammerPath, PayloadPath);
}
if (!App.Config.FFURepository.Any(e => App.PatchEngine.PatchDefinitions.First(p => p.Name == "SecureBootHack-V2-EFIESP").TargetVersions.Any(v => v.Description == e.OSVersion)))
{
ProductType = "RM-1085";
URL = LumiaDownloadModel.SearchFFU(ProductType, null, null);
DownloadFolder = args.Length >= 5
? args[4]
: Environment.ExpandEnvironmentVariables("%ALLUSERSPROFILE%\\WPInternals\\Repository\\" + ProductType.ToUpper());
if (!Directory.Exists(DownloadFolder))
{
Directory.CreateDirectory(DownloadFolder);
}
LogFile.Log("Download folder: " + DownloadFolder, LogType.FileAndConsole);
LogFile.Log("URL: " + URL, LogType.FileAndConsole);
URI = new Uri(URL);
FFUFileName = Path.GetFileName(URI.LocalPath);
LogFile.Log("File: " + FFUFileName, LogType.FileAndConsole);
FFUFilePath = Path.Combine(DownloadFolder, FFUFileName);
LogFile.Log("Downloading...", LogType.FileAndConsole);
using (System.Net.WebClient myWebClient = new())
{
await myWebClient.DownloadFileTaskAsync(URL, FFUFilePath);
}
LogFile.Log("Download finished", LogType.FileAndConsole);
App.Config.AddFfuToRepository(FFUFilePath);
if (!App.Config.FFURepository.Any(e => App.PatchEngine.PatchDefinitions.First(p => p.Name == "SecureBootHack-V2-EFIESP").TargetVersions.Any(v => v.Description == e.OSVersion)))
{
throw new WPinternalsException("Unable to find compatible FFU", "No donor-FFU has been found in the repository with a supported OS version. You can add a donor-FFU within the download section of the tool or by using the command line. A donor-FFU can be for a different device and a different CPU than your device. It is only used to gather Operating System specific binaries to be patched and used as part of the unlock process.");
}
}
break;
case "rewritepartitionsfrommassstorage":
if (args.Length < 2)
{
@@ -2149,12 +1415,18 @@ namespace WPinternals
Microsoft.Win32.SafeHandles.SafeFileHandle safeFileHandle = new(stdHandle, true);
FileStream fileStream = new(safeFileHandle, FileAccess.Write);
Encoding encoding = Encoding.GetEncoding(MY_CODE_PAGE);
StreamWriter standardOutput = new(fileStream, encoding);
standardOutput.AutoFlush = true;
StreamWriter standardOutput = new(fileStream, encoding)
{
AutoFlush = true
};
Console.SetOut(standardOutput);
}
catch
catch (Exception ex)
{
LogFile.Log("An unexpected error happened", LogType.FileAndConsole);
LogFile.Log(ex.GetType().ToString(), LogType.FileAndConsole);
LogFile.Log(ex.Message, LogType.FileAndConsole);
LogFile.Log(ex.StackTrace, LogType.FileAndConsole);
}
}
+59
View File
@@ -0,0 +1,59 @@
// Copyright (c) 2018, Rene Lergner - @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.IO;
using System.Xml.Serialization;
using WPinternals.HelperClasses;
namespace WPinternals.Config
{
public class EmergencyFileEntry
{
public string Type;
[XmlIgnore]
public byte[] RKH;
[XmlElement(ElementName = "RKH")]
public string RKHAsString
{
get
{
return RKH == null ? null : Converter.ConvertHexToString(RKH, "");
}
set
{
RKH = value == null ? null : Converter.ConvertStringToHex(value);
}
}
public string ProgrammerPath;
public string PayloadPath;
internal bool ProgrammerExists()
{
return File.Exists(ProgrammerPath);
}
internal bool PayloadExists()
{
return File.Exists(PayloadPath);
}
}
}
+37
View File
@@ -0,0 +1,37 @@
// Copyright (c) 2018, Rene Lergner - @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.IO;
namespace WPinternals.Config
{
public class FFUEntry
{
public string PlatformID;
public string FirmwareVersion;
public string OSVersion;
public string Path;
internal bool Exists()
{
return File.Exists(Path);
}
}
}
+75
View File
@@ -0,0 +1,75 @@
// Copyright (c) 2018, Rene Lergner - @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.Xml.Serialization;
namespace WPinternals.Config
{
public class FlashProfile
{
public string Type;
public string PlatformID;
public string ProductCode;
public string PhoneFirmware;
public string FfuFirmware;
[XmlIgnore]
internal uint FillSize;
[XmlIgnore]
internal uint HeaderSize;
[XmlIgnore]
internal bool AssumeImageHeaderFallsInGap;
[XmlIgnore]
internal bool AllocateAsyncBuffersOnPhone;
[XmlElement(ElementName = "Profile")]
public string ProfileAsString
{
get
{
byte[] ValueBuffer = new byte[10];
ValueBuffer[0] = 1; // Profile version
ByteOperations.WriteUInt32(ValueBuffer, 1, FillSize);
ByteOperations.WriteUInt32(ValueBuffer, 5, HeaderSize);
if (AssumeImageHeaderFallsInGap)
{
ValueBuffer[9] |= 1;
}
if (AllocateAsyncBuffersOnPhone)
{
ValueBuffer[9] |= 2;
}
return Convert.ToBase64String(ValueBuffer);
}
set
{
byte[] ValueBuffer = Convert.FromBase64String(value);
byte Version = ValueBuffer[0];
FillSize = ByteOperations.ReadUInt32(ValueBuffer, 1);
HeaderSize = ByteOperations.ReadUInt32(ValueBuffer, 5);
AssumeImageHeaderFallsInGap = (ValueBuffer[9] & 1) != 0;
AllocateAsyncBuffersOnPhone = (ValueBuffer[9] & 2) != 0;
}
}
}
}
+84
View File
@@ -0,0 +1,84 @@
// Copyright (c) 2018, Rene Lergner - @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.Linq;
using System.Security.Cryptography;
using System.Windows;
namespace WPinternals.Config
{
internal static class Registration
{
#if PREVIEW
internal const bool IsPrerelease = true;
#else
internal const bool IsPrerelease = false;
#endif
internal static readonly DateTime ExpirationDate = new(2027, 4, 1);
internal static void CheckExpiration()
{
#if PREVIEW
//if (IsPrerelease && (DateTime.Now >= ExpirationDate))
if (DateTime.Now >= ExpirationDate)
{
if (Environment.GetCommandLineArgs().Count() > 1)
{
Console.WriteLine("This prerelease version is expired!");
CommandLine.CloseConsole();
}
else
MessageBox.Show("This prerelease version is expired!", "Windows Phone Internals", MessageBoxButton.OK, MessageBoxImage.Exclamation);
Environment.Exit(0);
}
#endif
}
internal static bool IsRegistered()
{
bool Result = false;
if (App.Config.RegistrationName != null)
{
Result = CalcRegKey() == App.Config.RegistrationKey;
}
return Result;
}
internal static string CalcRegKey()
{
string KeyBase = App.Config.RegistrationName;
if (Environment.MachineName == null)
{
KeyBase += "-Unknown";
}
else
{
KeyBase += "-" + Environment.MachineName;
}
byte[] KeyBytes = System.Text.Encoding.UTF8.GetBytes(KeyBase);
SHA1Managed sha = new();
byte[] Key = sha.ComputeHash(KeyBytes);
return Convert.ToBase64String(Key);
}
}
}
+35
View File
@@ -0,0 +1,35 @@
// Copyright (c) 2018, Rene Lergner - @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.IO;
namespace WPinternals.Config
{
public class SecWimEntry
{
public string FirmwareVersion;
public string Path;
internal bool Exists()
{
return File.Exists(Path);
}
}
}
@@ -22,68 +22,11 @@ using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Security.Cryptography;
using System.Windows;
using System.Xml.Serialization;
using WPinternals.HelperClasses;
namespace WPinternals
namespace WPinternals.Config
{
internal static class Registration
{
#if PREVIEW
internal const bool IsPrerelease = true;
#else
internal const bool IsPrerelease = false;
#endif
internal static readonly DateTime ExpirationDate = new(2024, 12, 21);
internal static void CheckExpiration()
{
#if PREVIEW
//if (IsPrerelease && (DateTime.Now >= ExpirationDate))
if (DateTime.Now >= ExpirationDate)
{
if (Environment.GetCommandLineArgs().Count() > 1)
{
Console.WriteLine("This prerelease version is expired!");
CommandLine.CloseConsole();
}
else
MessageBox.Show("This prerelease version is expired!", "Windows Phone Internals", MessageBoxButton.OK, MessageBoxImage.Exclamation);
Environment.Exit(0);
}
#endif
}
internal static bool IsRegistered()
{
bool Result = false;
if (App.Config.RegistrationName != null)
{
Result = CalcRegKey() == App.Config.RegistrationKey;
}
return Result;
}
internal static string CalcRegKey()
{
string KeyBase = App.Config.RegistrationName;
if (Environment.MachineName == null)
{
KeyBase += "-Unknown";
}
else
{
KeyBase += "-" + Environment.MachineName;
}
byte[] KeyBytes = System.Text.Encoding.UTF8.GetBytes(KeyBase);
SHA1Managed sha = new();
byte[] Key = sha.ComputeHash(KeyBytes);
return Convert.ToBase64String(Key);
}
}
public class WPinternalsConfig
{
@@ -122,7 +65,7 @@ namespace WPinternals
FileWriter.Close();
}
internal void SetProfile(string Type, string PlatformID, string ProductCode, string PhoneFirmware, string FfuFirmware, UInt32 FillSize, UInt32 HeaderSize, bool AssumeImageHeaderFallsInGap, bool AllocateAsyncBuffersOnPhone)
internal void SetProfile(string Type, string PlatformID, string ProductCode, string PhoneFirmware, string FfuFirmware, uint FillSize, uint HeaderSize, bool AssumeImageHeaderFallsInGap, bool AllocateAsyncBuffersOnPhone)
{
FlashProfile Profile = GetProfile(PlatformID, PhoneFirmware, FfuFirmware);
if (Profile == null)
@@ -148,10 +91,10 @@ namespace WPinternals
internal FlashProfile GetProfile(string PlatformID, string PhoneFirmware, string FfuFirmware = null)
{
return FlashProfiles.Find(p => string.Equals(p.PlatformID, PlatformID, StringComparison.CurrentCultureIgnoreCase) && string.Equals(p.PhoneFirmware, PhoneFirmware, StringComparison.CurrentCultureIgnoreCase) && ((FfuFirmware == null) || string.Equals(p.FfuFirmware, FfuFirmware, StringComparison.CurrentCultureIgnoreCase)));
return FlashProfiles.Find(p => string.Equals(p.PlatformID, PlatformID, StringComparison.CurrentCultureIgnoreCase) && string.Equals(p.PhoneFirmware, PhoneFirmware, StringComparison.CurrentCultureIgnoreCase) && (FfuFirmware == null || string.Equals(p.FfuFirmware, FfuFirmware, StringComparison.CurrentCultureIgnoreCase)));
}
public List<FlashProfile> FlashProfiles = new();
public List<FlashProfile> FlashProfiles = [];
internal void AddFfuToRepository(string FFUPath)
{
@@ -168,7 +111,7 @@ namespace WPinternals
internal void AddFfuToRepository(string FFUPath, string PlatformID, string FirmwareVersion, string OSVersion)
{
FFUEntry Entry = FFURepository.Find(e => (e.PlatformID == PlatformID) && (e.FirmwareVersion == FirmwareVersion) && string.Equals(e.Path, FFUPath, StringComparison.CurrentCultureIgnoreCase));
FFUEntry Entry = FFURepository.Find(e => e.PlatformID == PlatformID && e.FirmwareVersion == FirmwareVersion && string.Equals(e.Path, FFUPath, StringComparison.CurrentCultureIgnoreCase));
if (Entry == null)
{
LogFile.Log("Adding FFU to repository: " + FFUPath, LogType.FileAndConsole);
@@ -218,11 +161,11 @@ namespace WPinternals
}
}
public List<FFUEntry> FFURepository = new();
public List<FFUEntry> FFURepository = [];
internal void AddSecWimToRepository(string SecWimPath, string FirmwareVersion)
{
SecWimEntry Entry = SecWimRepository.Find(e => (e.FirmwareVersion == FirmwareVersion) && string.Equals(e.Path, SecWimPath, StringComparison.CurrentCultureIgnoreCase));
SecWimEntry Entry = SecWimRepository.Find(e => e.FirmwareVersion == FirmwareVersion && string.Equals(e.Path, SecWimPath, StringComparison.CurrentCultureIgnoreCase));
if (Entry == null)
{
LogFile.Log("Adding Secure WIM to repository: " + SecWimPath, LogType.FileAndConsole);
@@ -264,14 +207,14 @@ namespace WPinternals
}
}
public List<SecWimEntry> SecWimRepository = new();
public List<SecWimEntry> SecWimRepository = [];
public List<EmergencyFileEntry> EmergencyRepository = new();
public List<EmergencyFileEntry> EmergencyRepository = [];
internal void AddEmergencyToRepository(string Type, string ProgrammerPath, string PayloadPath)
{
EmergencyFileEntry Entry = EmergencyRepository.Find(e => (e.Type == Type) && string.Equals(e.ProgrammerPath, ProgrammerPath, StringComparison.CurrentCultureIgnoreCase));
if ((Entry != null) && (PayloadPath != null) && (!string.Equals(Entry.PayloadPath, PayloadPath, StringComparison.CurrentCultureIgnoreCase)))
EmergencyFileEntry Entry = EmergencyRepository.Find(e => e.Type == Type && string.Equals(e.ProgrammerPath, ProgrammerPath, StringComparison.CurrentCultureIgnoreCase));
if (Entry != null && PayloadPath != null && !string.Equals(Entry.PayloadPath, PayloadPath, StringComparison.CurrentCultureIgnoreCase))
{
LogFile.Log("Updating emergency payload path in repository: " + PayloadPath, LogType.FileAndConsole);
Entry.PayloadPath = PayloadPath;
@@ -326,111 +269,4 @@ namespace WPinternals
public string RegistrationTelegramID;
public string RegistrationKey;
}
public class FlashProfile
{
public string Type;
public string PlatformID;
public string ProductCode;
public string PhoneFirmware;
public string FfuFirmware;
[XmlIgnore]
internal UInt32 FillSize;
[XmlIgnore]
internal UInt32 HeaderSize;
[XmlIgnore]
internal bool AssumeImageHeaderFallsInGap;
[XmlIgnore]
internal bool AllocateAsyncBuffersOnPhone;
[XmlElement(ElementName = "Profile")]
public string ProfileAsString
{
get
{
byte[] ValueBuffer = new byte[10];
ValueBuffer[0] = 1; // Profile version
ByteOperations.WriteUInt32(ValueBuffer, 1, FillSize);
ByteOperations.WriteUInt32(ValueBuffer, 5, HeaderSize);
if (AssumeImageHeaderFallsInGap)
{
ValueBuffer[9] |= 1;
}
if (AllocateAsyncBuffersOnPhone)
{
ValueBuffer[9] |= 2;
}
return Convert.ToBase64String(ValueBuffer);
}
set
{
byte[] ValueBuffer = Convert.FromBase64String(value);
byte Version = ValueBuffer[0];
FillSize = ByteOperations.ReadUInt32(ValueBuffer, 1);
HeaderSize = ByteOperations.ReadUInt32(ValueBuffer, 5);
AssumeImageHeaderFallsInGap = (ValueBuffer[9] & 1) != 0;
AllocateAsyncBuffersOnPhone = (ValueBuffer[9] & 2) != 0;
}
}
}
public class FFUEntry
{
public string PlatformID;
public string FirmwareVersion;
public string OSVersion;
public string Path;
internal bool Exists()
{
return File.Exists(Path);
}
}
public class SecWimEntry
{
public string FirmwareVersion;
public string Path;
internal bool Exists()
{
return File.Exists(Path);
}
}
public class EmergencyFileEntry
{
public string Type;
[XmlIgnore]
public byte[] RKH;
[XmlElement(ElementName = "RKH")]
public string RKHAsString
{
get
{
return RKH == null ? null : Converter.ConvertHexToString(RKH, "");
}
set
{
RKH = value == null ? null : Converter.ConvertStringToHex(value);
}
}
public string ProgrammerPath;
public string PayloadPath;
internal bool ProgrammerExists()
{
return File.Exists(ProgrammerPath);
}
internal bool PayloadExists()
{
return File.Exists(PayloadPath);
}
}
}
+10 -7
View File
@@ -24,6 +24,7 @@ using System.Globalization;
using System.Threading;
using System.Windows;
using System.Windows.Media;
using WPinternals.HelperClasses;
namespace WPinternals
{
@@ -149,7 +150,7 @@ namespace WPinternals
protected override Size MeasureOverride(Size availableSize)
{
var resultSize = new Size(availableSize.Width, 0);
Size resultSize = new Size(availableSize.Width, 0);
#if NETCORE
FormattedText formatted = new FormattedText(
@@ -429,9 +430,10 @@ namespace WPinternals
if (SaveDialog)
{
Microsoft.Win32.SaveFileDialog savedlg = new();
savedlg.FileName = Path ?? DefaultFileName;
Microsoft.Win32.SaveFileDialog savedlg = new()
{
FileName = Path ?? DefaultFileName
};
// Show open file dialog box
result = savedlg.ShowDialog();
@@ -446,9 +448,10 @@ namespace WPinternals
else
{
// Select file
Microsoft.Win32.OpenFileDialog dlg = new();
dlg.FileName = Path ?? DefaultFileName;
Microsoft.Win32.OpenFileDialog dlg = new()
{
FileName = Path ?? DefaultFileName
};
// Show open file dialog box
result = dlg.ShowDialog();
+1 -1
View File
@@ -79,7 +79,7 @@ namespace WPinternals
/// <returns>True if the user presses OK else false</returns>
public bool ShowDialog(IntPtr hWndOwner)
{
var fbd = new FolderBrowserDialog
FolderBrowserDialog fbd = new FolderBrowserDialog
{
Description = this.Title,
SelectedPath = this.InitialDirectory,
File diff suppressed because it is too large Load Diff
@@ -17,26 +17,24 @@
// 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.
//
// Some of the classes and functions in this file were found online.
// Where possible the original authors are referenced.
using System;
namespace WPinternals
namespace WPinternals.HelperClasses
{
internal class CommonPhoneInfo
internal class ArrivalEventArgs : EventArgs
{
public PhoneInfoState State = PhoneInfoState.Empty;
public PhoneInterfaces NewInterface;
public IDisposable NewModel;
public FlashAppType App;
public byte VersionMajor;
public byte VersionMinor;
public byte ProtocolVersionMajor;
public byte ProtocolVersionMinor;
internal void Log(LogType Type)
public ArrivalEventArgs(PhoneInterfaces NewInterface, IDisposable NewModel)
: base()
{
LogFile.Log($"App: {VersionMajor}.{VersionMinor}", Type);
LogFile.Log($"Protocol: {ProtocolVersionMajor}.{ProtocolVersionMinor}", Type);
this.NewInterface = NewInterface;
this.NewModel = NewModel;
}
}
}
@@ -0,0 +1,111 @@
// Copyright (c) 2018, Rene Lergner - @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.
//
// Some of the classes and functions in this file were found online.
// Where possible the original authors are referenced.
using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
namespace WPinternals.HelperClasses
{
internal class AsyncAutoResetEvent
{
private readonly LinkedList<TaskCompletionSource<bool>> waiters =
new();
private bool isSignaled;
public AsyncAutoResetEvent(bool signaled)
{
isSignaled = signaled;
}
public Task<bool> WaitAsync(TimeSpan timeout)
{
return WaitAsync(timeout, CancellationToken.None);
}
public async Task<bool> WaitAsync(TimeSpan timeout, CancellationToken cancellationToken)
{
TaskCompletionSource<bool> tcs;
lock (waiters)
{
if (isSignaled)
{
isSignaled = false;
return true;
}
else if (timeout == TimeSpan.Zero)
{
return isSignaled;
}
else
{
tcs = new TaskCompletionSource<bool>();
waiters.AddLast(tcs);
}
}
Task winner = await Task.WhenAny(tcs.Task, Task.Delay(timeout, cancellationToken));
if (winner == tcs.Task)
{
// The task was signaled.
return true;
}
else
{
// We timed-out; remove our reference to the task.
// This is an O(n) operation since waiters is a LinkedList<T>.
lock (waiters)
{
bool removed = waiters.Remove(tcs);
System.Diagnostics.Debug.Assert(removed);
return false;
}
}
}
public void Set()
{
TaskCompletionSource<bool> toRelease = null;
lock (waiters)
{
if (waiters.Count > 0)
{
// Signal the first task in the waiters list.
toRelease = waiters.First.Value;
waiters.RemoveFirst();
}
else if (!isSignaled)
{
// No tasks are pending
isSignaled = true;
}
}
toRelease?.SetResult(true);
}
}
}
+162
View File
@@ -0,0 +1,162 @@
// Copyright (c) 2018, Rene Lergner - @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.
//
// Some of the classes and functions in this file were found online.
// Where possible the original authors are referenced.
using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
namespace WPinternals.HelperClasses
{
// This class was found online.
// Original author is probably: John Melville
// https://social.msdn.microsoft.com/Forums/en-US/163ef755-ff7b-4ea5-b226-bbe8ef5f4796/is-there-a-pattern-for-calling-an-async-method-synchronously?forum=async
public static class AsyncHelpers
{
/// <summary>
/// Execute's an async Task<T> method which has a void return value synchronously
/// </summary>
/// <param name="task">Task<T> method to execute</param>
public static void RunSync(Func<Task> task)
{
SynchronizationContext oldContext = SynchronizationContext.Current;
ExclusiveSynchronizationContext synch = new ExclusiveSynchronizationContext();
SynchronizationContext.SetSynchronizationContext(synch);
synch.Post(async _ =>
{
try
{
await task();
}
catch (Exception e)
{
synch.InnerException = e;
throw;
}
finally
{
synch.EndMessageLoop();
}
}, null);
synch.BeginMessageLoop();
SynchronizationContext.SetSynchronizationContext(oldContext);
}
/// <summary>
/// Execute's an async Task<T> method which has a T return type synchronously
/// </summary>
/// <typeparam name="T">Return Type</typeparam>
/// <param name="task">Task<T> method to execute</param>
/// <returns></returns>
public static T RunSync<T>(Func<Task<T>> task)
{
SynchronizationContext oldContext = SynchronizationContext.Current;
ExclusiveSynchronizationContext synch = new ExclusiveSynchronizationContext();
SynchronizationContext.SetSynchronizationContext(synch);
T ret = default;
synch.Post(async _ =>
{
try
{
ret = await task();
}
catch (Exception e)
{
synch.InnerException = e;
throw;
}
finally
{
synch.EndMessageLoop();
}
}, null);
synch.BeginMessageLoop();
SynchronizationContext.SetSynchronizationContext(oldContext);
return ret;
}
private class ExclusiveSynchronizationContext : SynchronizationContext
{
private bool done;
public Exception InnerException
{
get; set;
}
private readonly AutoResetEvent workItemsWaiting = new(false);
private readonly Queue<Tuple<SendOrPostCallback, object>> items =
new();
public override void Send(SendOrPostCallback d, object state)
{
throw new NotSupportedException("We cannot send to our same thread");
}
public override void Post(SendOrPostCallback d, object state)
{
lock (items)
{
items.Enqueue(Tuple.Create(d, state));
}
workItemsWaiting.Set();
}
public void EndMessageLoop()
{
Post(_ => done = true, null);
}
public void BeginMessageLoop()
{
while (!done)
{
Tuple<SendOrPostCallback, object> task = null;
lock (items)
{
if (items.Count > 0)
{
task = items.Dequeue();
}
}
if (task != null)
{
task.Item1(task.Item2);
if (InnerException != null) // the method threw an exeption
{
throw new AggregateException("AsyncHelpers.Run method threw an exception.", InnerException);
}
}
else
{
workItemsWaiting.WaitOne();
}
}
}
public override SynchronizationContext CreateCopy()
{
return this;
}
}
}
}
+125
View File
@@ -0,0 +1,125 @@
// Copyright (c) 2018, Rene Lergner - @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.
//
// Some of the classes and functions in this file were found online.
// Where possible the original authors are referenced.
using System;
namespace WPinternals.HelperClasses
{
internal static class BigEndian
{
public static byte[] GetBytes(object Value)
{
byte[] Bytes;
if (Value is short)
{
Bytes = BitConverter.GetBytes((short)Value);
}
else if (Value is ushort)
{
Bytes = BitConverter.GetBytes((ushort)Value);
}
else if (Value is int)
{
Bytes = BitConverter.GetBytes((int)Value);
}
else
{
Bytes = Value is uint ? BitConverter.GetBytes((uint)Value) : throw new NotSupportedException();
}
byte[] Result = new byte[Bytes.Length];
for (int i = 0; i < Bytes.Length; i++)
{
Result[i] = Bytes[Bytes.Length - 1 - i];
}
return Result;
}
public static byte[] GetBytes(object Value, int Width)
{
byte[] Result;
byte[] BigEndianBytes = GetBytes(Value);
if (BigEndianBytes.Length == Width)
{
return BigEndianBytes;
}
else if (BigEndianBytes.Length > Width)
{
Result = new byte[Width];
Buffer.BlockCopy(BigEndianBytes, BigEndianBytes.Length - Width, Result, 0, Width);
return Result;
}
else
{
Result = new byte[Width];
Buffer.BlockCopy(BigEndianBytes, 0, Result, Width - BigEndianBytes.Length, BigEndianBytes.Length);
return Result;
}
}
public static ushort ToUInt16(byte[] Buffer, int Offset)
{
byte[] Bytes = new byte[2];
for (int i = 0; i < 2; i++)
{
Bytes[i] = Buffer[Offset + 1 - i];
}
return BitConverter.ToUInt16(Bytes, 0);
}
public static short ToInt16(byte[] Buffer, int Offset)
{
byte[] Bytes = new byte[2];
for (int i = 0; i < 2; i++)
{
Bytes[i] = Buffer[Offset + 1 - i];
}
return BitConverter.ToInt16(Bytes, 0);
}
public static uint ToUInt32(byte[] Buffer, int Offset)
{
byte[] Bytes = new byte[4];
for (int i = 0; i < 4; i++)
{
Bytes[i] = Buffer[Offset + 3 - i];
}
return BitConverter.ToUInt32(Bytes, 0);
}
public static int ToInt32(byte[] Buffer, int Offset)
{
byte[] Bytes = new byte[4];
for (int i = 0; i < 4; i++)
{
Bytes[i] = Buffer[Offset + 3 - i];
}
return BitConverter.ToInt32(Bytes, 0);
}
}
}
@@ -0,0 +1,138 @@
// Copyright (c) 2018, Rene Lergner - @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.
//
// Some of the classes and functions in this file were found online.
// Where possible the original authors are referenced.
using System;
using System.Globalization;
using System.Windows;
using System.Windows.Data;
namespace WPinternals.HelperClasses
{
public class BooleanConverter : DependencyObject, IValueConverter
{
public static readonly DependencyProperty OnTrueProperty =
DependencyProperty.Register("OnTrue", typeof(object), typeof(BooleanConverter),
new PropertyMetadata(default(object)));
public static readonly DependencyProperty OnFalseProperty =
DependencyProperty.Register("OnFalse", typeof(object), typeof(BooleanConverter),
new PropertyMetadata(default(object)));
public static readonly DependencyProperty OnNullProperty =
DependencyProperty.Register("OnNull", typeof(object), typeof(BooleanConverter),
new PropertyMetadata(default(object)));
public object OnTrue
{
get
{
return GetValue(OnTrueProperty);
}
set
{
SetValue(OnTrueProperty, value);
}
}
public object OnFalse
{
get
{
return GetValue(OnFalseProperty);
}
set
{
SetValue(OnFalseProperty, value);
}
}
public object OnNull
{
get
{
return GetValue(OnNullProperty);
}
set
{
SetValue(OnNullProperty, value);
}
}
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
return value == null
? OnNull ?? Default(targetType)
: string.Equals(value.ToString(), false.ToString(), StringComparison.CurrentCultureIgnoreCase)
? OnFalse
: OnTrue;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value == OnNull)
{
return Default(targetType);
}
if (value == OnFalse)
{
return false;
}
if (value == OnTrue)
{
return true;
}
if (value == null)
{
return null;
}
if (OnNull != null &&
string.Equals(value.ToString(), OnNull.ToString(), StringComparison.CurrentCultureIgnoreCase))
{
return Default(targetType);
}
if (OnFalse != null &&
string.Equals(value.ToString(), OnFalse.ToString(), StringComparison.CurrentCultureIgnoreCase))
{
return false;
}
if (OnTrue != null &&
string.Equals(value.ToString(), OnTrue.ToString(), StringComparison.CurrentCultureIgnoreCase))
{
return true;
}
return null;
}
public static object Default(Type type)
{
return type.IsValueType ? Activator.CreateInstance(type) : null;
}
}
}

Some files were not shown because too many files have changed in this diff Show More