├── ACEPatcher ├── Resources │ ├── placeholder.txt │ ├── patch.ico │ ├── ACEx32.dll │ ├── ACEx64.dll │ ├── 0Harmony.dll │ ├── Class_16x.png │ ├── Method_16x.png │ ├── Module_16x.png │ ├── Assembly_16x.png │ ├── DllInjector.exe │ ├── Property_16x.png │ ├── ClassFriend_16x.png │ ├── DllInjector64.exe │ ├── Namespace_16x.png │ ├── ClassPrivate_16x.png │ ├── MethodFriend_16x.png │ ├── MethodPrivate_16x.png │ ├── MethodProtect_16x.png │ ├── ClassProtected_16x.png │ └── ExtensionMethod_16x.png ├── patch.ico ├── packages.config ├── Properties │ ├── Settings.settings │ ├── Settings.Designer.cs │ ├── AssemblyInfo.cs │ ├── Resources.Designer.cs │ └── Resources.resx ├── App.config ├── Program.cs ├── PatchDialog.cs ├── Controls │ └── DarkToolStripRenderer.cs ├── ACEFiles.Designer.cs ├── PatchDialog.resx ├── MainFRM.resx ├── DotNetUtils.cs ├── PatchDialog.Designer.cs ├── ACEFiles.resx ├── ACEPatcher.csproj ├── TreeViewLoader.cs ├── Icons.Designer.cs ├── ConfigManager.cs ├── Icons.resx ├── ModuleLoader │ └── DotNetModuleLoader.cs ├── MainFRM.cs ├── MainFRM.Designer.cs └── Patcher.cs ├── AceTest ├── Class1.cs ├── Properties │ └── AssemblyInfo.cs └── AceTest.csproj ├── ACEPatcher.sln └── README.md /ACEPatcher/Resources/placeholder.txt: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /ACEPatcher/patch.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BataBo/ACEPatcher/HEAD/ACEPatcher/patch.ico -------------------------------------------------------------------------------- /ACEPatcher/Resources/patch.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BataBo/ACEPatcher/HEAD/ACEPatcher/Resources/patch.ico -------------------------------------------------------------------------------- /ACEPatcher/Resources/ACEx32.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BataBo/ACEPatcher/HEAD/ACEPatcher/Resources/ACEx32.dll -------------------------------------------------------------------------------- /ACEPatcher/Resources/ACEx64.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BataBo/ACEPatcher/HEAD/ACEPatcher/Resources/ACEx64.dll -------------------------------------------------------------------------------- /ACEPatcher/Resources/0Harmony.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BataBo/ACEPatcher/HEAD/ACEPatcher/Resources/0Harmony.dll -------------------------------------------------------------------------------- /ACEPatcher/Resources/Class_16x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BataBo/ACEPatcher/HEAD/ACEPatcher/Resources/Class_16x.png -------------------------------------------------------------------------------- /ACEPatcher/Resources/Method_16x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BataBo/ACEPatcher/HEAD/ACEPatcher/Resources/Method_16x.png -------------------------------------------------------------------------------- /ACEPatcher/Resources/Module_16x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BataBo/ACEPatcher/HEAD/ACEPatcher/Resources/Module_16x.png -------------------------------------------------------------------------------- /ACEPatcher/Resources/Assembly_16x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BataBo/ACEPatcher/HEAD/ACEPatcher/Resources/Assembly_16x.png -------------------------------------------------------------------------------- /ACEPatcher/Resources/DllInjector.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BataBo/ACEPatcher/HEAD/ACEPatcher/Resources/DllInjector.exe -------------------------------------------------------------------------------- /ACEPatcher/Resources/Property_16x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BataBo/ACEPatcher/HEAD/ACEPatcher/Resources/Property_16x.png -------------------------------------------------------------------------------- /ACEPatcher/Resources/ClassFriend_16x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BataBo/ACEPatcher/HEAD/ACEPatcher/Resources/ClassFriend_16x.png -------------------------------------------------------------------------------- /ACEPatcher/Resources/DllInjector64.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BataBo/ACEPatcher/HEAD/ACEPatcher/Resources/DllInjector64.exe -------------------------------------------------------------------------------- /ACEPatcher/Resources/Namespace_16x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BataBo/ACEPatcher/HEAD/ACEPatcher/Resources/Namespace_16x.png -------------------------------------------------------------------------------- /ACEPatcher/Resources/ClassPrivate_16x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BataBo/ACEPatcher/HEAD/ACEPatcher/Resources/ClassPrivate_16x.png -------------------------------------------------------------------------------- /ACEPatcher/Resources/MethodFriend_16x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BataBo/ACEPatcher/HEAD/ACEPatcher/Resources/MethodFriend_16x.png -------------------------------------------------------------------------------- /ACEPatcher/Resources/MethodPrivate_16x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BataBo/ACEPatcher/HEAD/ACEPatcher/Resources/MethodPrivate_16x.png -------------------------------------------------------------------------------- /ACEPatcher/Resources/MethodProtect_16x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BataBo/ACEPatcher/HEAD/ACEPatcher/Resources/MethodProtect_16x.png -------------------------------------------------------------------------------- /ACEPatcher/Resources/ClassProtected_16x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BataBo/ACEPatcher/HEAD/ACEPatcher/Resources/ClassProtected_16x.png -------------------------------------------------------------------------------- /ACEPatcher/Resources/ExtensionMethod_16x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BataBo/ACEPatcher/HEAD/ACEPatcher/Resources/ExtensionMethod_16x.png -------------------------------------------------------------------------------- /ACEPatcher/packages.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /ACEPatcher/Properties/Settings.settings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /AceTest/Class1.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Collections.Specialized; 5 | using System.IO; 6 | using System.Linq; 7 | using System.Net; 8 | using System.Security.Cryptography; 9 | using System.Security.Cryptography.X509Certificates; 10 | using System.Text; 11 | using System.Threading.Tasks; 12 | 13 | namespace AceTest 14 | { 15 | public class Program 16 | { 17 | 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /ACEPatcher/App.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /ACEPatcher/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | using System.Windows.Forms; 6 | 7 | namespace ACEPatcher 8 | { 9 | static class Program 10 | { 11 | /// 12 | /// The main entry point for the application. 13 | /// 14 | [STAThread] 15 | static void Main() 16 | { 17 | Application.EnableVisualStyles(); 18 | Application.SetCompatibleTextRenderingDefault(false); 19 | Application.Run(new MainFRM()); 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /ACEPatcher/Properties/Settings.Designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // Runtime Version:4.0.30319.42000 5 | // 6 | // Changes to this file may cause incorrect behavior and will be lost if 7 | // the code is regenerated. 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | 12 | namespace ACEPatcher.Properties 13 | { 14 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] 15 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "11.0.0.0")] 16 | internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase 17 | { 18 | 19 | private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); 20 | 21 | public static Settings Default 22 | { 23 | get 24 | { 25 | return defaultInstance; 26 | } 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /AceTest/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("AceTest")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("AceTest")] 13 | [assembly: AssemblyCopyright("Copyright © 2022")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("6699f677-f1b1-49eb-bb34-509714188027")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /ACEPatcher/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("ACEPatcher")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("ACEPatcher")] 13 | [assembly: AssemblyCopyright("Copyright © 2022")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("f7f4a377-f96f-4cb6-91f1-bcee82a8de63")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /ACEPatcher/PatchDialog.cs: -------------------------------------------------------------------------------- 1 | using dnlib.DotNet; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.ComponentModel; 5 | using System.Data; 6 | using System.Drawing; 7 | using System.Linq; 8 | using System.Text; 9 | using System.Threading.Tasks; 10 | using System.Windows.Forms; 11 | 12 | namespace ACEPatcher 13 | { 14 | public partial class PatchDialog : Form 15 | { 16 | public IMethod SelectedMethod; 17 | 18 | public PatchDialog() 19 | { 20 | InitializeComponent(); 21 | treeView1.ImageList = TreeViewLoader.Images; 22 | TreeViewLoader.FillTreeView(Patcher.patchAssembly,null, treeView1); 23 | this.Icon = Icons.patch; 24 | } 25 | 26 | private void button1_Click(object sender, EventArgs e) 27 | { 28 | if(treeView1.SelectedNode == null) 29 | { 30 | MessageBox.Show("Please select a patch method", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning); 31 | } 32 | else 33 | { 34 | if (treeView1.SelectedNode.Tag.GetType().GetInterfaces().Contains(typeof(IMethodDefOrRef))) 35 | { 36 | SelectedMethod = (IMethod)treeView1.SelectedNode.Tag; 37 | DialogResult = DialogResult.OK; 38 | Close(); 39 | } 40 | else 41 | { 42 | MessageBox.Show("Please select a valid method", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning); 43 | } 44 | } 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /ACEPatcher.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 16 4 | VisualStudioVersion = 16.0.31729.503 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ACEPatcher", "ACEPatcher\ACEPatcher.csproj", "{F7F4A377-F96F-4CB6-91F1-BCEE82A8DE63}" 7 | EndProject 8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AceTest", "AceTest\AceTest.csproj", "{6699F677-F1B1-49EB-BB34-509714188027}" 9 | EndProject 10 | Global 11 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 12 | Debug|Any CPU = Debug|Any CPU 13 | Release|Any CPU = Release|Any CPU 14 | EndGlobalSection 15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 16 | {F7F4A377-F96F-4CB6-91F1-BCEE82A8DE63}.Debug|Any CPU.ActiveCfg = Debug|x64 17 | {F7F4A377-F96F-4CB6-91F1-BCEE82A8DE63}.Debug|Any CPU.Build.0 = Debug|x64 18 | {F7F4A377-F96F-4CB6-91F1-BCEE82A8DE63}.Release|Any CPU.ActiveCfg = Release|Any CPU 19 | {F7F4A377-F96F-4CB6-91F1-BCEE82A8DE63}.Release|Any CPU.Build.0 = Release|Any CPU 20 | {6699F677-F1B1-49EB-BB34-509714188027}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 21 | {6699F677-F1B1-49EB-BB34-509714188027}.Debug|Any CPU.Build.0 = Debug|Any CPU 22 | {6699F677-F1B1-49EB-BB34-509714188027}.Release|Any CPU.ActiveCfg = Release|Any CPU 23 | {6699F677-F1B1-49EB-BB34-509714188027}.Release|Any CPU.Build.0 = Release|Any CPU 24 | EndGlobalSection 25 | GlobalSection(SolutionProperties) = preSolution 26 | HideSolutionNode = FALSE 27 | EndGlobalSection 28 | GlobalSection(ExtensibilityGlobals) = postSolution 29 | SolutionGuid = {0208B823-B731-4D3C-96B0-FCCE4E00F5B2} 30 | EndGlobalSection 31 | EndGlobal 32 | -------------------------------------------------------------------------------- /AceTest/AceTest.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {6699F677-F1B1-49EB-BB34-509714188027} 8 | Library 9 | Properties 10 | AceTest 11 | AceTest 12 | v4.7.2 13 | 512 14 | true 15 | 16 | 17 | true 18 | full 19 | false 20 | bin\Debug\ 21 | DEBUG;TRACE 22 | prompt 23 | 4 24 | 25 | 26 | pdbonly 27 | true 28 | bin\Release\ 29 | TRACE 30 | prompt 31 | 4 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | -------------------------------------------------------------------------------- /ACEPatcher/Properties/Resources.Designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // Runtime Version:4.0.30319.42000 5 | // 6 | // Changes to this file may cause incorrect behavior and will be lost if 7 | // the code is regenerated. 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | 12 | namespace ACEPatcher.Properties 13 | { 14 | /// 15 | /// A strongly-typed resource class, for looking up localized strings, etc. 16 | /// 17 | // This class was auto-generated by the StronglyTypedResourceBuilder 18 | // class via a tool like ResGen or Visual Studio. 19 | // To add or remove a member, edit your .ResX file then rerun ResGen 20 | // with the /str option, or rebuild your VS project. 21 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] 22 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 23 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] 24 | internal class Resources 25 | { 26 | 27 | private static global::System.Resources.ResourceManager resourceMan; 28 | 29 | private static global::System.Globalization.CultureInfo resourceCulture; 30 | 31 | [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] 32 | internal Resources() 33 | { 34 | } 35 | 36 | /// 37 | /// Returns the cached ResourceManager instance used by this class. 38 | /// 39 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 40 | internal static global::System.Resources.ResourceManager ResourceManager 41 | { 42 | get 43 | { 44 | if ((resourceMan == null)) 45 | { 46 | global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("ACEPatcher.Properties.Resources", typeof(Resources).Assembly); 47 | resourceMan = temp; 48 | } 49 | return resourceMan; 50 | } 51 | } 52 | 53 | /// 54 | /// Overrides the current thread's CurrentUICulture property for all 55 | /// resource lookups using this strongly typed resource class. 56 | /// 57 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 58 | internal static global::System.Globalization.CultureInfo Culture 59 | { 60 | get 61 | { 62 | return resourceCulture; 63 | } 64 | set 65 | { 66 | resourceCulture = value; 67 | } 68 | } 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /ACEPatcher/Controls/DarkToolStripRenderer.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Drawing; 3 | using System.Windows.Forms; 4 | 5 | namespace ACEPatcher.Controls 6 | { 7 | public class DarkMenuRenderer : ToolStripRenderer 8 | { 9 | #region Initialisation Region 10 | 11 | protected override void Initialize(ToolStrip toolStrip) 12 | { 13 | base.Initialize(toolStrip); 14 | 15 | toolStrip.BackColor = Color.FromArgb(27, 27, 28); 16 | toolStrip.ForeColor = Color.FromArgb(220, 220, 220); 17 | } 18 | 19 | protected override void InitializeItem(ToolStripItem item) 20 | { 21 | base.InitializeItem(item); 22 | 23 | item.BackColor = Color.FromArgb(27, 27, 28); 24 | item.ForeColor = Color.FromArgb(220, 220, 220); 25 | 26 | if (item.GetType() == typeof(ToolStripSeparator)) 27 | { 28 | item.Margin = new Padding(0, 0, 0, 0); 29 | } 30 | } 31 | 32 | #endregion 33 | 34 | #region Render Region 35 | 36 | protected override void OnRenderToolStripBackground(ToolStripRenderEventArgs e) 37 | { 38 | var g = e.Graphics; 39 | using (var b = new SolidBrush(Color.FromArgb(27, 27, 28))) 40 | { 41 | g.FillRectangle(b, e.AffectedBounds); 42 | } 43 | } 44 | 45 | protected override void OnRenderImageMargin(ToolStripRenderEventArgs e) 46 | { 47 | var g = e.Graphics; 48 | 49 | var rect = new Rectangle(0, 0, e.ToolStrip.Width - 1, e.ToolStrip.Height - 1); 50 | 51 | using (var p = new Pen(Color.FromArgb(51, 51, 51))) 52 | { 53 | g.DrawRectangle(p, rect); 54 | } 55 | } 56 | 57 | protected override void OnRenderItemCheck(ToolStripItemImageRenderEventArgs e) 58 | { 59 | var g = e.Graphics; 60 | 61 | var rect = new Rectangle(e.ImageRectangle.Left - 2, e.ImageRectangle.Top + 2, 62 | e.ImageRectangle.Width + 4, e.ImageRectangle.Height + 4); 63 | 64 | using (var b = new SolidBrush(Color.FromArgb(62, 62, 64))) 65 | { 66 | g.FillRectangle(b, rect); 67 | } 68 | 69 | using (var p = new Pen(Color.FromArgb(0, 0, 56))) 70 | { 71 | var modRect = new Rectangle(rect.Left, rect.Top, rect.Width - 1, rect.Height - 1); 72 | g.DrawRectangle(p, modRect); 73 | } 74 | 75 | } 76 | 77 | protected override void OnRenderSeparator(ToolStripSeparatorRenderEventArgs e) 78 | { 79 | /*var g = e.Graphics; 80 | 81 | var rect = new Rectangle(1, 3, e.Item.Width, 1); 82 | 83 | using (var b = new SolidBrush(Color.FromArgb(81, 81, 81))) 84 | { 85 | g.FillRectangle(b, rect); 86 | }*/ 87 | } 88 | 89 | protected override void OnRenderArrow(ToolStripArrowRenderEventArgs e) 90 | { 91 | e.ArrowColor = Color.FromArgb(220, 220, 220); 92 | e.ArrowRectangle = new Rectangle(new Point(e.ArrowRectangle.Left, e.ArrowRectangle.Top - 1), e.ArrowRectangle.Size); 93 | 94 | base.OnRenderArrow(e); 95 | } 96 | 97 | protected override void OnRenderMenuItemBackground(ToolStripItemRenderEventArgs e) 98 | { 99 | var g = e.Graphics; 100 | 101 | e.Item.ForeColor = e.Item.Enabled ? Color.FromArgb(220, 220, 220) : Color.FromArgb(153, 153, 153); 102 | 103 | if (e.Item.Enabled) 104 | { 105 | 106 | var bgColor = e.Item.Selected ? Color.FromArgb(62, 62, 64) : e.Item.BackColor; 107 | 108 | // Normal item 109 | var rect = new Rectangle(0, 0, e.Item.Width, e.Item.Height); 110 | 111 | using (var b = new SolidBrush(bgColor)) 112 | { 113 | g.FillRectangle(b, rect); 114 | } 115 | 116 | // Header item on open menu 117 | if (e.Item.GetType() == typeof(ToolStripMenuItem)) 118 | { 119 | if (((ToolStripMenuItem)e.Item).DropDown.Visible && e.Item.IsOnDropDown == false) 120 | { 121 | using (var b = new SolidBrush(Color.FromArgb(27, 27, 28))) 122 | { 123 | g.FillRectangle(b, rect); 124 | } 125 | } 126 | } 127 | } 128 | } 129 | 130 | #endregion 131 | } 132 | } 133 | -------------------------------------------------------------------------------- /ACEPatcher/ACEFiles.Designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // Runtime Version:4.0.30319.42000 5 | // 6 | // Changes to this file may cause incorrect behavior and will be lost if 7 | // the code is regenerated. 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | namespace ACEPatcher { 12 | using System; 13 | 14 | 15 | /// 16 | /// A strongly-typed resource class, for looking up localized strings, etc. 17 | /// 18 | // This class was auto-generated by the StronglyTypedResourceBuilder 19 | // class via a tool like ResGen or Visual Studio. 20 | // To add or remove a member, edit your .ResX file then rerun ResGen 21 | // with the /str option, or rebuild your VS project. 22 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")] 23 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 24 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] 25 | internal class ACEFiles { 26 | 27 | private static global::System.Resources.ResourceManager resourceMan; 28 | 29 | private static global::System.Globalization.CultureInfo resourceCulture; 30 | 31 | [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] 32 | internal ACEFiles() { 33 | } 34 | 35 | /// 36 | /// Returns the cached ResourceManager instance used by this class. 37 | /// 38 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 39 | internal static global::System.Resources.ResourceManager ResourceManager { 40 | get { 41 | if (object.ReferenceEquals(resourceMan, null)) { 42 | global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("ACEPatcher.ACEFiles", typeof(ACEFiles).Assembly); 43 | resourceMan = temp; 44 | } 45 | return resourceMan; 46 | } 47 | } 48 | 49 | /// 50 | /// Overrides the current thread's CurrentUICulture property for all 51 | /// resource lookups using this strongly typed resource class. 52 | /// 53 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 54 | internal static global::System.Globalization.CultureInfo Culture { 55 | get { 56 | return resourceCulture; 57 | } 58 | set { 59 | resourceCulture = value; 60 | } 61 | } 62 | 63 | /// 64 | /// Looks up a localized resource of type System.Byte[]. 65 | /// 66 | internal static byte[] _0Harmony { 67 | get { 68 | object obj = ResourceManager.GetObject("_0Harmony", resourceCulture); 69 | return ((byte[])(obj)); 70 | } 71 | } 72 | 73 | /// 74 | /// Looks up a localized resource of type System.Byte[]. 75 | /// 76 | internal static byte[] ACEx32 { 77 | get { 78 | object obj = ResourceManager.GetObject("ACEx32", resourceCulture); 79 | return ((byte[])(obj)); 80 | } 81 | } 82 | 83 | /// 84 | /// Looks up a localized resource of type System.Byte[]. 85 | /// 86 | internal static byte[] ACEx64 { 87 | get { 88 | object obj = ResourceManager.GetObject("ACEx64", resourceCulture); 89 | return ((byte[])(obj)); 90 | } 91 | } 92 | 93 | /// 94 | /// Looks up a localized resource of type System.Byte[]. 95 | /// 96 | internal static byte[] DllInjector { 97 | get { 98 | object obj = ResourceManager.GetObject("DllInjector", resourceCulture); 99 | return ((byte[])(obj)); 100 | } 101 | } 102 | 103 | /// 104 | /// Looks up a localized resource of type System.Byte[]. 105 | /// 106 | internal static byte[] DllInjector64 { 107 | get { 108 | object obj = ResourceManager.GetObject("DllInjector64", resourceCulture); 109 | return ((byte[])(obj)); 110 | } 111 | } 112 | } 113 | } 114 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ACEPatcher 2 | A simple to use, gui based program for patching .NET assemblies 3 | 4 | ![ACE patcher](https://i.ibb.co/wCB6pvx/Ace-Patcher.png) 5 | 6 | ## Features 7 | 8 | * Patches a wide range of methods(static methods, instance methods, constructors, getters, setters, etc.) 9 | * Works on packed assemblies 10 | * Works on a majority of obfuscators(including but not limited to:DnGuard,Eazfuscator,VMProtect,.NET reactor,Babel,Crypto Obfuscator and many more) 11 | * Easy and intuative GUI 12 | * Exports patches 13 | * Exports patches with password 14 | * Imports patches 15 | 16 | ## How to write patch methods 17 | 18 | Firstly you have to analyze the target assembly and see which methods do you want to patch, once you found the methods you want to patch open a new visual studio c# project and write patch methods after you have written patch methods compile the assembly with Release build. 19 | 20 | Patch method must be static and public. 21 | 22 | If the target method is static, the signature of the patch method must match the signature of target method: 23 | 24 | ```cs 25 | //Target method 26 | private static bool TargetMethod(string text,byte[] array) 27 | { 28 | //... 29 | } 30 | 31 | //Patch method 32 | public static bool PatchMethod(string something,byte[] somethingelse) 33 | { 34 | //... 35 | } 36 | ``` 37 | 38 | If the target method is not static, patch method must return the same type, first argument of the patch method must be type target method belongs to and the rest of the arguments are copied from the target method: 39 | 40 | ```cs 41 | //Target method 42 | class A 43 | { 44 | private int TargetMethod(string text) 45 | { 46 | //... 47 | } 48 | } 49 | 50 | //Patch method 51 | public static int PatchMethod(A instance,string text) 52 | { 53 | //... 54 | } 55 | ``` 56 | 57 | Within the patch method you can modify the return value of the TargetMethod: 58 | 59 | ```cs 60 | //Target method 61 | private static bool TargetMethod(string text) 62 | { 63 | //... 64 | } 65 | 66 | //Patch method 67 | public static bool PatchMethod(string text) 68 | { 69 | return true; 70 | } 71 | ``` 72 | 73 | You can execute the original method by calling the patch method from within itself, the values of passed parameters will be ignored to change parameters modify the values of parameters passed to patch method: 74 | 75 | ```cs 76 | //Target method 77 | private static bool TargetMethod(string text) 78 | { 79 | //... 80 | } 81 | 82 | //Patch method 83 | public static bool PatchMethod(string text) 84 | { 85 | //This will change the text parameter in the original method 86 | text = "Something else"; 87 | //This will return the execution to the original method 88 | return PatchMethod(text); 89 | } 90 | ``` 91 | 92 | Or you could do both: 93 | 94 | ```cs 95 | //Target method 96 | private static bool TargetMethod(string text) 97 | { 98 | //... 99 | } 100 | 101 | //Patch method 102 | public static bool PatchMethod(string text) 103 | { 104 | if(text.Contains("Invalid password")) 105 | return true; 106 | else 107 | return PatchMethod(text); 108 | } 109 | ``` 110 | 111 | If the method is not static you can also edit the values of fields and properties on the object associated with target method. 112 | 113 | ## How to patch assembly 114 | 115 | Once you wrote the patch methods and compiled them into a .NET assembly open ACE patcher 116 | 117 | Go to file -> open or click ctrl+o or drag n' drop target assembly onto ACE patcher. 118 | Note: if you are loading in a packed assembly you must use 32 bit ACE patcher for 32 bit assembly and 64 bit ACE patcher for 64 bit assembly. 119 | After the assembly is imported you will see it and it's dependancies in the 'Assembly Tree' panel, this panel has an interface similar to that of DnSpy. 120 | Navigate to the methods you want to patch and double click them, if this is the first patch you are making the program will ask you to load the patch assembly. 121 | A new window will appear that will list all the methods in the patch assembly, choose the one that patches the target method and then click on Add patch button. 122 | Repeat that for all the methods you want to patch and after you've patched all the methods click on the apply patches button. 123 | Then, in the result folder, move all of the files associated with the main assembly(resources ,configurations ,dll dependancies , misc files) and then click on Execute.bat to run patched version of the assembly. 124 | 125 | ## Export patch 126 | 127 | Let's say you have 5 assemblies that use the same auth provider, it would be tedious to manually patch every single one, so that is why export functionality exists to use it first patch one of the assemblies manually then go to file -> Export or click ctrl+E and the patch will be saved as file then load in the seconds assembly go to file -> Import or clicl ctrl+I to import all of the patches, these exports can also be distributed. 128 | 129 | ACE patcher also allows you to password protect patches to export password protected patch go to File -> Secure Export or click ctrl+shift+E, when you try to import password protected patch you will be asked to provide the password and you won't be able to load the patch without the correct password. 130 | 131 | ## Credits 132 | * [dnlib](https://github.com/0xd4d/dnlib) - This is used for .net assembly manipulation 133 | * [Harmony](https://github.com/pardeike/Harmony) - This is used for patching the assemblies 134 | * [JitFreezer](https://github.com/okieeee/JIT-Freezer) - This is used to deal with anti-dump when loading packed files 135 | * [DarkUI](https://github.com/RobinPerris/DarkUI) - This is used for the dark theme 136 | -------------------------------------------------------------------------------- /ACEPatcher/Properties/Resources.resx: -------------------------------------------------------------------------------- 1 | 2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | text/microsoft-resx 107 | 108 | 109 | 2.0 110 | 111 | 112 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 113 | 114 | 115 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | -------------------------------------------------------------------------------- /ACEPatcher/PatchDialog.resx: -------------------------------------------------------------------------------- 1 | 2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | text/microsoft-resx 110 | 111 | 112 | 2.0 113 | 114 | 115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | 118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 119 | 120 | -------------------------------------------------------------------------------- /ACEPatcher/MainFRM.resx: -------------------------------------------------------------------------------- 1 | 2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | text/microsoft-resx 110 | 111 | 112 | 2.0 113 | 114 | 115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | 118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 119 | 120 | 121 | 17, 17 122 | 123 | -------------------------------------------------------------------------------- /ACEPatcher/DotNetUtils.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | using System.Collections.Generic; 4 | using dnlib.DotNet; 5 | using dnlib.DotNet.Emit; 6 | using dnlib.PE; 7 | 8 | namespace ACEPatcher 9 | { 10 | 11 | public static class DotNetUtils 12 | { 13 | 14 | public static IDictionary CreateObjectToIndexDictionary(IList objs) 15 | { 16 | var dict = new Dictionary(); 17 | for (int i = 0; i < objs.Count; i++) 18 | dict[objs[i]] = i; 19 | return dict; 20 | } 21 | public static void CopyBody(MethodDef method, out IList instructions, out IList exceptionHandlers) 22 | { 23 | if (method == null || !method.HasBody) 24 | { 25 | instructions = new List(); 26 | exceptionHandlers = new List(); 27 | return; 28 | } 29 | 30 | var oldInstrs = method.Body.Instructions; 31 | var oldExHandlers = method.Body.ExceptionHandlers; 32 | instructions = new List(oldInstrs.Count); 33 | exceptionHandlers = new List(oldExHandlers.Count); 34 | var oldToIndex = CreateObjectToIndexDictionary(oldInstrs); 35 | 36 | foreach (var oldInstr in oldInstrs) 37 | instructions.Add(oldInstr.Clone()); 38 | 39 | foreach (var newInstr in instructions) 40 | { 41 | var operand = newInstr.Operand; 42 | if (operand is Instruction) 43 | newInstr.Operand = instructions[oldToIndex[(Instruction)operand]]; 44 | else if (operand is IList oldArray) 45 | { 46 | var newArray = new Instruction[oldArray.Count]; 47 | for (int i = 0; i < oldArray.Count; i++) 48 | newArray[i] = instructions[oldToIndex[oldArray[i]]]; 49 | newInstr.Operand = newArray; 50 | } 51 | } 52 | 53 | foreach (var oldEx in oldExHandlers) 54 | { 55 | var newEx = new ExceptionHandler(oldEx.HandlerType) 56 | { 57 | TryStart = GetInstruction(instructions, oldToIndex, oldEx.TryStart), 58 | TryEnd = GetInstruction(instructions, oldToIndex, oldEx.TryEnd), 59 | FilterStart = GetInstruction(instructions, oldToIndex, oldEx.FilterStart), 60 | HandlerStart = GetInstruction(instructions, oldToIndex, oldEx.HandlerStart), 61 | HandlerEnd = GetInstruction(instructions, oldToIndex, oldEx.HandlerEnd), 62 | CatchType = oldEx.CatchType, 63 | }; 64 | exceptionHandlers.Add(newEx); 65 | } 66 | } 67 | 68 | static Instruction GetInstruction(IList instructions, IDictionary instructionToIndex, Instruction instruction) 69 | { 70 | if (instruction == null) 71 | return null; 72 | return instructions[instructionToIndex[instruction]]; 73 | } 74 | 75 | public static void RestoreBody(MethodDef method, IEnumerable instructions, IEnumerable exceptionHandlers) 76 | { 77 | if (method == null || method.Body == null) 78 | return; 79 | 80 | var bodyInstrs = method.Body.Instructions; 81 | bodyInstrs.Clear(); 82 | foreach (var instr in instructions) 83 | bodyInstrs.Add(instr); 84 | 85 | var bodyExceptionHandlers = method.Body.ExceptionHandlers; 86 | bodyExceptionHandlers.Clear(); 87 | foreach (var eh in exceptionHandlers) 88 | bodyExceptionHandlers.Add(eh); 89 | } 90 | 91 | public static void CopyBodyFromTo(MethodDef fromMethod, MethodDef toMethod) 92 | { 93 | if (fromMethod == toMethod) 94 | return; 95 | 96 | CopyBody(fromMethod, out var instructions, out var exceptionHandlers); 97 | RestoreBody(toMethod, instructions, exceptionHandlers); 98 | CopyLocalsFromTo(fromMethod, toMethod); 99 | UpdateInstructionOperands(fromMethod, toMethod); 100 | } 101 | 102 | static void CopyLocalsFromTo(MethodDef fromMethod, MethodDef toMethod) 103 | { 104 | var fromBody = fromMethod.Body; 105 | var toBody = toMethod.Body; 106 | 107 | toBody.Variables.Clear(); 108 | foreach (var local in fromBody.Variables) 109 | toBody.Variables.Add(new Local(local.Type)); 110 | } 111 | 112 | static void UpdateInstructionOperands(MethodDef fromMethod, MethodDef toMethod) 113 | { 114 | var fromBody = fromMethod.Body; 115 | var toBody = toMethod.Body; 116 | 117 | toBody.InitLocals = fromBody.InitLocals; 118 | toBody.MaxStack = fromBody.MaxStack; 119 | 120 | var newOperands = new Dictionary(); 121 | var fromParams = fromMethod.Parameters; 122 | var toParams = toMethod.Parameters; 123 | for (int i = 0; i < fromParams.Count; i++) 124 | newOperands[fromParams[i]] = toParams[i]; 125 | for (int i = 0; i < fromBody.Variables.Count; i++) 126 | newOperands[fromBody.Variables[i]] = toBody.Variables[i]; 127 | 128 | foreach (var instr in toBody.Instructions) 129 | { 130 | if (instr.Operand == null) 131 | continue; 132 | if (newOperands.TryGetValue(instr.Operand, out object newOperand)) 133 | instr.Operand = newOperand; 134 | } 135 | } 136 | 137 | public static int ReplaceInstruction(IList instructions, Instruction instruction,params Instruction[] replacement) 138 | { 139 | int index = instructions.IndexOf(instruction); 140 | if (replacement.Length == 0) 141 | return 0; 142 | else if(replacement.Length == 1) 143 | { 144 | instructions[index].OpCode = replacement[0].OpCode; 145 | instructions[index].Operand = replacement[0].Operand; 146 | return 1; 147 | } 148 | else 149 | { 150 | instructions[index].OpCode = replacement[0].OpCode; 151 | instructions[index].Operand = replacement[0].Operand; 152 | ((List)instructions).InsertRange(index+1, replacement.Skip(1).ToArray()); 153 | return replacement.Length; 154 | } 155 | } 156 | 157 | public static MethodDef findMethodByName(ModuleDefMD[] dependancies,string moduleName,string methodName) 158 | { 159 | ModuleDefMD module = dependancies.Where(x => x.Assembly.FullName == moduleName).First(); 160 | foreach(TypeDef type in module.Types) 161 | { 162 | foreach(MethodDef method in type.Methods) 163 | { 164 | if (method.FullName == methodName) 165 | return method; 166 | } 167 | } 168 | throw new KeyNotFoundException(); 169 | } 170 | 171 | public static byte[] ReadAssembly(ModuleDefMD module) 172 | { 173 | IPEImage image = module.Metadata.PEImage; 174 | var Reader = image.CreateReader(); 175 | return Reader.ReadBytes((int)Reader.Length); 176 | } 177 | 178 | } 179 | } -------------------------------------------------------------------------------- /ACEPatcher/PatchDialog.Designer.cs: -------------------------------------------------------------------------------- 1 | 2 | namespace ACEPatcher 3 | { 4 | partial class PatchDialog 5 | { 6 | /// 7 | /// Required designer variable. 8 | /// 9 | private System.ComponentModel.IContainer components = null; 10 | 11 | /// 12 | /// Clean up any resources being used. 13 | /// 14 | /// true if managed resources should be disposed; otherwise, false. 15 | protected override void Dispose(bool disposing) 16 | { 17 | if (disposing && (components != null)) 18 | { 19 | components.Dispose(); 20 | } 21 | base.Dispose(disposing); 22 | } 23 | 24 | #region Windows Form Designer generated code 25 | 26 | /// 27 | /// Required method for Designer support - do not modify 28 | /// the contents of this method with the code editor. 29 | /// 30 | private void InitializeComponent() 31 | { 32 | this.label1 = new System.Windows.Forms.Label(); 33 | this.tableLayoutPanel1 = new System.Windows.Forms.TableLayoutPanel(); 34 | this.treeView1 = new System.Windows.Forms.TreeView(); 35 | this.button1 = new System.Windows.Forms.Button(); 36 | this.tableLayoutPanel1.SuspendLayout(); 37 | this.SuspendLayout(); 38 | // 39 | // label1 40 | // 41 | this.label1.AutoSize = true; 42 | this.label1.Dock = System.Windows.Forms.DockStyle.Left; 43 | this.label1.Font = new System.Drawing.Font("Arial", 11.90083F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); 44 | this.label1.ForeColor = System.Drawing.Color.White; 45 | this.label1.Location = new System.Drawing.Point(3, 0); 46 | this.label1.Name = "label1"; 47 | this.label1.Size = new System.Drawing.Size(220, 45); 48 | this.label1.TabIndex = 0; 49 | this.label1.Text = "Choose patch method:"; 50 | this.label1.TextAlign = System.Drawing.ContentAlignment.MiddleLeft; 51 | // 52 | // tableLayoutPanel1 53 | // 54 | this.tableLayoutPanel1.ColumnCount = 1; 55 | this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F)); 56 | this.tableLayoutPanel1.Controls.Add(this.label1, 0, 0); 57 | this.tableLayoutPanel1.Controls.Add(this.treeView1, 0, 1); 58 | this.tableLayoutPanel1.Controls.Add(this.button1, 0, 2); 59 | this.tableLayoutPanel1.Dock = System.Windows.Forms.DockStyle.Fill; 60 | this.tableLayoutPanel1.Location = new System.Drawing.Point(0, 0); 61 | this.tableLayoutPanel1.Name = "tableLayoutPanel1"; 62 | this.tableLayoutPanel1.RowCount = 3; 63 | this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 10F)); 64 | this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 80F)); 65 | this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 10F)); 66 | this.tableLayoutPanel1.Size = new System.Drawing.Size(800, 450); 67 | this.tableLayoutPanel1.TabIndex = 1; 68 | // 69 | // treeView1 70 | // 71 | this.treeView1.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(37)))), ((int)(((byte)(37)))), ((int)(((byte)(38))))); 72 | this.treeView1.Dock = System.Windows.Forms.DockStyle.Fill; 73 | this.treeView1.Location = new System.Drawing.Point(3, 48); 74 | this.treeView1.Name = "treeView1"; 75 | this.treeView1.Size = new System.Drawing.Size(794, 354); 76 | this.treeView1.TabIndex = 1; 77 | // 78 | // button1 79 | // 80 | this.button1.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(63)))), ((int)(((byte)(63)))), ((int)(((byte)(70))))); 81 | this.button1.Cursor = System.Windows.Forms.Cursors.Hand; 82 | this.button1.Dock = System.Windows.Forms.DockStyle.Right; 83 | this.button1.FlatAppearance.BorderColor = System.Drawing.Color.FromArgb(((int)(((byte)(85)))), ((int)(((byte)(85)))), ((int)(((byte)(85))))); 84 | this.button1.FlatAppearance.BorderSize = 2; 85 | this.button1.FlatAppearance.MouseDownBackColor = System.Drawing.Color.FromArgb(((int)(((byte)(0)))), ((int)(((byte)(122)))), ((int)(((byte)(204))))); 86 | this.button1.FlatAppearance.MouseOverBackColor = System.Drawing.Color.FromArgb(((int)(((byte)(0)))), ((int)(((byte)(102)))), ((int)(((byte)(204))))); 87 | this.button1.FlatStyle = System.Windows.Forms.FlatStyle.Flat; 88 | this.button1.ForeColor = System.Drawing.SystemColors.ButtonHighlight; 89 | this.button1.Location = new System.Drawing.Point(638, 408); 90 | this.button1.Name = "button1"; 91 | this.button1.Size = new System.Drawing.Size(159, 39); 92 | this.button1.TabIndex = 2; 93 | this.button1.Text = "Add Patch"; 94 | this.button1.UseVisualStyleBackColor = false; 95 | this.button1.Click += new System.EventHandler(this.button1_Click); 96 | // 97 | // PatchDialog 98 | // 99 | this.AutoScaleDimensions = new System.Drawing.SizeF(8F, 16F); 100 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; 101 | this.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(45)))), ((int)(((byte)(45)))), ((int)(((byte)(48))))); 102 | this.ClientSize = new System.Drawing.Size(800, 450); 103 | this.Controls.Add(this.tableLayoutPanel1); 104 | this.Name = "PatchDialog"; 105 | this.Text = "PatchDialog"; 106 | this.tableLayoutPanel1.ResumeLayout(false); 107 | this.tableLayoutPanel1.PerformLayout(); 108 | this.ResumeLayout(false); 109 | 110 | } 111 | 112 | #endregion 113 | 114 | private System.Windows.Forms.Label label1; 115 | private System.Windows.Forms.TableLayoutPanel tableLayoutPanel1; 116 | private System.Windows.Forms.TreeView treeView1; 117 | private System.Windows.Forms.Button button1; 118 | } 119 | } -------------------------------------------------------------------------------- /ACEPatcher/ACEFiles.resx: -------------------------------------------------------------------------------- 1 | 2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | text/microsoft-resx 110 | 111 | 112 | 2.0 113 | 114 | 115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | 118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 119 | 120 | 121 | 122 | Resources\ACEx32.dll;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 123 | 124 | 125 | Resources\ACEx64.dll;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 126 | 127 | 128 | Resources\DllInjector.exe;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 129 | 130 | 131 | Resources\DllInjector64.exe;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 132 | 133 | 134 | Resources\0Harmony.dll;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 135 | 136 | -------------------------------------------------------------------------------- /ACEPatcher/ACEPatcher.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {F7F4A377-F96F-4CB6-91F1-BCEE82A8DE63} 8 | WinExe 9 | ACEPatcher 10 | ACEPatcher 11 | v4.8 12 | 512 13 | true 14 | true 15 | 16 | 17 | AnyCPU 18 | true 19 | full 20 | false 21 | bin\Debug\ 22 | DEBUG;TRACE 23 | prompt 24 | 4 25 | true 26 | 27 | 28 | AnyCPU 29 | pdbonly 30 | true 31 | bin\Release\ 32 | TRACE 33 | prompt 34 | 4 35 | true 36 | 37 | 38 | true 39 | bin\x64\Debug\ 40 | DEBUG;TRACE 41 | true 42 | full 43 | x64 44 | 7.3 45 | prompt 46 | true 47 | 48 | 49 | bin\x64\Release\ 50 | TRACE 51 | true 52 | true 53 | pdbonly 54 | x64 55 | 7.3 56 | prompt 57 | true 58 | 59 | 60 | patch.ico 61 | 62 | 63 | 64 | ..\packages\dnlib.3.5.0\lib\net45\dnlib.dll 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | True 82 | True 83 | ACEFiles.resx 84 | 85 | 86 | 87 | 88 | 89 | Form 90 | 91 | 92 | MainFRM.cs 93 | 94 | 95 | True 96 | True 97 | Icons.resx 98 | 99 | 100 | 101 | Form 102 | 103 | 104 | PatchDialog.cs 105 | 106 | 107 | 108 | 109 | 110 | 111 | ResXFileCodeGenerator 112 | ACEFiles.Designer.cs 113 | 114 | 115 | MainFRM.cs 116 | 117 | 118 | ResXFileCodeGenerator 119 | Icons.Designer.cs 120 | 121 | 122 | PatchDialog.cs 123 | 124 | 125 | ResXFileCodeGenerator 126 | Resources.Designer.cs 127 | Designer 128 | 129 | 130 | True 131 | Resources.resx 132 | 133 | 134 | 135 | SettingsSingleFileGenerator 136 | Settings.Designer.cs 137 | 138 | 139 | True 140 | Settings.settings 141 | True 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | -------------------------------------------------------------------------------- /ACEPatcher/TreeViewLoader.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using dnlib.DotNet; 7 | using System.Windows.Forms; 8 | using System.Drawing; 9 | 10 | namespace ACEPatcher 11 | { 12 | class TreeViewLoader 13 | { 14 | public static Dictionary ResourceMap; 15 | public static ImageList Images; 16 | private static TreeNode[] ListNamespaces(ModuleDef module) 17 | { 18 | List namespaces = new List(); 19 | namespaces.Add(new TreeNode("", ResourceMap["Namespace"], ResourceMap["Namespace"]) { ForeColor = Color.FromArgb(255, 215, 15) }); 20 | foreach (TypeDef def in module.Types) 21 | { 22 | string ns = def.Namespace.String; 23 | if (namespaces.Where(x => x.Text == ns).Count() == 0) 24 | namespaces.Add(new TreeNode(ns,ResourceMap["Namespace"], ResourceMap["Namespace"]) { ForeColor = Color.FromArgb(255, 215, 15) }); 25 | } 26 | return namespaces.ToArray(); 27 | } 28 | 29 | public static void FillTreeView(ModuleDefMD module,ModuleDefMD[] dependancies,TreeView treeView,bool AddDependancies = false) 30 | { 31 | AddThisAssemblyToTree(module, treeView); 32 | if (AddDependancies) 33 | { 34 | foreach(ModuleDefMD dependancy in dependancies) 35 | { 36 | AddThisAssemblyToTree(dependancy, treeView); 37 | } 38 | } 39 | } 40 | 41 | 42 | private static void AddThisAssemblyToTree(ModuleDefMD module, TreeView treeView) 43 | { 44 | TreeNode root = new TreeNode(module.Assembly.Name, ResourceMap["Assembly"], ResourceMap["Assembly"]) { ForeColor = Color.FromArgb(219, 179, 126), Tag = module.Assembly }; 45 | foreach (ModuleDef AssemblyModule in module.Assembly.Modules) 46 | { 47 | TreeNode moduleNode = new TreeNode(AssemblyModule.Name, ResourceMap["Module"], ResourceMap["Module"]) { ForeColor = Color.FromArgb(177, 127, 216), Tag = AssemblyModule }; 48 | TreeNode[] namespaces = ListNamespaces(AssemblyModule); 49 | namespaces = namespaces.OrderBy(x => x.Text).ToArray(); 50 | List types = AssemblyModule.Types.ToList(); 51 | types.Sort((x, y) => { return x.Name.CompareTo(y.Name); }); 52 | foreach (TypeDef type in types) 53 | { 54 | ProcessType(namespaces.Where(x => x.Text == type.Namespace.String).First(), type); 55 | } 56 | namespaces[0].Name = "-"; 57 | foreach (TreeNode ns in namespaces) 58 | moduleNode.Nodes.Add(ns); 59 | root.Nodes.Add(moduleNode); 60 | } 61 | treeView.Nodes.Add(root); 62 | } 63 | 64 | private static void ProcessType(TreeNode ParentNode,TypeDef type) 65 | { 66 | if (type.HasGenericParameters || type.IsInterface || type.IsEnum || type.IsDelegate) 67 | return; 68 | TreeNode node = new TreeNode(type.Name) {Tag = type }; 69 | if (type.IsNestedPrivate) 70 | { 71 | node.ImageIndex = ResourceMap["ClassPrivate"]; 72 | node.SelectedImageIndex = ResourceMap["ClassPrivate"]; 73 | } 74 | else if (type.IsNestedFamily) 75 | { 76 | node.ImageIndex = ResourceMap["ClassProtected"]; 77 | node.SelectedImageIndex = ResourceMap["ClassProtected"]; 78 | } 79 | else if (type.Visibility == TypeAttributes.NotPublic || type.IsNestedAssembly || type.IsNestedFamilyAndAssembly || type.IsNestedFamilyOrAssembly) 80 | { 81 | node.ImageIndex = ResourceMap["ClassFriend"]; 82 | node.SelectedImageIndex = ResourceMap["ClassFriend"]; 83 | } 84 | else 85 | { 86 | node.ImageIndex = ResourceMap["Class"]; 87 | node.SelectedImageIndex = ResourceMap["Class"]; 88 | } 89 | if (type.IsAbstract) 90 | node.ForeColor = Color.FromArgb(55, 141, 108); 91 | else 92 | node.ForeColor = Color.FromArgb(78,201,176); 93 | 94 | foreach(MethodDef m in type.FindConstructors()) 95 | { 96 | ProccessMethod(node, m); 97 | } 98 | List methods = type.Methods.ToList(); 99 | methods.Sort((x,y) => { return FormatMethod(x).CompareTo(FormatMethod(y)); }); 100 | foreach(MethodDef method in methods) 101 | { 102 | if(!(method.IsGetter || method.IsSetter) && !method.IsConstructor) 103 | ProccessMethod(node, method); 104 | } 105 | List properties = type.Properties.ToList(); 106 | properties.Sort((x, y) => { return x.Name.CompareTo(y.Name); }); 107 | foreach (PropertyDef property in properties) 108 | { 109 | ProccessProperty(node, property); 110 | } 111 | List NestedTypes = type.NestedTypes.ToList(); 112 | NestedTypes.Sort((x, y) => { return x.Name.CompareTo(y.Name); }); 113 | foreach (TypeDef NestedType in NestedTypes) 114 | { 115 | ProcessType(node, NestedType); 116 | } 117 | ParentNode.Nodes.Add(node); 118 | } 119 | 120 | private static void ProccessProperty(TreeNode ParentNode,PropertyDef property) 121 | { 122 | TreeNode node = new TreeNode(property.Name, ResourceMap["Property"], ResourceMap["Property"]) {Tag = property }; 123 | node.ForeColor = Color.FromArgb(36,143,143); 124 | if (property.GetMethod != null) 125 | ProccessMethod(node, property.GetMethod); 126 | if(property.SetMethod != null) 127 | ProccessMethod(node, property.SetMethod); 128 | ParentNode.Nodes.Add(node); 129 | } 130 | 131 | private static void ProccessMethod(TreeNode ParentNode,MethodDef method) 132 | { 133 | if (method.IsAbstract || method.HasGenericParameters) 134 | return; 135 | TreeNode node = new TreeNode(FormatMethod(method)) {Tag = method }; 136 | if (method.IsInternalCall) 137 | { 138 | node.ImageIndex = ResourceMap["MethodFriend"]; 139 | node.SelectedImageIndex = ResourceMap["MethodFriend"]; 140 | } 141 | else if (method.IsPrivate) 142 | { 143 | node.ImageIndex = ResourceMap["MethodPrivate"]; 144 | node.SelectedImageIndex = ResourceMap["MethodPrivate"]; 145 | } 146 | else if (method.IsPublic) 147 | { 148 | node.ImageIndex = ResourceMap["Method"]; 149 | node.SelectedImageIndex = ResourceMap["Method"]; 150 | } 151 | if (method.IsConstructor) 152 | { 153 | node.ForeColor = ParentNode.ForeColor; 154 | } 155 | else 156 | { 157 | node.ForeColor = Color.FromArgb(230,155,0); 158 | } 159 | ParentNode.Nodes.Add(node); 160 | } 161 | 162 | private static string FormatMethod(MethodDef method) 163 | { 164 | string name = (method.IsInstanceConstructor ? method.DeclaringType.Name : method.Name) + "("; 165 | List parameters = new List(); 166 | List parameters1 = method.Parameters.ToList(); 167 | if (method.HasThis) 168 | { 169 | parameters1.RemoveAt(0); 170 | } 171 | foreach(Parameter param in parameters1) 172 | { 173 | parameters.Add(param.Type.TypeName); 174 | } 175 | name += string.Join(",", parameters) + ") : " + method.ReturnType.TypeName; 176 | return name; 177 | } 178 | 179 | private static string FormatMethod(MemberRef method) 180 | { 181 | string name = (method.Name == ".ctor" ? method.DeclaringType.Name : method.Name) + "("; 182 | List parameters = new List(); 183 | foreach (TypeSig param in method.MethodSig.GetParams()) 184 | { 185 | parameters.Add(param.TypeName); 186 | } 187 | name += string.Join(",", parameters) + ") : " + method.ReturnType.TypeName; 188 | return name; 189 | } 190 | } 191 | } 192 | -------------------------------------------------------------------------------- /ACEPatcher/Icons.Designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // Runtime Version:4.0.30319.42000 5 | // 6 | // Changes to this file may cause incorrect behavior and will be lost if 7 | // the code is regenerated. 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | namespace ACEPatcher { 12 | using System; 13 | 14 | 15 | /// 16 | /// A strongly-typed resource class, for looking up localized strings, etc. 17 | /// 18 | // This class was auto-generated by the StronglyTypedResourceBuilder 19 | // class via a tool like ResGen or Visual Studio. 20 | // To add or remove a member, edit your .ResX file then rerun ResGen 21 | // with the /str option, or rebuild your VS project. 22 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")] 23 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 24 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] 25 | internal class Icons { 26 | 27 | private static global::System.Resources.ResourceManager resourceMan; 28 | 29 | private static global::System.Globalization.CultureInfo resourceCulture; 30 | 31 | [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] 32 | internal Icons() { 33 | } 34 | 35 | /// 36 | /// Returns the cached ResourceManager instance used by this class. 37 | /// 38 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 39 | internal static global::System.Resources.ResourceManager ResourceManager { 40 | get { 41 | if (object.ReferenceEquals(resourceMan, null)) { 42 | global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("ACEPatcher.Icons", typeof(Icons).Assembly); 43 | resourceMan = temp; 44 | } 45 | return resourceMan; 46 | } 47 | } 48 | 49 | /// 50 | /// Overrides the current thread's CurrentUICulture property for all 51 | /// resource lookups using this strongly typed resource class. 52 | /// 53 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 54 | internal static global::System.Globalization.CultureInfo Culture { 55 | get { 56 | return resourceCulture; 57 | } 58 | set { 59 | resourceCulture = value; 60 | } 61 | } 62 | 63 | /// 64 | /// Looks up a localized resource of type System.Drawing.Bitmap. 65 | /// 66 | internal static System.Drawing.Bitmap Assembly_16x { 67 | get { 68 | object obj = ResourceManager.GetObject("Assembly_16x", resourceCulture); 69 | return ((System.Drawing.Bitmap)(obj)); 70 | } 71 | } 72 | 73 | /// 74 | /// Looks up a localized resource of type System.Drawing.Bitmap. 75 | /// 76 | internal static System.Drawing.Bitmap Class_16x { 77 | get { 78 | object obj = ResourceManager.GetObject("Class_16x", resourceCulture); 79 | return ((System.Drawing.Bitmap)(obj)); 80 | } 81 | } 82 | 83 | /// 84 | /// Looks up a localized resource of type System.Drawing.Bitmap. 85 | /// 86 | internal static System.Drawing.Bitmap ClassFriend_16x { 87 | get { 88 | object obj = ResourceManager.GetObject("ClassFriend_16x", resourceCulture); 89 | return ((System.Drawing.Bitmap)(obj)); 90 | } 91 | } 92 | 93 | /// 94 | /// Looks up a localized resource of type System.Drawing.Bitmap. 95 | /// 96 | internal static System.Drawing.Bitmap ClassPrivate_16x { 97 | get { 98 | object obj = ResourceManager.GetObject("ClassPrivate_16x", resourceCulture); 99 | return ((System.Drawing.Bitmap)(obj)); 100 | } 101 | } 102 | 103 | /// 104 | /// Looks up a localized resource of type System.Drawing.Bitmap. 105 | /// 106 | internal static System.Drawing.Bitmap ClassProtected_16x { 107 | get { 108 | object obj = ResourceManager.GetObject("ClassProtected_16x", resourceCulture); 109 | return ((System.Drawing.Bitmap)(obj)); 110 | } 111 | } 112 | 113 | /// 114 | /// Looks up a localized resource of type System.Drawing.Bitmap. 115 | /// 116 | internal static System.Drawing.Bitmap ExtensionMethod_16x { 117 | get { 118 | object obj = ResourceManager.GetObject("ExtensionMethod_16x", resourceCulture); 119 | return ((System.Drawing.Bitmap)(obj)); 120 | } 121 | } 122 | 123 | /// 124 | /// Looks up a localized resource of type System.Drawing.Bitmap. 125 | /// 126 | internal static System.Drawing.Bitmap Method_16x { 127 | get { 128 | object obj = ResourceManager.GetObject("Method_16x", resourceCulture); 129 | return ((System.Drawing.Bitmap)(obj)); 130 | } 131 | } 132 | 133 | /// 134 | /// Looks up a localized resource of type System.Drawing.Bitmap. 135 | /// 136 | internal static System.Drawing.Bitmap MethodFriend_16x { 137 | get { 138 | object obj = ResourceManager.GetObject("MethodFriend_16x", resourceCulture); 139 | return ((System.Drawing.Bitmap)(obj)); 140 | } 141 | } 142 | 143 | /// 144 | /// Looks up a localized resource of type System.Drawing.Bitmap. 145 | /// 146 | internal static System.Drawing.Bitmap MethodPrivate_16x { 147 | get { 148 | object obj = ResourceManager.GetObject("MethodPrivate_16x", resourceCulture); 149 | return ((System.Drawing.Bitmap)(obj)); 150 | } 151 | } 152 | 153 | /// 154 | /// Looks up a localized resource of type System.Drawing.Bitmap. 155 | /// 156 | internal static System.Drawing.Bitmap MethodProtect_16x { 157 | get { 158 | object obj = ResourceManager.GetObject("MethodProtect_16x", resourceCulture); 159 | return ((System.Drawing.Bitmap)(obj)); 160 | } 161 | } 162 | 163 | /// 164 | /// Looks up a localized resource of type System.Drawing.Bitmap. 165 | /// 166 | internal static System.Drawing.Bitmap Module_16x { 167 | get { 168 | object obj = ResourceManager.GetObject("Module_16x", resourceCulture); 169 | return ((System.Drawing.Bitmap)(obj)); 170 | } 171 | } 172 | 173 | /// 174 | /// Looks up a localized resource of type System.Drawing.Bitmap. 175 | /// 176 | internal static System.Drawing.Bitmap Namespace_16x { 177 | get { 178 | object obj = ResourceManager.GetObject("Namespace_16x", resourceCulture); 179 | return ((System.Drawing.Bitmap)(obj)); 180 | } 181 | } 182 | 183 | /// 184 | /// Looks up a localized resource of type System.Drawing.Icon similar to (Icon). 185 | /// 186 | internal static System.Drawing.Icon patch { 187 | get { 188 | object obj = ResourceManager.GetObject("patch", resourceCulture); 189 | return ((System.Drawing.Icon)(obj)); 190 | } 191 | } 192 | 193 | /// 194 | /// Looks up a localized resource of type System.Drawing.Bitmap. 195 | /// 196 | internal static System.Drawing.Bitmap Property_16x { 197 | get { 198 | object obj = ResourceManager.GetObject("Property_16x", resourceCulture); 199 | return ((System.Drawing.Bitmap)(obj)); 200 | } 201 | } 202 | } 203 | } 204 | -------------------------------------------------------------------------------- /ACEPatcher/ConfigManager.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.IO.Compression; 5 | using System.Linq; 6 | using System.Security.Cryptography; 7 | using System.Text; 8 | using System.Threading.Tasks; 9 | using dnlib.DotNet; 10 | using System.Windows.Forms; 11 | using dnlib.PE; 12 | 13 | namespace ACEPatcher 14 | { 15 | class ConfigManager 16 | { 17 | 18 | public static void ExportConfig(ModuleDefMD mainAssembly,string path,bool Secure,string password = null) 19 | { 20 | foreach(KeyValuePair patch in Patcher.patchList) 21 | { 22 | if(((MethodDef)patch.Key).Module.Assembly.FullName == mainAssembly.Assembly.FullName) 23 | { 24 | MessageBox.Show("These patches are only applicable to the assembly in question and thus cannot be exported","Error",MessageBoxButtons.OK,MessageBoxIcon.Error); 25 | return; 26 | } 27 | } 28 | byte[] content; 29 | using(MemoryStream stream = new MemoryStream()) 30 | { 31 | using(BinaryWriter writer = new BinaryWriter(stream)) 32 | { 33 | writer.Write((ushort)Patcher.patchList.Count); 34 | foreach(KeyValuePair patch in Patcher.patchList) 35 | { 36 | writer.Write(patch.Key.DeclaringType.DefinitionAssembly.FullName); 37 | writer.Write('\0'); 38 | writer.Write(patch.Key.FullName); 39 | writer.Write('\0'); 40 | writer.Write(patch.Value.DeclaringType.DefinitionAssembly.FullName); 41 | writer.Write('\0'); 42 | writer.Write(patch.Value.FullName); 43 | writer.Write('\0'); 44 | } 45 | writer.Write(DotNetUtils.ReadAssembly(Patcher.patchAssembly)); 46 | } 47 | content = Compress(stream.ToArray()); 48 | if (Secure) 49 | { 50 | content = Encrypt(content, password); 51 | } 52 | } 53 | File.WriteAllBytes(path,content.Prepend(Secure ? (byte)1 : (byte)0).ToArray()); 54 | } 55 | 56 | 57 | public static void ImportConfig(ModuleDefMD[] dependancies,string path) 58 | { 59 | byte[] config = File.ReadAllBytes(path); 60 | byte magic = config[0]; 61 | config = config.Skip(1).ToArray(); 62 | if(magic == 1) 63 | { 64 | string password = null; 65 | if (MainFRM.InputBox("Password", "Type in password:", ref password) == DialogResult.OK) 66 | { 67 | try 68 | { 69 | config = Decrypt(config, password); 70 | } 71 | catch 72 | { 73 | MessageBox.Show("Invalid password", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); 74 | return; 75 | } 76 | } 77 | else 78 | return; 79 | } 80 | try 81 | { 82 | config = Decompress(config); 83 | } 84 | catch 85 | { 86 | MessageBox.Show("Invalid patch", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); 87 | return; 88 | } 89 | using (MemoryStream stream = new MemoryStream(config)) 90 | { 91 | using (BinaryReader reader = new BinaryReader(stream)) 92 | { 93 | ushort patchNo = reader.ReadUInt16(); 94 | KeyValuePair[] pairs = new KeyValuePair[patchNo*2]; 95 | for(int i = 0; i < patchNo * 2; i+=2) 96 | { 97 | string _1 = reader.ReadString(); 98 | reader.ReadByte(); 99 | string _2 = reader.ReadString(); 100 | reader.ReadByte(); 101 | pairs[i] = new KeyValuePair(_1, _2); 102 | _1 = reader.ReadString(); 103 | reader.ReadByte(); 104 | _2 = reader.ReadString(); 105 | reader.ReadByte(); 106 | pairs[i+1] = new KeyValuePair(_1, _2); 107 | } 108 | for(int i = 0;i x.Assembly.FullName == pairs[i].Key).Count() == 0) 111 | { 112 | MessageBox.Show("Assembly " + pairs[i].Key + " is missing", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); 113 | return; 114 | } 115 | } 116 | byte[] PatchAssembly = new byte[stream.Length - stream.Position]; 117 | reader.Read(PatchAssembly, 0, (int)(stream.Length - stream.Position)); 118 | Patcher.patchAssembly = ModuleDefMD.Load(PatchAssembly); 119 | for(int i = 0; i < pairs.Length; i += 2) 120 | { 121 | Patcher.patchList.Add(DotNetUtils.findMethodByName(dependancies,pairs[i].Key,pairs[i].Value), DotNetUtils.findMethodByName(dependancies.Prepend(Patcher.patchAssembly).ToArray(), pairs[i+1].Key, pairs[i+1].Value)); 122 | } 123 | } 124 | } 125 | MessageBox.Show("Config succesfully imported", "Information", MessageBoxButtons.OK, MessageBoxIcon.Information); 126 | 127 | } 128 | 129 | 130 | static byte[] Compress(byte[] data) 131 | { 132 | byte[] compressArray = null; 133 | using (MemoryStream memoryStream = new MemoryStream()) 134 | { 135 | using (GZipStream deflateStream = new GZipStream(memoryStream, CompressionMode.Compress)) 136 | { 137 | deflateStream.Write(data, 0, data.Length); 138 | } 139 | compressArray = memoryStream.ToArray(); 140 | } 141 | return compressArray; 142 | } 143 | 144 | static byte[] Decompress(byte[] data) 145 | { 146 | using (GZipStream stream = new GZipStream(new MemoryStream(data), CompressionMode.Decompress)) 147 | { 148 | byte[] buffer = new byte[4096]; 149 | using (MemoryStream memory = new MemoryStream()) 150 | { 151 | int count = 0; 152 | do 153 | { 154 | count = stream.Read(buffer, 0, 4096); 155 | if (count > 0) 156 | { 157 | memory.Write(buffer, 0, count); 158 | } 159 | } 160 | while (count > 0); 161 | return memory.ToArray(); 162 | } 163 | } 164 | } 165 | 166 | static byte[] Encrypt(byte[] data,string password) 167 | { 168 | byte[] result; 169 | SHA256Managed sha256 = new SHA256Managed(); 170 | byte[] hash = sha256.ComputeHash(Encoding.UTF8.GetBytes(password)); 171 | AesManaged aes = new AesManaged(); 172 | ICryptoTransform encryptor = aes.CreateEncryptor(hash.Take(16).ToArray(), hash.Skip(16).Take(16).ToArray()); 173 | using (MemoryStream ms = new MemoryStream()) 174 | { 175 | using (CryptoStream cs = new CryptoStream(ms, encryptor, CryptoStreamMode.Write)) 176 | { 177 | using (BinaryWriter sw = new BinaryWriter(cs)) 178 | sw.Write(data); 179 | result = ms.ToArray(); 180 | } 181 | } 182 | return result; 183 | } 184 | 185 | static byte[] Decrypt(byte[] data, string password) 186 | { 187 | byte[] result; 188 | SHA256Managed sha256 = new SHA256Managed(); 189 | byte[] hash = sha256.ComputeHash(Encoding.UTF8.GetBytes(password)); 190 | AesManaged aes = new AesManaged(); 191 | ICryptoTransform decryptor = aes.CreateDecryptor(hash.Take(16).ToArray(), hash.Skip(16).Take(16).ToArray()); 192 | using (MemoryStream ms = new MemoryStream()) 193 | { 194 | using (CryptoStream cs = new CryptoStream(ms, decryptor, CryptoStreamMode.Write)) 195 | { 196 | using (BinaryWriter sw = new BinaryWriter(cs)) 197 | sw.Write(data); 198 | result = ms.ToArray(); 199 | } 200 | } 201 | return result; 202 | } 203 | 204 | } 205 | } 206 | -------------------------------------------------------------------------------- /ACEPatcher/Icons.resx: -------------------------------------------------------------------------------- 1 | 2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | text/microsoft-resx 110 | 111 | 112 | 2.0 113 | 114 | 115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | 118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 119 | 120 | 121 | 122 | Resources\Assembly_16x.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a 123 | 124 | 125 | Resources\ClassFriend_16x.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a 126 | 127 | 128 | Resources\ClassPrivate_16x.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a 129 | 130 | 131 | Resources\ClassProtected_16x.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a 132 | 133 | 134 | Resources\Class_16x.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a 135 | 136 | 137 | Resources\ExtensionMethod_16x.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a 138 | 139 | 140 | Resources\MethodFriend_16x.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a 141 | 142 | 143 | Resources\MethodPrivate_16x.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a 144 | 145 | 146 | Resources\MethodProtect_16x.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a 147 | 148 | 149 | Resources\Method_16x.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a 150 | 151 | 152 | Resources\Module_16x.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a 153 | 154 | 155 | Resources\Namespace_16x.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a 156 | 157 | 158 | Resources\patch.ico;System.Drawing.Icon, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a 159 | 160 | 161 | Resources\Property_16x.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a 162 | 163 | -------------------------------------------------------------------------------- /ACEPatcher/ModuleLoader/DotNetModuleLoader.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Diagnostics; 4 | using System.IO; 5 | using System.Linq; 6 | using System.Reflection; 7 | using System.Runtime.InteropServices; 8 | using System.Text; 9 | using System.Threading.Tasks; 10 | using dnlib.DotNet; 11 | using dnlib.DotNet.MD; 12 | using dnlib.PE; 13 | using System.Windows.Forms; 14 | using System.ComponentModel; 15 | using System.Threading; 16 | using dnlib.DotNet.Writer; 17 | 18 | namespace ACEPatcher.ModuleLoader 19 | { 20 | class DotNetModuleLoader 21 | { 22 | [DllImport("kernel32.dll")] 23 | private static extern IntPtr OpenThread(int dwDesiredAccess, bool bInheritHandle, uint dwThreadId); 24 | 25 | [DllImport("kernel32.dll")] 26 | private static extern uint SuspendThread(IntPtr hThread); 27 | 28 | [DllImport("kernel32", CharSet = CharSet.Auto, SetLastError = true)] 29 | private static extern bool CloseHandle(IntPtr handle); 30 | 31 | [DllImport("dbghelp.dll",SetLastError = true)] 32 | public static extern bool MiniDumpWriteDump(IntPtr hProcess,uint processId,SafeHandle hFile,int dumpType,IntPtr expParam,IntPtr userStreamParam,IntPtr callbackParam); 33 | 34 | static int BitNessConstant = IntPtr.Size == 4 ? 0x010B : 0x020B; 35 | 36 | static bool IsDotNetAssembly(string path) 37 | { 38 | PEImage image = new PEImage(path); 39 | return image.ImageNTHeaders.OptionalHeader.DataDirectories[14].VirtualAddress != 0; 40 | } 41 | 42 | static bool DoesBitnessMatch(string path) 43 | { 44 | PEImage image = new PEImage(path); 45 | return image.ImageNTHeaders.OptionalHeader.Magic == BitNessConstant; 46 | } 47 | 48 | public static ModuleDefMD LoadModule(string path,out ModuleDefMD[] dependancies,out string[] failed) 49 | { 50 | failed = null; 51 | if (IsDotNetAssembly(path)) 52 | { 53 | ModuleDefMD m = ModuleDefMD.Load(path); 54 | if (m != null) 55 | dependancies = LoadDependancies(m, path, out failed); 56 | else 57 | dependancies = null; 58 | return m; 59 | } 60 | else 61 | { 62 | ModuleDefMD m = TryLoadPackedDotNetAssembly(path); 63 | if (m != null) 64 | dependancies = LoadDependancies(m, path, out failed); 65 | else 66 | dependancies = null; 67 | return m; 68 | } 69 | } 70 | 71 | static ModuleDefMD TryLoadPackedDotNetAssembly(string path) 72 | { 73 | if (!DoesBitnessMatch(path)) 74 | { 75 | MessageBox.Show("Please use " + (BitNessConstant == 0x010B ? "64bit" : "32bit") + " version of ACEPatcher on this assembly"); 76 | return null; 77 | } 78 | Process process; 79 | if((process = Freeze(path)) != null) 80 | { 81 | string dumpFile = DumpProccess(process); 82 | process.Kill(); 83 | ModuleDefMD moduleDef = dumpMainModule(dumpFile); 84 | GC.Collect(); 85 | GC.WaitForPendingFinalizers(); 86 | File.Delete(dumpFile); 87 | return moduleDef; 88 | } 89 | else 90 | { 91 | return null; 92 | } 93 | } 94 | 95 | static Process Freeze(string path) 96 | { 97 | Process process = new Process(); 98 | process.StartInfo.FileName = path; 99 | process.StartInfo.CreateNoWindow = true; 100 | process.StartInfo.UseShellExecute = false; 101 | Stopwatch stopwatch = new Stopwatch(); 102 | stopwatch.Start(); 103 | process.Start(); 104 | while (true) 105 | { 106 | if (GetCLRModule(process.Id)) 107 | { 108 | SuspendThreads(process.Id); 109 | return process; 110 | } 111 | if(stopwatch.ElapsedMilliseconds >= 10000) 112 | { 113 | process.Close(); 114 | return null; 115 | } 116 | } 117 | } 118 | 119 | static bool GetCLRModule(int pID) 120 | { 121 | ProcessModuleCollection modules = Process.GetProcessById(pID).Modules; 122 | for (int i = 0; i < modules.Count; i++) 123 | { 124 | if (modules[i].ModuleName.ToLower() == "clr.dll") 125 | { 126 | return true; 127 | } 128 | } 129 | return false; 130 | } 131 | 132 | static void SuspendThreads(int pid) 133 | { 134 | Process processById = Process.GetProcessById(pid); 135 | if (string.IsNullOrEmpty(processById.ProcessName)) 136 | { 137 | return; 138 | } 139 | foreach (object obj in processById.Threads) 140 | { 141 | ProcessThread processThread = (ProcessThread)obj; 142 | IntPtr intPtr = OpenThread(2, false, (uint)processThread.Id); 143 | if (!(intPtr == IntPtr.Zero)) 144 | { 145 | SuspendThread(intPtr); 146 | CloseHandle(intPtr); 147 | } 148 | } 149 | } 150 | 151 | static string DumpProccess(Process process) 152 | { 153 | string result = Path.GetTempFileName(); 154 | using (var fs = new FileStream(result, FileMode.Create, FileAccess.ReadWrite, FileShare.None)) 155 | { 156 | if (!MiniDumpWriteDump(process.Handle, (uint)process.Id, fs.SafeFileHandle, 2, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero)) 157 | { 158 | throw new Win32Exception(Marshal.GetLastWin32Error()); 159 | } 160 | } 161 | return result; 162 | } 163 | 164 | static unsafe ModuleDefMD dumpMainModule(string fileName) 165 | { 166 | byte[] dumpData = File.ReadAllBytes(fileName); 167 | fixed (byte* dump = dumpData) 168 | { 169 | for (int i = 0; i < dumpData.Length; i++) 170 | { 171 | if (dump[i] == 0x4D && dump[i + 1] == 0x5A) 172 | { 173 | int NTHeaderOffset = *(int*)(dump + i + 0x3C); 174 | 175 | if (*(int*)(dump + i + NTHeaderOffset) == 0x00004550) 176 | { 177 | if (*(short*)(dump + i + NTHeaderOffset + 0x18) == 0x010B || *(short*)(dump + i + NTHeaderOffset + 0x18) == 0x020B) 178 | { 179 | PEImage image = new PEImage((IntPtr)(dump + i), false); 180 | uint alignment = image.ImageNTHeaders.OptionalHeader.FileAlignment; 181 | uint imageSize = image.ImageSectionHeaders.Last().PointerToRawData + image.ImageSectionHeaders.Last().SizeOfRawData; 182 | if (imageSize % alignment != 0) 183 | imageSize = imageSize - (imageSize % alignment) + alignment; 184 | byte[] AssemblyData = new byte[imageSize]; 185 | Marshal.Copy((IntPtr)(dump + i), AssemblyData, 0, (int)imageSize); 186 | if (image.ImageNTHeaders.OptionalHeader.DataDirectories[14].VirtualAddress != 0) 187 | { 188 | ModuleDefMD moduleDef = ModuleDefMD.Load(AssemblyData); 189 | if (moduleDef.Name.EndsWith(".exe")) 190 | { 191 | return moduleDef; 192 | } 193 | else 194 | moduleDef.Dispose(); 195 | } 196 | 197 | } 198 | } 199 | } 200 | 201 | } 202 | } 203 | return null; 204 | } 205 | 206 | public static ModuleDefMD[] LoadDependancies(ModuleDefMD md, string path, out string[] failed) 207 | { 208 | List f = new List(); 209 | List result = new List(); 210 | List refs = md.GetAssemblyRefs().ToList(); 211 | List backup = new List(refs); 212 | string[] files = Directory.GetFiles(Path.GetDirectoryName(path)).Where(x => x.ToLower().EndsWith(".dll") || x.ToLower().EndsWith(".exe")).ToArray(); 213 | foreach (string file in files) 214 | { 215 | try 216 | { 217 | using (PEImage image = new PEImage(file)) 218 | { 219 | if (IsDotNetAssembly(file)) 220 | { 221 | AssemblyName name = AssemblyName.GetAssemblyName(file); 222 | if (refs.Any(x => x.FullName == name.FullName)) 223 | { 224 | result.Add(ModuleDefMD.Load(file)); 225 | refs.Remove(refs.Where(x => x.FullName == name.FullName).First()); 226 | backup.Remove(backup.Where(x => x.FullName == name.FullName).First()); 227 | } 228 | } 229 | } 230 | } 231 | catch 232 | { 233 | 234 | } 235 | } 236 | foreach (AssemblyRef r in refs) 237 | { 238 | try 239 | { 240 | AssemblyName name = new AssemblyName(r.FullName); 241 | result.Add(ModuleDefMD.Load(Assembly.Load(name).ManifestModule)); 242 | backup.Remove(r); 243 | } 244 | catch 245 | { 246 | 247 | } 248 | } 249 | foreach (AssemblyRef r in backup) 250 | f.Add(r.FullName); 251 | failed = f.ToArray(); 252 | return result.ToArray(); 253 | } 254 | 255 | 256 | } 257 | 258 | class NoErrorLoggin : ILogger 259 | { 260 | public bool IgnoresEvent(LoggerEvent loggerEvent) 261 | { 262 | return true; 263 | } 264 | 265 | public void Log(object sender, LoggerEvent loggerEvent, string format, params object[] args) 266 | { 267 | 268 | } 269 | } 270 | } 271 | -------------------------------------------------------------------------------- /ACEPatcher/MainFRM.cs: -------------------------------------------------------------------------------- 1 | using ACEPatcher.Controls; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.ComponentModel; 5 | using System.Data; 6 | using System.Drawing; 7 | using System.Linq; 8 | using System.Text; 9 | using System.Threading.Tasks; 10 | using System.Windows.Forms; 11 | using dnlib.DotNet; 12 | using System.IO; 13 | using ACEPatcher.ModuleLoader; 14 | using System.Resources; 15 | using System.Globalization; 16 | using System.Collections; 17 | 18 | namespace ACEPatcher 19 | { 20 | public partial class MainFRM : Form 21 | { 22 | ModuleDefMD AssemblyToPatch; 23 | ModuleDefMD[] Dependancies; 24 | string AssemblyPath; 25 | 26 | private void PrepareMenuStrip() 27 | { 28 | menuStrip1.Renderer = new DarkMenuRenderer(); 29 | foreach (ToolStripMenuItem menuItem in menuStrip1.Items) 30 | { 31 | ((ToolStripDropDownMenu)menuItem.DropDown).ShowImageMargin = false; 32 | } 33 | 34 | } 35 | 36 | private void PrepareTreeListView() 37 | { 38 | ResourceManager resourceManager = Icons.ResourceManager; 39 | ResourceSet resourceSet = resourceManager.GetResourceSet(CultureInfo.CurrentUICulture, true, true); 40 | TreeViewLoader.Images = new ImageList(); 41 | TreeViewLoader.ResourceMap = new Dictionary(); 42 | foreach(DictionaryEntry resource in resourceSet) 43 | { 44 | if (resource.Value.GetType() != typeof(Icon)) 45 | { 46 | TreeViewLoader.ResourceMap.Add(resource.Key.ToString().Replace("_16x", ""), TreeViewLoader.Images.Images.Count); 47 | TreeViewLoader.Images.Images.Add((Bitmap)resource.Value); 48 | } 49 | } 50 | treeView1.ImageList = TreeViewLoader.Images; 51 | } 52 | 53 | public MainFRM() 54 | { 55 | InitializeComponent(); 56 | PrepareMenuStrip(); 57 | PrepareTreeListView(); 58 | this.Icon = Icons.patch; 59 | } 60 | 61 | private void Form1_DragDrop(object sender, DragEventArgs e) 62 | { 63 | string[] files = (string[])e.Data.GetData(DataFormats.FileDrop); 64 | if (File.Exists(files[0])) 65 | { 66 | string[] failed; 67 | AssemblyToPatch = DotNetModuleLoader.LoadModule(files[0],out Dependancies,out failed); 68 | if(AssemblyToPatch == null) 69 | { 70 | MessageBox.Show("Invalid Assembly"); 71 | return; 72 | } 73 | AssemblyPath = files[0]; 74 | TreeViewLoader.FillTreeView(AssemblyToPatch,Dependancies,treeView1,true); 75 | if (failed.Length > 0) 76 | { 77 | MessageBox.Show("Failed to load: \r\n" + string.Join("\r\n", failed) + "\r\nSome references might be missing", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning); 78 | } 79 | } 80 | else 81 | { 82 | MessageBox.Show("Invalid file"); 83 | } 84 | } 85 | 86 | private void Form1_DragEnter(object sender, DragEventArgs e) 87 | { 88 | if (e.Data.GetDataPresent(DataFormats.FileDrop)) 89 | e.Effect = DragDropEffects.Copy; 90 | else 91 | e.Effect = DragDropEffects.None; 92 | } 93 | 94 | private void openToolStripMenuItem_Click(object sender, EventArgs e) 95 | { 96 | OpenFileDialog dialog = new OpenFileDialog() 97 | { 98 | Title = "Load assembly", 99 | Filter = "Executable|*.exe|Dynamic Link Library|*.dll", 100 | CheckFileExists = true 101 | }; 102 | if(dialog.ShowDialog() == DialogResult.OK) 103 | { 104 | string[] failed; 105 | AssemblyToPatch = DotNetModuleLoader.LoadModule(dialog.FileName,out Dependancies,out failed); 106 | if (AssemblyToPatch == null) 107 | { 108 | MessageBox.Show("Invalid Assembly"); 109 | return; 110 | } 111 | AssemblyPath = dialog.FileName; 112 | TreeViewLoader.FillTreeView(AssemblyToPatch,Dependancies, treeView1,true); 113 | if (failed.Length > 0) 114 | { 115 | MessageBox.Show("Failed to load: \r\n" + string.Join("\r\n", failed) + "\r\nSome references might be missing", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning); 116 | } 117 | } 118 | } 119 | 120 | private void treeView1_NodeMouseDoubleClick(object sender, TreeNodeMouseClickEventArgs e) 121 | { 122 | if(e.Node.Tag != null && e.Node.Tag.GetType().GetInterfaces().Contains(typeof(IMethodDefOrRef))) 123 | { 124 | Patcher.AddPatchToList((IMethod)e.Node.Tag); 125 | string[] vs = new string[Patcher.patchList.Count]; 126 | for(int i = 0; i < Patcher.patchList.Count; i++) 127 | { 128 | vs[i] = Patcher.patchList.ElementAt(i).Key.DeclaringType.Name + "." + Patcher.patchList.ElementAt(i).Key.Name + "->" + Patcher.patchList.ElementAt(i).Value.DeclaringType.Name + "." + Patcher.patchList.ElementAt(i).Value.Name; 129 | } 130 | richTextBox1.Lines = vs; 131 | } 132 | } 133 | 134 | 135 | 136 | private void button1_Click(object sender, EventArgs e) 137 | { 138 | if(richTextBox1.Text.Length == 0) 139 | MessageBox.Show("No patches made", "Information", MessageBoxButtons.OK, MessageBoxIcon.Information); 140 | else 141 | Patcher.ApplyPatches(AssemblyPath); 142 | } 143 | 144 | private void Form1_FormClosing(object sender, FormClosingEventArgs e) 145 | { 146 | Environment.Exit(0); 147 | } 148 | 149 | private void exportToolStripMenuItem_Click(object sender, EventArgs e) 150 | { 151 | if(Patcher.patchAssembly == null || Patcher.patchList.Count == 0) 152 | { 153 | MessageBox.Show("No patches to export", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); 154 | } 155 | SaveFileDialog dialog = new SaveFileDialog() 156 | { 157 | Title = "Export patch...", 158 | Filter = "AcePatcher Patch(*.btb)|*.btb", 159 | }; 160 | if(dialog.ShowDialog() == DialogResult.OK) 161 | { 162 | ConfigManager.ExportConfig(AssemblyToPatch,dialog.FileName,false); 163 | MessageBox.Show("File successfully exported", "Information", MessageBoxButtons.OK, MessageBoxIcon.Information); 164 | } 165 | } 166 | 167 | private void secureExportToolStripMenuItem_Click(object sender, EventArgs e) 168 | { 169 | if (Patcher.patchAssembly == null || Patcher.patchList.Count == 0) 170 | { 171 | MessageBox.Show("No patches to export", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); 172 | } 173 | SaveFileDialog dialog = new SaveFileDialog() 174 | { 175 | Title = "Export patch", 176 | Filter = "AcePatcher Patch(*.btb)|*.btb", 177 | }; 178 | if (dialog.ShowDialog() == DialogResult.OK) 179 | { 180 | string password = ""; 181 | if(InputBox("Password","Type in password:",ref password) == DialogResult.OK) 182 | ConfigManager.ExportConfig(AssemblyToPatch, dialog.FileName, true,password); 183 | MessageBox.Show("File successfully exported", "Information", MessageBoxButtons.OK, MessageBoxIcon.Information); 184 | } 185 | } 186 | 187 | public static DialogResult InputBox(string title, string promptText, ref string value) 188 | { 189 | Form form = new Form(); 190 | Label label = new Label(); 191 | TextBox textBox = new TextBox(); 192 | Button buttonOk = new Button(); 193 | Button buttonCancel = new Button(); 194 | 195 | form.Text = title; 196 | label.Text = promptText; 197 | textBox.Text = value; 198 | 199 | buttonOk.Text = "OK"; 200 | buttonCancel.Text = "Cancel"; 201 | buttonOk.DialogResult = DialogResult.OK; 202 | buttonCancel.DialogResult = DialogResult.Cancel; 203 | 204 | label.SetBounds(9, 20, 372, 13); 205 | textBox.SetBounds(12, 36, 372, 20); 206 | buttonOk.SetBounds(228, 72, 75, 23); 207 | buttonCancel.SetBounds(309, 72, 75, 23); 208 | 209 | label.AutoSize = true; 210 | textBox.Anchor = textBox.Anchor | AnchorStyles.Right; 211 | buttonOk.Anchor = AnchorStyles.Bottom | AnchorStyles.Right; 212 | buttonCancel.Anchor = AnchorStyles.Bottom | AnchorStyles.Right; 213 | 214 | form.ClientSize = new Size(396, 107); 215 | form.Controls.AddRange(new Control[] { label, textBox, buttonOk, buttonCancel }); 216 | form.ClientSize = new Size(Math.Max(300, label.Right + 10), form.ClientSize.Height); 217 | form.FormBorderStyle = FormBorderStyle.FixedDialog; 218 | form.StartPosition = FormStartPosition.CenterScreen; 219 | form.MinimizeBox = false; 220 | form.MaximizeBox = false; 221 | form.AcceptButton = buttonOk; 222 | form.CancelButton = buttonCancel; 223 | 224 | DialogResult dialogResult = form.ShowDialog(); 225 | value = textBox.Text; 226 | return dialogResult; 227 | } 228 | 229 | private void importToolStripMenuItem_Click(object sender, EventArgs e) 230 | { 231 | if(AssemblyToPatch != null) 232 | { 233 | OpenFileDialog dialog = new OpenFileDialog() 234 | { 235 | Title = "Import Patch", 236 | Filter = "AcePatcher Patch(*.btb)|*.btb", 237 | CheckFileExists = true 238 | }; 239 | if(dialog.ShowDialog() == DialogResult.OK) 240 | { 241 | ConfigManager.ImportConfig(Dependancies,dialog.FileName); 242 | string[] vs = new string[Patcher.patchList.Count]; 243 | for (int i = 0; i < Patcher.patchList.Count; i++) 244 | { 245 | vs[i] = Patcher.patchList.ElementAt(i).Key.DeclaringType.Name + "." + Patcher.patchList.ElementAt(i).Key.Name + "->" + Patcher.patchList.ElementAt(i).Value.DeclaringType.Name + "." + Patcher.patchList.ElementAt(i).Value.Name; 246 | } 247 | richTextBox1.Lines = vs; 248 | } 249 | } 250 | else 251 | { 252 | MessageBox.Show("Please load the assembly first", "Information", MessageBoxButtons.OK, MessageBoxIcon.Asterisk); 253 | } 254 | } 255 | } 256 | } 257 | -------------------------------------------------------------------------------- /ACEPatcher/MainFRM.Designer.cs: -------------------------------------------------------------------------------- 1 | 2 | namespace ACEPatcher 3 | { 4 | partial class MainFRM 5 | { 6 | /// 7 | /// Required designer variable. 8 | /// 9 | private System.ComponentModel.IContainer components = null; 10 | 11 | /// 12 | /// Clean up any resources being used. 13 | /// 14 | /// true if managed resources should be disposed; otherwise, false. 15 | protected override void Dispose(bool disposing) 16 | { 17 | if (disposing && (components != null)) 18 | { 19 | components.Dispose(); 20 | } 21 | base.Dispose(disposing); 22 | } 23 | 24 | #region Windows Form Designer generated code 25 | 26 | /// 27 | /// Required method for Designer support - do not modify 28 | /// the contents of this method with the code editor. 29 | /// 30 | private void InitializeComponent() 31 | { 32 | this.menuStrip1 = new System.Windows.Forms.MenuStrip(); 33 | this.fileToolStripMenuItem1 = new System.Windows.Forms.ToolStripMenuItem(); 34 | this.openToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); 35 | this.importToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); 36 | this.exportToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); 37 | this.secureExportToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); 38 | this.treeView1 = new System.Windows.Forms.TreeView(); 39 | this.label1 = new System.Windows.Forms.Label(); 40 | this.tableLayoutPanel1 = new System.Windows.Forms.TableLayoutPanel(); 41 | this.button1 = new System.Windows.Forms.Button(); 42 | this.label2 = new System.Windows.Forms.Label(); 43 | this.richTextBox1 = new System.Windows.Forms.RichTextBox(); 44 | this.menuStrip1.SuspendLayout(); 45 | this.tableLayoutPanel1.SuspendLayout(); 46 | this.SuspendLayout(); 47 | // 48 | // menuStrip1 49 | // 50 | this.menuStrip1.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(60)))), ((int)(((byte)(63)))), ((int)(((byte)(65))))); 51 | this.menuStrip1.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(220)))), ((int)(((byte)(220)))), ((int)(((byte)(220))))); 52 | this.menuStrip1.GripMargin = new System.Windows.Forms.Padding(3); 53 | this.menuStrip1.ImageScalingSize = new System.Drawing.Size(20, 20); 54 | this.menuStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { 55 | this.fileToolStripMenuItem1}); 56 | this.menuStrip1.Location = new System.Drawing.Point(0, 0); 57 | this.menuStrip1.Name = "menuStrip1"; 58 | this.menuStrip1.Padding = new System.Windows.Forms.Padding(2, 0, 0, 0); 59 | this.menuStrip1.Size = new System.Drawing.Size(844, 30); 60 | this.menuStrip1.TabIndex = 0; 61 | this.menuStrip1.Text = "menuStrip1"; 62 | // 63 | // fileToolStripMenuItem1 64 | // 65 | this.fileToolStripMenuItem1.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(60)))), ((int)(((byte)(63)))), ((int)(((byte)(65))))); 66 | this.fileToolStripMenuItem1.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Text; 67 | this.fileToolStripMenuItem1.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { 68 | this.openToolStripMenuItem, 69 | this.importToolStripMenuItem, 70 | this.exportToolStripMenuItem, 71 | this.secureExportToolStripMenuItem}); 72 | this.fileToolStripMenuItem1.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(220)))), ((int)(((byte)(220)))), ((int)(((byte)(220))))); 73 | this.fileToolStripMenuItem1.Name = "fileToolStripMenuItem1"; 74 | this.fileToolStripMenuItem1.Padding = new System.Windows.Forms.Padding(0); 75 | this.fileToolStripMenuItem1.Size = new System.Drawing.Size(38, 30); 76 | this.fileToolStripMenuItem1.Text = "File"; 77 | // 78 | // openToolStripMenuItem 79 | // 80 | this.openToolStripMenuItem.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(27)))), ((int)(((byte)(27)))), ((int)(((byte)(28))))); 81 | this.openToolStripMenuItem.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(220)))), ((int)(((byte)(220)))), ((int)(((byte)(220))))); 82 | this.openToolStripMenuItem.Name = "openToolStripMenuItem"; 83 | this.openToolStripMenuItem.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.O))); 84 | this.openToolStripMenuItem.Size = new System.Drawing.Size(287, 28); 85 | this.openToolStripMenuItem.Text = "Open"; 86 | this.openToolStripMenuItem.Click += new System.EventHandler(this.openToolStripMenuItem_Click); 87 | // 88 | // importToolStripMenuItem 89 | // 90 | this.importToolStripMenuItem.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(27)))), ((int)(((byte)(27)))), ((int)(((byte)(28))))); 91 | this.importToolStripMenuItem.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(220)))), ((int)(((byte)(220)))), ((int)(((byte)(220))))); 92 | this.importToolStripMenuItem.Name = "importToolStripMenuItem"; 93 | this.importToolStripMenuItem.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.I))); 94 | this.importToolStripMenuItem.Size = new System.Drawing.Size(287, 28); 95 | this.importToolStripMenuItem.Text = "Import"; 96 | this.importToolStripMenuItem.Click += new System.EventHandler(this.importToolStripMenuItem_Click); 97 | // 98 | // exportToolStripMenuItem 99 | // 100 | this.exportToolStripMenuItem.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(27)))), ((int)(((byte)(27)))), ((int)(((byte)(28))))); 101 | this.exportToolStripMenuItem.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(220)))), ((int)(((byte)(220)))), ((int)(((byte)(220))))); 102 | this.exportToolStripMenuItem.Name = "exportToolStripMenuItem"; 103 | this.exportToolStripMenuItem.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.E))); 104 | this.exportToolStripMenuItem.Size = new System.Drawing.Size(287, 28); 105 | this.exportToolStripMenuItem.Text = "Export"; 106 | this.exportToolStripMenuItem.Click += new System.EventHandler(this.exportToolStripMenuItem_Click); 107 | // 108 | // secureExportToolStripMenuItem 109 | // 110 | this.secureExportToolStripMenuItem.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(27)))), ((int)(((byte)(27)))), ((int)(((byte)(28))))); 111 | this.secureExportToolStripMenuItem.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(220)))), ((int)(((byte)(220)))), ((int)(((byte)(220))))); 112 | this.secureExportToolStripMenuItem.Name = "secureExportToolStripMenuItem"; 113 | this.secureExportToolStripMenuItem.ShortcutKeys = ((System.Windows.Forms.Keys)(((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.Shift) 114 | | System.Windows.Forms.Keys.E))); 115 | this.secureExportToolStripMenuItem.Size = new System.Drawing.Size(287, 28); 116 | this.secureExportToolStripMenuItem.Text = "Secure Export"; 117 | this.secureExportToolStripMenuItem.Click += new System.EventHandler(this.secureExportToolStripMenuItem_Click); 118 | // 119 | // treeView1 120 | // 121 | this.treeView1.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(37)))), ((int)(((byte)(37)))), ((int)(((byte)(38))))); 122 | this.treeView1.Dock = System.Windows.Forms.DockStyle.Fill; 123 | this.treeView1.Location = new System.Drawing.Point(3, 25); 124 | this.treeView1.Name = "treeView1"; 125 | this.treeView1.Size = new System.Drawing.Size(389, 382); 126 | this.treeView1.TabIndex = 0; 127 | this.treeView1.NodeMouseDoubleClick += new System.Windows.Forms.TreeNodeMouseClickEventHandler(this.treeView1_NodeMouseDoubleClick); 128 | // 129 | // label1 130 | // 131 | this.label1.Anchor = System.Windows.Forms.AnchorStyles.None; 132 | this.label1.AutoSize = true; 133 | this.label1.ForeColor = System.Drawing.Color.White; 134 | this.label1.Location = new System.Drawing.Point(146, 3); 135 | this.label1.Name = "label1"; 136 | this.label1.Size = new System.Drawing.Size(103, 16); 137 | this.label1.TabIndex = 2; 138 | this.label1.Text = "Assembly Tree:"; 139 | // 140 | // tableLayoutPanel1 141 | // 142 | this.tableLayoutPanel1.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) 143 | | System.Windows.Forms.AnchorStyles.Left) 144 | | System.Windows.Forms.AnchorStyles.Right))); 145 | this.tableLayoutPanel1.AutoSize = true; 146 | this.tableLayoutPanel1.ColumnCount = 2; 147 | this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 50F)); 148 | this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 50F)); 149 | this.tableLayoutPanel1.Controls.Add(this.button1, 1, 2); 150 | this.tableLayoutPanel1.Controls.Add(this.label2, 1, 0); 151 | this.tableLayoutPanel1.Controls.Add(this.treeView1, 0, 1); 152 | this.tableLayoutPanel1.Controls.Add(this.label1, 0, 0); 153 | this.tableLayoutPanel1.Controls.Add(this.richTextBox1, 1, 1); 154 | this.tableLayoutPanel1.Location = new System.Drawing.Point(22, 41); 155 | this.tableLayoutPanel1.Name = "tableLayoutPanel1"; 156 | this.tableLayoutPanel1.RowCount = 3; 157 | this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 5F)); 158 | this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 85F)); 159 | this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 10F)); 160 | this.tableLayoutPanel1.Size = new System.Drawing.Size(791, 457); 161 | this.tableLayoutPanel1.TabIndex = 3; 162 | // 163 | // button1 164 | // 165 | this.button1.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(63)))), ((int)(((byte)(63)))), ((int)(((byte)(70))))); 166 | this.button1.Cursor = System.Windows.Forms.Cursors.Hand; 167 | this.button1.Dock = System.Windows.Forms.DockStyle.Right; 168 | this.button1.FlatAppearance.BorderColor = System.Drawing.Color.FromArgb(((int)(((byte)(85)))), ((int)(((byte)(85)))), ((int)(((byte)(85))))); 169 | this.button1.FlatAppearance.BorderSize = 2; 170 | this.button1.FlatAppearance.MouseDownBackColor = System.Drawing.Color.FromArgb(((int)(((byte)(0)))), ((int)(((byte)(122)))), ((int)(((byte)(204))))); 171 | this.button1.FlatAppearance.MouseOverBackColor = System.Drawing.Color.FromArgb(((int)(((byte)(0)))), ((int)(((byte)(102)))), ((int)(((byte)(204))))); 172 | this.button1.FlatStyle = System.Windows.Forms.FlatStyle.Flat; 173 | this.button1.ForeColor = System.Drawing.SystemColors.ButtonHighlight; 174 | this.button1.Location = new System.Drawing.Point(629, 413); 175 | this.button1.Name = "button1"; 176 | this.button1.Size = new System.Drawing.Size(159, 41); 177 | this.button1.TabIndex = 4; 178 | this.button1.Text = "Apply Patches"; 179 | this.button1.UseVisualStyleBackColor = false; 180 | this.button1.Click += new System.EventHandler(this.button1_Click); 181 | // 182 | // label2 183 | // 184 | this.label2.Anchor = System.Windows.Forms.AnchorStyles.None; 185 | this.label2.AutoSize = true; 186 | this.label2.ForeColor = System.Drawing.Color.White; 187 | this.label2.Location = new System.Drawing.Point(559, 3); 188 | this.label2.Name = "label2"; 189 | this.label2.Size = new System.Drawing.Size(68, 16); 190 | this.label2.TabIndex = 3; 191 | this.label2.Text = "Patch List:"; 192 | // 193 | // richTextBox1 194 | // 195 | this.richTextBox1.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(37)))), ((int)(((byte)(37)))), ((int)(((byte)(38))))); 196 | this.richTextBox1.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; 197 | this.richTextBox1.Cursor = System.Windows.Forms.Cursors.Default; 198 | this.richTextBox1.DetectUrls = false; 199 | this.richTextBox1.Dock = System.Windows.Forms.DockStyle.Fill; 200 | this.richTextBox1.ForeColor = System.Drawing.SystemColors.Window; 201 | this.richTextBox1.Location = new System.Drawing.Point(398, 25); 202 | this.richTextBox1.Name = "richTextBox1"; 203 | this.richTextBox1.ReadOnly = true; 204 | this.richTextBox1.ShortcutsEnabled = false; 205 | this.richTextBox1.Size = new System.Drawing.Size(390, 382); 206 | this.richTextBox1.TabIndex = 5; 207 | this.richTextBox1.Text = ""; 208 | this.richTextBox1.WordWrap = false; 209 | // 210 | // Form1 211 | // 212 | this.AllowDrop = true; 213 | this.AutoScaleDimensions = new System.Drawing.SizeF(8F, 16F); 214 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; 215 | this.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(45)))), ((int)(((byte)(45)))), ((int)(((byte)(48))))); 216 | this.ClientSize = new System.Drawing.Size(844, 522); 217 | this.Controls.Add(this.tableLayoutPanel1); 218 | this.Controls.Add(this.menuStrip1); 219 | this.Name = "Form1"; 220 | this.Text = "ACEPatcher"; 221 | this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.Form1_FormClosing); 222 | this.DragDrop += new System.Windows.Forms.DragEventHandler(this.Form1_DragDrop); 223 | this.DragEnter += new System.Windows.Forms.DragEventHandler(this.Form1_DragEnter); 224 | this.menuStrip1.ResumeLayout(false); 225 | this.menuStrip1.PerformLayout(); 226 | this.tableLayoutPanel1.ResumeLayout(false); 227 | this.tableLayoutPanel1.PerformLayout(); 228 | this.ResumeLayout(false); 229 | this.PerformLayout(); 230 | 231 | } 232 | 233 | #endregion 234 | 235 | private System.Windows.Forms.MenuStrip menuStrip1; 236 | private System.Windows.Forms.ToolStripMenuItem fileToolStripMenuItem1; 237 | private System.Windows.Forms.ToolStripMenuItem openToolStripMenuItem; 238 | private System.Windows.Forms.ToolStripMenuItem importToolStripMenuItem; 239 | private System.Windows.Forms.ToolStripMenuItem exportToolStripMenuItem; 240 | private System.Windows.Forms.ToolStripMenuItem secureExportToolStripMenuItem; 241 | private System.Windows.Forms.Label label1; 242 | private System.Windows.Forms.TreeView treeView1; 243 | private System.Windows.Forms.TableLayoutPanel tableLayoutPanel1; 244 | private System.Windows.Forms.Label label2; 245 | private System.Windows.Forms.Button button1; 246 | private System.Windows.Forms.RichTextBox richTextBox1; 247 | } 248 | } 249 | 250 | -------------------------------------------------------------------------------- /ACEPatcher/Patcher.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using System.IO; 7 | using System.Windows.Forms; 8 | using dnlib.DotNet; 9 | using dnlib.DotNet.Emit; 10 | using dnlib.PE; 11 | 12 | 13 | namespace ACEPatcher 14 | { 15 | class Patcher 16 | { 17 | public static ModuleDefMD patchAssembly; 18 | public static ModuleDefMD _0harmony = ModuleDefMD.Load(ACEFiles._0Harmony); 19 | public static string patchAssemblyPath; 20 | public static Dictionary patchList = new Dictionary(); 21 | 22 | private static bool CompareSignature(IMethod method1,IMethod method2) 23 | { 24 | if (method1.MethodSig.RetType.FullName != method2.MethodSig.RetType.FullName) 25 | return false; 26 | if (((MethodDef)method1).HasThis) 27 | { 28 | if (method1.MethodSig.Params.Count+1 != method2.MethodSig.Params.Count) 29 | return false; 30 | if (method1.DeclaringType.FullName != method2.GetParam(0).FullName) 31 | return false; 32 | int i = 0; 33 | for(int j = 0; j < method1.MethodSig.Params.Count; j++) 34 | { 35 | if (method1.MethodSig.Params[j].FullName == method2.MethodSig.Params[j+1].FullName) 36 | i++; 37 | } 38 | return method1.MethodSig.Params.Count == i; 39 | } 40 | else 41 | { 42 | if (method1.MethodSig.Params.Count != method2.MethodSig.Params.Count) 43 | return false; 44 | int i = 0; 45 | for (int j = 0; j < method1.MethodSig.Params.Count; j++) 46 | { 47 | if (method1.MethodSig.Params[j].FullName == method2.MethodSig.Params[j].FullName) 48 | i++; 49 | } 50 | return i == method1.MethodSig.Params.Count; 51 | } 52 | } 53 | 54 | private static OpCode DetermineStindType(TypeSig sig) 55 | { 56 | if (sig == patchAssembly.CorLibTypes.IntPtr) 57 | return OpCodes.Stind_I; 58 | else if (sig == patchAssembly.CorLibTypes.SByte || sig == patchAssembly.CorLibTypes.Byte || sig == patchAssembly.CorLibTypes.Boolean) 59 | return OpCodes.Stind_I1; 60 | else if (sig == patchAssembly.CorLibTypes.Int16 || sig == patchAssembly.CorLibTypes.UInt16 || sig == patchAssembly.CorLibTypes.Char) 61 | return OpCodes.Stind_I2; 62 | else if (sig == patchAssembly.CorLibTypes.Int32 || sig == patchAssembly.CorLibTypes.UInt32) 63 | return OpCodes.Stind_I4; 64 | else if (sig == patchAssembly.CorLibTypes.Int64 || sig == patchAssembly.CorLibTypes.UInt64) 65 | return OpCodes.Stind_I8; 66 | else if (sig == patchAssembly.CorLibTypes.Single) 67 | return OpCodes.Stind_R4; 68 | else if (sig == patchAssembly.CorLibTypes.Double) 69 | return OpCodes.Stind_R8; 70 | else 71 | return OpCodes.Stind_Ref; 72 | } 73 | 74 | private static OpCode DetermineLdindType(TypeSig sig) 75 | { 76 | if (sig == patchAssembly.CorLibTypes.IntPtr) 77 | return OpCodes.Ldind_I; 78 | else if (sig == patchAssembly.CorLibTypes.SByte || sig == patchAssembly.CorLibTypes.Byte || sig == patchAssembly.CorLibTypes.Boolean) 79 | return OpCodes.Ldind_I1; 80 | else if (sig == patchAssembly.CorLibTypes.Int16 || sig == patchAssembly.CorLibTypes.UInt16 || sig == patchAssembly.CorLibTypes.Char) 81 | return OpCodes.Ldind_I2; 82 | else if (sig == patchAssembly.CorLibTypes.Int32 || sig == patchAssembly.CorLibTypes.UInt32) 83 | return OpCodes.Ldind_I4; 84 | else if (sig == patchAssembly.CorLibTypes.Int64 || sig == patchAssembly.CorLibTypes.UInt64) 85 | return OpCodes.Ldind_I8; 86 | else if (sig == patchAssembly.CorLibTypes.Single) 87 | return OpCodes.Ldind_R4; 88 | else if (sig == patchAssembly.CorLibTypes.Double) 89 | return OpCodes.Ldind_R8; 90 | else 91 | return OpCodes.Ldind_Ref; 92 | } 93 | 94 | public static void AddPatchToList(IMethod method) 95 | { 96 | if(patchAssembly == null) 97 | { 98 | OpenFileDialog dialog = new OpenFileDialog() 99 | { 100 | Title = "Load assembly", 101 | Filter = "Executable|*.exe|Dynamic Link Library|*.dll", 102 | CheckFileExists = true 103 | }; 104 | if (dialog.ShowDialog() == DialogResult.OK) 105 | { 106 | try 107 | { 108 | patchAssembly = ModuleDefMD.Load(dialog.FileName); 109 | patchAssemblyPath = dialog.FileName; 110 | } 111 | catch 112 | { 113 | MessageBox.Show("Invalid Assembly", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); 114 | } 115 | } 116 | else 117 | return; 118 | } 119 | PatchDialog patchDialog = new PatchDialog(); 120 | if(patchDialog.ShowDialog() == DialogResult.OK) 121 | { 122 | if (((MethodDef)patchDialog.SelectedMethod).HasThis) 123 | { 124 | MessageBox.Show("The chosen method must be static", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); 125 | return; 126 | } 127 | if (CompareSignature(method, patchDialog.SelectedMethod)) 128 | { 129 | if (!patchList.ContainsKey(method)) 130 | patchList.Add(method, patchDialog.SelectedMethod); 131 | else 132 | MessageBox.Show("Method already patched", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning); 133 | } 134 | else 135 | { 136 | MessageBox.Show("Method signature mismatch","Error",MessageBoxButtons.OK,MessageBoxIcon.Error); 137 | } 138 | } 139 | } 140 | 141 | private static MethodDefUser GenerateMethod(IMethod method,Importer importer) 142 | { 143 | MethodDefUser resultMethod = new MethodDefUser("ACE" + Guid.NewGuid().ToString("N"), new MethodSig(CallingConvention.Default, 0, importer.Import(typeof(System.Reflection.MethodBase)).ToTypeSig()), MethodAttributes.Public | MethodAttributes.Static); 144 | resultMethod.Body = new CilBody(); 145 | resultMethod.Body.Instructions.Add(new Instruction(OpCodes.Ldtoken, method.DeclaringType.DefinitionAssembly.FullName == patchAssembly.Assembly.FullName ? ((MethodDef)method) : importer.Import((MethodDef)method))); 146 | resultMethod.Body.Instructions.Add(new Instruction(OpCodes.Call, importer.Import(typeof(System.Reflection.MethodBase).GetMethod("GetMethodFromHandle", new Type[] { typeof(RuntimeMethodHandle) })))); 147 | resultMethod.Body.Instructions.Add(new Instruction(OpCodes.Ret)); 148 | return resultMethod; 149 | } 150 | 151 | public static void ApplyPatches(string MainAssemblyPath) 152 | { 153 | byte[] backup = DotNetUtils.ReadAssembly(patchAssembly); 154 | Dictionary patchList2 = new Dictionary(); 155 | foreach (KeyValuePair patch in patchList) 156 | { 157 | MethodSig sig = new MethodSig(); 158 | sig.CallingConvention = CallingConvention.Default; 159 | sig.RetType = patchAssembly.CorLibTypes.Boolean; 160 | foreach(TypeSig typeSig in patch.Value.MethodSig.Params) 161 | sig.Params.Add(new ByRefSig( typeSig)); 162 | sig.Params.Add(new ByRefSig(patch.Value.MethodSig.RetType)); 163 | MethodDefUser method = new MethodDefUser("Prefix" + DateTimeOffset.UtcNow.ToUnixTimeMilliseconds(),sig,MethodAttributes.Public| MethodAttributes.Static); 164 | List paramds = ((MethodDef)patch.Value).ParamDefs.ToList(); 165 | if (((MethodDef)patch.Key).HasThis) 166 | { 167 | method.ParamDefs.Add(new ParamDefUser("__instance", 1)); 168 | paramds.RemoveAt(0); 169 | } 170 | foreach (ParamDef pdef in paramds) 171 | method.ParamDefs.Add(new ParamDefUser(pdef.Name, (ushort)(method.ParamDefs.Count + 1))); 172 | method.ParamDefs.Add(new ParamDefUser("__result",(ushort)(method.ParamDefs.Count+1) )); 173 | method.Body = new CilBody(); 174 | DotNetUtils.CopyBodyFromTo((MethodDef)patch.Value, method); 175 | if(((MethodDef)patch.Value).HasReturnType) 176 | method.Body.Variables.Add(new Local(patch.Value.MethodSig.RetType)); 177 | int stack = 0; 178 | int LastStackZero = 0; 179 | method.Body.Instructions.SimplifyMacros(method.Body.Variables, method.Parameters); 180 | for(int i = 0; i < method.Body.Instructions.Count; i++) 181 | { 182 | if (stack == 0) 183 | LastStackZero = i; 184 | if(method.Body.Instructions[i].OpCode == OpCodes.Ret) 185 | { 186 | if(((MethodDef)patch.Value).HasReturnType) 187 | i += DotNetUtils.ReplaceInstruction(method.Body.Instructions, method.Body.Instructions[i], Instruction.Create(OpCodes.Stloc_S, method.Body.Variables.Last()), Instruction.Create(OpCodes.Ldarg_S, method.Parameters.Last()), Instruction.Create(OpCodes.Ldloc_S, method.Body.Variables.Last()), Instruction.Create(DetermineStindType(patch.Value.MethodSig.RetType)), Instruction.Create(OpCodes.Ldc_I4_0),Instruction.Create(OpCodes.Ret)); 188 | else 189 | i += DotNetUtils.ReplaceInstruction(method.Body.Instructions, method.Body.Instructions[i],Instruction.Create(OpCodes.Ldc_I4_0), Instruction.Create(OpCodes.Ret)); 190 | LastStackZero = i; 191 | stack = 0; 192 | } 193 | else if(method.Body.Instructions[i].Operand != null && method.Body.Instructions[i].Operand.GetType().GetInterfaces().Contains(typeof(IMethodDefOrRef)) && ((IMDTokenProvider)method.Body.Instructions[i].Operand).MDToken == patch.Value.MDToken) 194 | { 195 | if(method.Body.Instructions[i + 1].OpCode != OpCodes.Ret) 196 | { 197 | MessageBox.Show("Invalid call to continue", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Error); 198 | return; 199 | } 200 | for(int j = LastStackZero; j < i; j++) 201 | { 202 | method.Body.Instructions[j].OpCode = OpCodes.Nop; 203 | method.Body.Instructions[j].Operand = null; 204 | } 205 | i += DotNetUtils.ReplaceInstruction(method.Body.Instructions, method.Body.Instructions[i],new Instruction(OpCodes.Ldc_I4_1)); 206 | LastStackZero = i; 207 | stack = 0; 208 | } 209 | else if (method.Body.Instructions[i].OpCode.ToString().ToLower().Contains("ldarg")) 210 | { 211 | method.Body.Instructions.Insert(i + 1, new Instruction(DetermineLdindType(((Parameter)method.Body.Instructions[i].Operand).Type))); 212 | } 213 | else if (method.Body.Instructions[i].OpCode.ToString().ToLower().Contains("starg")) 214 | { 215 | stack++; 216 | method.Body.Instructions.Insert(LastStackZero, new Instruction(OpCodes.Ldarg, method.Body.Instructions[i++].Operand)); 217 | method.Body.Instructions[i].OpCode = DetermineStindType(((Parameter)method.Body.Instructions[i].Operand).Type); 218 | method.Body.Instructions[i].Operand = null; 219 | } 220 | try 221 | { 222 | method.Body.Instructions[i].UpdateStack(ref stack); 223 | } 224 | catch 225 | { 226 | break; 227 | } 228 | } 229 | method.Body.Instructions.UpdateInstructionOffsets(); 230 | method.Body.Instructions.OptimizeMacros(); 231 | ((TypeDef)patch.Value.DeclaringType).Methods.Add(method); 232 | patchList2.Add(method, patch.Key); 233 | } 234 | TypeDefUser patchType = new TypeDefUser("ACE", patchAssembly.CorLibTypes.Object.ToTypeDefOrRef()); 235 | MethodDefUser patchMethod = new MethodDefUser("ACE" + DateTimeOffset.UtcNow.ToUnixTimeMilliseconds(), new MethodSig(CallingConvention.Default, 0, patchAssembly.CorLibTypes.Int32, patchAssembly.CorLibTypes.String), MethodAttributes.Public | MethodAttributes.Static); 236 | patchAssembly.Types.Add(patchType); 237 | patchType.Methods.Add(patchMethod); 238 | patchMethod.Body = new CilBody(); 239 | Importer importer = new Importer(patchAssembly); 240 | var guid = importer.Import(typeof(Guid)); 241 | patchMethod.Body.Variables.Add(new Local(new ValueTypeSig(guid))); 242 | foreach (KeyValuePair patch in patchList2) 243 | { 244 | patchMethod.Body.Instructions.Add(new Instruction(OpCodes.Call,importer.Import(typeof(Guid).GetMethod("NewGuid")))); 245 | patchMethod.Body.Instructions.Add(new Instruction(OpCodes.Stloc_0)); 246 | patchMethod.Body.Instructions.Add(new Instruction(OpCodes.Ldloca_S,patchMethod.Body.Variables[0])); 247 | patchMethod.Body.Instructions.Add(new Instruction(OpCodes.Ldstr,"N")); 248 | patchMethod.Body.Instructions.Add(new Instruction(OpCodes.Call, importer.Import(typeof(Guid).GetMethod("ToString",new Type[] { typeof(string)})))); 249 | patchMethod.Body.Instructions.Add(new Instruction(OpCodes.Newobj, importer.Import(_0harmony.ResolveMethod(438)))); 250 | MethodDef method1 = GenerateMethod(patch.Value, importer); 251 | patchType.Methods.Add(method1); 252 | patchMethod.Body.Instructions.Add(new Instruction(OpCodes.Call,method1)); 253 | method1 = GenerateMethod(patch.Key, importer); 254 | patchType.Methods.Add(method1); 255 | patchMethod.Body.Instructions.Add(new Instruction(OpCodes.Call, method1)); 256 | patchMethod.Body.Instructions.Add(new Instruction(OpCodes.Castclass, importer.Import(typeof(System.Reflection.MethodInfo)))); 257 | patchMethod.Body.Instructions.Add(new Instruction(OpCodes.Newobj, importer.Import(_0harmony.ResolveMethod(488)))); 258 | patchMethod.Body.Instructions.Add(new Instruction(OpCodes.Ldnull)); 259 | patchMethod.Body.Instructions.Add(new Instruction(OpCodes.Ldnull)); 260 | patchMethod.Body.Instructions.Add(new Instruction(OpCodes.Ldnull)); 261 | patchMethod.Body.Instructions.Add(new Instruction(OpCodes.Call, importer.Import(_0harmony.ResolveMethod(444)))); 262 | patchMethod.Body.Instructions.Add(new Instruction(OpCodes.Pop)); 263 | } 264 | patchMethod.Body.Instructions.Add(new Instruction(OpCodes.Ldc_I4_1)); 265 | patchMethod.Body.Instructions.Add(new Instruction(OpCodes.Ret)); 266 | MemoryStream stream = new MemoryStream(); 267 | patchAssembly.Write(stream); 268 | byte[] patchedAssembly = stream.ToArray(); 269 | string path = Path.GetFileNameWithoutExtension(MainAssemblyPath) + "_patch_" + DateTimeOffset.Now.ToUnixTimeSeconds(); 270 | Directory.CreateDirectory(path); 271 | File.Copy(MainAssemblyPath, path + "/" + Path.GetFileName(MainAssemblyPath)); 272 | File.WriteAllBytes(path + "/0harmony.dll", ACEFiles._0Harmony); 273 | if(new PEImage(MainAssemblyPath).ImageNTHeaders.OptionalHeader.Magic == 0x010B) 274 | { 275 | File.WriteAllBytes(path + "/DllInjector.exe",ACEFiles.DllInjector); 276 | File.WriteAllBytes(path + "/ACE.dll",ACEFiles.ACEx32); 277 | } 278 | else 279 | { 280 | File.WriteAllBytes(path + "/DllInjector.exe", ACEFiles.DllInjector64); 281 | File.WriteAllBytes(path + "/ACE.dll", ACEFiles.ACEx64); 282 | } 283 | File.WriteAllBytes(path + "/patch", patchedAssembly); 284 | string command = "DllInjector.exe " + Path.GetFileName(MainAssemblyPath) + " ACE.dll patch " + patchType.Name + "." + patchMethod.Name; 285 | File.WriteAllText(path + "/Execute.bat", command); 286 | ModuleDefMD backup2 = ModuleDefMD.Load(backup); 287 | Dictionary newDict = new Dictionary(); 288 | foreach(KeyValuePair pair in patchList) 289 | { 290 | newDict.Add(pair.Key, (IMethod)backup2.ResolveToken(pair.Value.MDToken)); 291 | } 292 | patchList = newDict; 293 | patchAssembly = backup2; 294 | MessageBox.Show("Assembly succcessfully patched, please move all dependancies into the folder with patched executable","Success",MessageBoxButtons.OK,MessageBoxIcon.Information); 295 | } 296 | 297 | 298 | } 299 | } 300 | --------------------------------------------------------------------------------