mirror of
https://github.com/k1tbyte/Wand-Enhancer.git
synced 2026-09-04 09:13:26 +00:00
bump version to 1.0.5.0, refactor patching logic, remove unused code
This commit is contained in:
@@ -14,7 +14,7 @@ using Application = System.Windows.Application;
|
||||
|
||||
namespace WeModPatcher.Core
|
||||
{
|
||||
public class StaticPatcher
|
||||
public class Patcher
|
||||
{
|
||||
private class PatchEntry
|
||||
{
|
||||
@@ -54,7 +54,7 @@ namespace WeModPatcher.Core
|
||||
private readonly string _unpackedPath;
|
||||
private int _sumOfPatches = 0;
|
||||
|
||||
public StaticPatcher(WeModConfig weModConfig, Action<string, ELogType> logger, PatchConfig config)
|
||||
public Patcher(WeModConfig weModConfig, Action<string, ELogType> logger, PatchConfig config)
|
||||
{
|
||||
_weModConfig = weModConfig;
|
||||
_logger = logger;
|
||||
@@ -138,59 +138,22 @@ namespace WeModPatcher.Core
|
||||
}
|
||||
}
|
||||
|
||||
private void PatchPe()
|
||||
private void AttachProxyDll()
|
||||
{
|
||||
_logger("[PATCHER] Patching PE...", ELogType.Info);
|
||||
var patchResult = MemoryUtils.PatchFile(
|
||||
_weModConfig.ExecutablePath,
|
||||
Constants.ExePatchSignature,
|
||||
Constants.ExePatchSignature.PatchBytes
|
||||
);
|
||||
if(patchResult == -1)
|
||||
var assembly = Assembly.GetExecutingAssembly();
|
||||
var dll = assembly.GetManifestResourceStream(Constants.ProxyDllResouceName);
|
||||
if (dll == null)
|
||||
{
|
||||
_logger("[PATCHER] Failed to patch PE", ELogType.Error);
|
||||
return;
|
||||
throw new Exception("[PATCHER] Proxy DLL resource not found");
|
||||
}
|
||||
_logger(patchResult == 0 ? "[PATCHER] PE already patched!" : "[PATCHER] PE patched successfully!", ELogType.Success);
|
||||
var destPath = Path.Combine(_weModConfig.RootDirectory, "version.dll");
|
||||
using (var fileStream = File.Create(destPath))
|
||||
{
|
||||
dll.CopyTo(fileStream);
|
||||
}
|
||||
_logger("[PATCHER] Proxy DLL attached", ELogType.Info);
|
||||
}
|
||||
|
||||
private void CreateShortcut()
|
||||
{
|
||||
// invoke file dialog save file
|
||||
|
||||
var fileDialog = new SaveFileDialog()
|
||||
{
|
||||
CheckPathExists = true,
|
||||
AddExtension = true,
|
||||
SupportMultiDottedExtensions = false,
|
||||
FileName = _weModConfig.BrandName,
|
||||
};
|
||||
|
||||
if(fileDialog.ShowDialog() != DialogResult.OK)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_config.Path = _weModConfig.RootDirectory;
|
||||
var json = JsonConvert.SerializeObject(_config, new JsonSerializerSettings
|
||||
{
|
||||
NullValueHandling = NullValueHandling.Ignore,
|
||||
DefaultValueHandling = DefaultValueHandling.Ignore,
|
||||
Formatting = Formatting.None
|
||||
});
|
||||
|
||||
Utils.Win32.Shortcut.CreateShortcut(
|
||||
fileName: fileDialog.FileName + ".lnk",
|
||||
targetPath: Assembly.GetExecutingAssembly().Location,
|
||||
arguments: Extensions.Base64Encode(json),
|
||||
workingDirectory: Common.GetCurrentDir(),
|
||||
description: null,
|
||||
iconPath: _weModConfig.ExecutablePath
|
||||
);
|
||||
|
||||
_logger("[PATCHER] The shortcut has been created, now you should only run WeMod through this shortcut", ELogType.Success);
|
||||
}
|
||||
|
||||
public void Patch()
|
||||
{
|
||||
Common.TryKillProcess(_weModConfig.BrandName);
|
||||
@@ -232,15 +195,8 @@ namespace WeModPatcher.Core
|
||||
{
|
||||
throw new Exception($"[PATCHER] Failed to pack app.asar: {e.Message}");
|
||||
}
|
||||
|
||||
if (_config.PatchMethod == EPatchProcessMethod.Static)
|
||||
{
|
||||
PatchPe();
|
||||
}
|
||||
else if(_config.PatchMethod == EPatchProcessMethod.Runtime)
|
||||
{
|
||||
Application.Current.Dispatcher.Invoke(CreateShortcut);
|
||||
}
|
||||
|
||||
AttachProxyDll();
|
||||
|
||||
_logger("[PATCHER] Done!", ELogType.Success);
|
||||
}
|
||||
@@ -1,144 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Runtime.InteropServices;
|
||||
using WeModPatcher.Models;
|
||||
using WeModPatcher.Utils;
|
||||
using WeModPatcher.Utils.Win32;
|
||||
using WeModPatcher.View.MainWindow;
|
||||
|
||||
namespace WeModPatcher.Core
|
||||
{
|
||||
|
||||
public class RuntimePatcher
|
||||
{
|
||||
private readonly WeModConfig _config;
|
||||
|
||||
public RuntimePatcher(WeModConfig config)
|
||||
{
|
||||
_config = config;
|
||||
}
|
||||
|
||||
|
||||
public void StartProcess()
|
||||
{
|
||||
if(string.IsNullOrEmpty(_config?.ExecutablePath))
|
||||
{
|
||||
throw new Exception("Path is not specified");
|
||||
}
|
||||
|
||||
Common.TryKillProcess(_config.BrandName);
|
||||
var startupInfo = new Imports.StartupInfo { cb = Marshal.SizeOf(typeof(Imports.StartupInfo)) };
|
||||
if(!Imports.CreateProcessA(_config.ExecutablePath,
|
||||
null,
|
||||
IntPtr.Zero,
|
||||
IntPtr.Zero,
|
||||
false, Imports.DEBUG_PROCESS, IntPtr.Zero,
|
||||
null, ref startupInfo, out var processInfo))
|
||||
{
|
||||
throw new Exception("Failed to create process, error code: " + Marshal.GetLastWin32Error());
|
||||
}
|
||||
|
||||
var debugEvent = new Imports.DEBUG_EVENT();
|
||||
var processIds = new Dictionary<uint, bool>();
|
||||
while (Imports.WaitForDebugEvent(ref debugEvent, uint.MaxValue))
|
||||
{
|
||||
uint continueStatus = Imports.DBG_CONTINUE;
|
||||
var code = debugEvent.dwDebugEventCode;
|
||||
// Console.WriteLine("Debug event code: " + code);
|
||||
if (code == Imports.CREATE_PROCESS_DEBUG_EVENT)
|
||||
{
|
||||
// Console.WriteLine("Spawning process: " + debugEvent.dwProcessId);
|
||||
processIds.Add(debugEvent.dwProcessId, false);
|
||||
}
|
||||
else if (code == Imports.EXIT_PROCESS_DEBUG_EVENT)
|
||||
{
|
||||
processIds.Remove(debugEvent.dwProcessId);
|
||||
|
||||
if(processIds.Count == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (code == Imports.EXCEPTION_DEBUG_EVENT)
|
||||
{
|
||||
// pass the exception to the process
|
||||
continueStatus = Imports.DBG_EXCEPTION_NOT_HANDLED;
|
||||
|
||||
var exceptionInfo = Imports.MapUnmanagedStructure<Imports.EXCEPTION_DEBUG_INFO>(debugEvent.Union);
|
||||
// Console.WriteLine("Exception code: " + exceptionInfo.ExceptionRecord.ExceptionCode);
|
||||
|
||||
if (exceptionInfo.ExceptionRecord.ExceptionCode == Imports.EXCEPTION_BREAKPOINT &&
|
||||
processIds.TryGetValue(debugEvent.dwProcessId, out var wasPatched) && !wasPatched)
|
||||
{
|
||||
var process = Process.GetProcessById((int)debugEvent.dwProcessId);
|
||||
// Console.WriteLine("Scanning process: " + process.ProcessName + " " + process.Id);
|
||||
var address = MemoryUtils.ScanVirtualMemory(
|
||||
process.Handle,
|
||||
process.Modules[0].BaseAddress,
|
||||
process.Modules[0].ModuleMemorySize,
|
||||
Constants.ExePatchSignature.Sequence, Constants.ExePatchSignature.Mask
|
||||
);
|
||||
|
||||
if (address != IntPtr.Zero)
|
||||
{
|
||||
processIds[debugEvent.dwProcessId] = MemoryUtils.SafeWriteVirtualMemory(
|
||||
process.Handle,
|
||||
address + Constants.ExePatchSignature.Offset,
|
||||
Constants.ExePatchSignature.PatchBytes
|
||||
);
|
||||
|
||||
/*byte[] patchedBytes = new byte[32];
|
||||
if (Imports.ReadProcessMemory(process.Handle, address, patchedBytes, patchedBytes.Length, out int bytesRead))
|
||||
{
|
||||
Console.WriteLine("Bytes after patching: ");
|
||||
for (int i = 0; i < bytesRead; i++)
|
||||
{
|
||||
Console.Write($"{patchedBytes[i]:X2} ");
|
||||
}
|
||||
Console.WriteLine();
|
||||
}*/
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Imports.ContinueDebugEvent(debugEvent.dwProcessId, debugEvent.dwThreadId, continueStatus);
|
||||
}
|
||||
|
||||
foreach (var entry in processIds)
|
||||
{
|
||||
Imports.DebugActiveProcessStop(entry.Key);
|
||||
}
|
||||
|
||||
Imports.CloseHandle(processInfo.hProcess);
|
||||
}
|
||||
|
||||
public static void Patch(PatchConfig config, Action<string, ELogType> logger)
|
||||
{
|
||||
if (config.AppProps == null)
|
||||
{
|
||||
throw new Exception("Path is not specified");
|
||||
}
|
||||
|
||||
var parent = Directory.GetParent(config.AppProps.RootDirectory)?.FullName ?? config.AppProps.RootDirectory;
|
||||
var latestWeModConfig = config.AutoApplyPatches ? Extensions.FindLatestWeMod(parent) ?? config.AppProps : config.AppProps;
|
||||
|
||||
if (Extensions.CheckWeModPath(latestWeModConfig.RootDirectory) == null)
|
||||
{
|
||||
throw new Exception("Invalid WeMod path");
|
||||
}
|
||||
|
||||
if(!File.Exists(Path.Combine(latestWeModConfig.RootDirectory, "resources", "app.asar.backup")))
|
||||
{
|
||||
config.PatchMethod = EPatchProcessMethod.None;
|
||||
new StaticPatcher(latestWeModConfig, logger, config).Patch();
|
||||
}
|
||||
|
||||
new RuntimePatcher(latestWeModConfig)
|
||||
.StartProcess();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user