mirror of
https://github.com/k1tbyte/Wand-Enhancer.git
synced 2026-09-04 16:23:17 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
54fe538ed9 | ||
|
|
8f14ee2939 | ||
|
|
9ba60a09a7 | ||
|
|
108feeafa8 | ||
|
|
b283c63fd7 | ||
|
|
9ed3d270e3 | ||
|
|
e534c08f88 | ||
|
|
fcf47673af |
@@ -0,0 +1,30 @@
|
|||||||
|
---
|
||||||
|
name: Bug report
|
||||||
|
about: Create a report to help us improve
|
||||||
|
title: ''
|
||||||
|
labels: bug
|
||||||
|
assignees: k1tbyte
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**WeMod version**: X.X.X
|
||||||
|
**Patcher version**: X.X.X
|
||||||
|
|
||||||
|
**Describe the bug**
|
||||||
|
A clear and concise description of what the bug is.
|
||||||
|
|
||||||
|
**To Reproduce**
|
||||||
|
Steps to reproduce the behavior:
|
||||||
|
1. Go to '...'
|
||||||
|
2. Click on '....'
|
||||||
|
3. Scroll down to '....'
|
||||||
|
4. See error
|
||||||
|
|
||||||
|
**Expected behavior**
|
||||||
|
A clear and concise description of what you expected to happen.
|
||||||
|
|
||||||
|
**Screenshots**
|
||||||
|
If applicable, add screenshots to help explain your problem.
|
||||||
|
|
||||||
|
**Additional context**
|
||||||
|
Add any other context about the problem here.
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
---
|
||||||
|
name: Feature request
|
||||||
|
about: Suggest an idea for this project
|
||||||
|
title: ''
|
||||||
|
labels: ''
|
||||||
|
assignees: ''
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**Is your feature request related to a problem? Please describe.**
|
||||||
|
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
|
||||||
|
|
||||||
|
**Describe the solution you'd like**
|
||||||
|
A clear and concise description of what you want to happen.
|
||||||
|
|
||||||
|
**Describe alternatives you've considered**
|
||||||
|
A clear and concise description of any alternative solutions or features you've considered.
|
||||||
|
|
||||||
|
**Additional context**
|
||||||
|
Add any other context or screenshots about the feature request here.
|
||||||
+111
@@ -0,0 +1,111 @@
|
|||||||
|
# Contributing to WeMod Patcher
|
||||||
|
|
||||||
|
Thank you for your interest in the WeMod Patcher project! This document provides guidelines for contributing to the project.
|
||||||
|
|
||||||
|
## Table of Contents
|
||||||
|
|
||||||
|
- [Development Environment Setup](#development-environment-setup)
|
||||||
|
- [Bug Reports](#bug-reports)
|
||||||
|
- [Feature Suggestions](#feature-suggestions)
|
||||||
|
- [Creating a Pull Request](#creating-a-pull-request)
|
||||||
|
- [Code Style](#code-style)
|
||||||
|
- [Testing](#testing)
|
||||||
|
- [License](#license)
|
||||||
|
|
||||||
|
## Code of Conduct
|
||||||
|
|
||||||
|
By participating in this project, you commit to maintaining respectful interactions with all community members. Any form of insults, harassment, or other unacceptable behavior will not be tolerated.
|
||||||
|
|
||||||
|
## Project Structure
|
||||||
|
|
||||||
|
The project consists of the following main components:
|
||||||
|
|
||||||
|
- **WeModPatcher** - Main project containing the patcher logic and user interface
|
||||||
|
- **AsarSharp** - Library for working with ASAR archives (used for unpacking and modifying WeMod files)
|
||||||
|
- **Core** - Core of the patcher, including static and dynamic patching
|
||||||
|
- **Models** - Data models used in the project
|
||||||
|
- **View** - User interface components
|
||||||
|
|
||||||
|
## Development Environment Setup
|
||||||
|
|
||||||
|
1. Clone the repository:
|
||||||
|
```
|
||||||
|
git clone https://github.com/k1tbyte/Wemod-Patcher.git
|
||||||
|
```
|
||||||
|
|
||||||
|
2. Open the solution `Wemod-Patcher.sln` in Visual Studio or JetBrains Rider.
|
||||||
|
|
||||||
|
3. Restore NuGet packages.
|
||||||
|
|
||||||
|
4. Build the project.
|
||||||
|
|
||||||
|
## Bug Reports
|
||||||
|
|
||||||
|
If you've found a bug, please create an Issue with a detailed description:
|
||||||
|
|
||||||
|
- WeMod Patcher version
|
||||||
|
- WeMod version where the problem occurred
|
||||||
|
- Detailed steps to reproduce the bug
|
||||||
|
- Expected and actual behavior
|
||||||
|
- Screenshots or error logs (if available)
|
||||||
|
|
||||||
|
## Feature Suggestions
|
||||||
|
|
||||||
|
Suggestions for new features or improvements are welcome! Create an Issue describing your idea, explaining:
|
||||||
|
|
||||||
|
- What problem the proposed improvement solves
|
||||||
|
- How you envision implementing this feature
|
||||||
|
- Potential alternatives you've considered
|
||||||
|
|
||||||
|
## Creating a Pull Request
|
||||||
|
|
||||||
|
1. Fork the repository.
|
||||||
|
2. Create a branch with a descriptive name:
|
||||||
|
```
|
||||||
|
git checkout -b feature/feature-name
|
||||||
|
```
|
||||||
|
or
|
||||||
|
```
|
||||||
|
git checkout -b fix/fix-name
|
||||||
|
```
|
||||||
|
|
||||||
|
3. Make the necessary changes and commit with clear, descriptive messages.
|
||||||
|
|
||||||
|
4. Ensure your code follows the project's style.
|
||||||
|
|
||||||
|
5. Push the branch to your fork:
|
||||||
|
```
|
||||||
|
git push origin your-branch-name
|
||||||
|
```
|
||||||
|
|
||||||
|
6. Create a Pull Request to the main repository.
|
||||||
|
|
||||||
|
7. In the Pull Request description, explain the changes made and why they're necessary.
|
||||||
|
|
||||||
|
## Code Style
|
||||||
|
|
||||||
|
- Use C# naming conventions:
|
||||||
|
- PascalCase for class, method, and property names
|
||||||
|
- camelCase for local variables and parameters
|
||||||
|
- _camelCase for private fields
|
||||||
|
|
||||||
|
- Add comments for complex code sections or patching methods
|
||||||
|
|
||||||
|
- Follow SOLID and DRY principles
|
||||||
|
|
||||||
|
## Testing
|
||||||
|
|
||||||
|
Before submitting a Pull Request, ensure that:
|
||||||
|
|
||||||
|
1. Your code compiles without errors
|
||||||
|
2. You've manually tested the functionality
|
||||||
|
3. The patch works with the current version of WeMod
|
||||||
|
4. Changes don't break existing functionality
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
By contributing, you agree that your contributions will be licensed under the [Apache License 2.0](LICENSE.md).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
Thank you for contributing to the WeMod Patcher project!
|
||||||
@@ -1,4 +1,8 @@
|
|||||||
<div align="center">
|
<div align="center">
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
---
|
||||||
<h1>WeMod Patcher</h1>
|
<h1>WeMod Patcher</h1>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -15,11 +19,14 @@ With this patch you will be able to use the latest version together with Pro.
|
|||||||
## 💫 What features will be available?
|
## 💫 What features will be available?
|
||||||
|
|
||||||
✅ Unlimited usage time <br/>
|
✅ Unlimited usage time <br/>
|
||||||
✅ No ads <br/>
|
✅ Disabling automatic updates (optional) <br/>
|
||||||
|
✅ Automatic patching of new WeMod versions <br/>
|
||||||
✅ AI Game guides <br/>
|
✅ AI Game guides <br/>
|
||||||
✅ Saving mods <br/>
|
✅ Saving mods <br/>
|
||||||
|
✅ Exclusive to pro subscription customization for hacks <br/>
|
||||||
|
✅ Hotkeys (hotkey functionality is broken after static patching for unknown reason) <br/>
|
||||||
❌ Connect phone <br/>
|
❌ Connect phone <br/>
|
||||||
❌ Hotkeys (hotkey functionality breaks after patch for unknown reason)
|
|
||||||
|
|
||||||
## 👀 How to use?
|
## 👀 How to use?
|
||||||
|
|
||||||
@@ -34,15 +41,28 @@ With this patch you will be able to use the latest version together with Pro.
|
|||||||
- I applied the patch but when I inject I get stuck on 'Loading mods...'.
|
- I applied the patch but when I inject I get stuck on 'Loading mods...'.
|
||||||
- Just close WeMod and try again
|
- Just close WeMod and try again
|
||||||
- During the game, some hacks are enabled without my input
|
- During the game, some hacks are enabled without my input
|
||||||
- This is a bug after the patch, you have to turn off hotkeys in WeMod settings
|
- This is a bug after the static patch, you have to turn off hotkeys in WeMod settings
|
||||||
- Why is the patch executable file size so large? It seems to me that you want to harm my system.
|
- VirusTotal claims that this program is a malware/trojan.
|
||||||
- The thing is that the application is written in Electron, so it also puts chromium, nodejs and some libraries in the exe. Maybe Electron is a temporary solution and in the future I will consider another option
|
- Perhaps the patcher does have the same signatures as malware (virtual memory patching). But this is a false positive, you can look at the source code or even build the patcher yourself.
|
||||||
|
- Does this application transfer any data to the Internet from my computer?
|
||||||
|
- The short answer is NO. This application does not need access to the Internet. The most it does is download updates if you want it to.
|
||||||
|
- What makes this application better than other patchers?
|
||||||
|
- All actions related to patches are performed on your computer. No files of unknown origin will be downloaded.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
## 🖼️ Screenshots
|
||||||
|

|
||||||
|

|
||||||
|
---
|
||||||
|
|
||||||
## 📜 License
|
## 📜 License
|
||||||
This project is licensed under the Apache-2.0 - see the [LICENSE](LICENSE.txt) file for details.
|
This project is licensed under the Apache-2.0 - see the [LICENSE](LICENSE.md) file for details.
|
||||||
|
|
||||||
---
|
---
|
||||||
## ❤️ Support
|
## ❤️ Support
|
||||||
[](https://ko-fi.com/kitbyte)
|
[](https://ko-fi.com/kitbyte)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
[](https://www.star-history.com/#k1tbyte/Wemod-Patcher&Date)
|
||||||
@@ -8,8 +8,10 @@ namespace WeModPatcher
|
|||||||
{
|
{
|
||||||
public const string RepoName = "Wemod-Patcher";
|
public const string RepoName = "Wemod-Patcher";
|
||||||
public const string Owner = "k1tbyte";
|
public const string Owner = "k1tbyte";
|
||||||
|
/*public const string PatchRegistryName = "patchRegistry.json";*/
|
||||||
public static readonly string RepositoryUrl = $"https://github.com/{Owner}/{RepoName}";
|
public static readonly string RepositoryUrl = $"https://github.com/{Owner}/{RepoName}";
|
||||||
public static readonly Version Version;
|
public static readonly Version Version;
|
||||||
|
public static readonly string[] WeModBrandNames = { "Wand", "WeMod" };
|
||||||
|
|
||||||
// cmp dword ptr [rdx], 0
|
// cmp dword ptr [rdx], 0
|
||||||
// jnz loc_XXXXXXXX
|
// jnz loc_XXXXXXXX
|
||||||
|
|||||||
@@ -3,8 +3,6 @@ using System.Collections.Generic;
|
|||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
using System.Threading;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using WeModPatcher.Models;
|
using WeModPatcher.Models;
|
||||||
using WeModPatcher.Utils;
|
using WeModPatcher.Utils;
|
||||||
using WeModPatcher.Utils.Win32;
|
using WeModPatcher.Utils.Win32;
|
||||||
@@ -15,24 +13,24 @@ namespace WeModPatcher.Core
|
|||||||
|
|
||||||
public class RuntimePatcher
|
public class RuntimePatcher
|
||||||
{
|
{
|
||||||
private readonly string _exePath;
|
private readonly WeModConfig _config;
|
||||||
|
|
||||||
public RuntimePatcher(string exePath)
|
public RuntimePatcher(WeModConfig config)
|
||||||
{
|
{
|
||||||
_exePath = exePath;
|
_config = config;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void StartProcess()
|
public void StartProcess()
|
||||||
{
|
{
|
||||||
if(string.IsNullOrEmpty(_exePath))
|
if(string.IsNullOrEmpty(_config?.ExecutablePath))
|
||||||
{
|
{
|
||||||
throw new Exception("Path is not specified");
|
throw new Exception("Path is not specified");
|
||||||
}
|
}
|
||||||
|
|
||||||
KillWeMod();
|
Common.TryKillProcess(_config.BrandName);
|
||||||
var startupInfo = new Imports.StartupInfo { cb = Marshal.SizeOf(typeof(Imports.StartupInfo)) };
|
var startupInfo = new Imports.StartupInfo { cb = Marshal.SizeOf(typeof(Imports.StartupInfo)) };
|
||||||
if(!Imports.CreateProcessA(_exePath,
|
if(!Imports.CreateProcessA(_config.ExecutablePath,
|
||||||
null,
|
null,
|
||||||
IntPtr.Zero,
|
IntPtr.Zero,
|
||||||
IntPtr.Zero,
|
IntPtr.Zero,
|
||||||
@@ -43,21 +41,39 @@ namespace WeModPatcher.Core
|
|||||||
}
|
}
|
||||||
|
|
||||||
var debugEvent = new Imports.DEBUG_EVENT();
|
var debugEvent = new Imports.DEBUG_EVENT();
|
||||||
var processIds = new List<uint>();
|
var processIds = new Dictionary<uint, bool>();
|
||||||
while (Imports.WaitForDebugEvent(ref debugEvent, 1000))
|
while (Imports.WaitForDebugEvent(ref debugEvent, uint.MaxValue))
|
||||||
{
|
{
|
||||||
|
uint continueStatus = Imports.DBG_CONTINUE;
|
||||||
var code = debugEvent.dwDebugEventCode;
|
var code = debugEvent.dwDebugEventCode;
|
||||||
|
// Console.WriteLine("Debug event code: " + code);
|
||||||
if (code == Imports.CREATE_PROCESS_DEBUG_EVENT)
|
if (code == Imports.CREATE_PROCESS_DEBUG_EVENT)
|
||||||
{
|
{
|
||||||
processIds.Add(debugEvent.dwProcessId);
|
// 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)
|
else if (code == Imports.EXCEPTION_DEBUG_EVENT)
|
||||||
{
|
{
|
||||||
var exceptionInfo = Imports.MapUnmanagedStructure<Imports.EXCEPTION_DEBUG_INFO>(debugEvent.Union);
|
// pass the exception to the process
|
||||||
|
continueStatus = Imports.DBG_EXCEPTION_NOT_HANDLED;
|
||||||
|
|
||||||
if (exceptionInfo.ExceptionRecord.ExceptionCode == Imports.EXCEPTION_BREAKPOINT)
|
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);
|
var process = Process.GetProcessById((int)debugEvent.dwProcessId);
|
||||||
|
// Console.WriteLine("Scanning process: " + process.ProcessName + " " + process.Id);
|
||||||
var address = MemoryUtils.ScanVirtualMemory(
|
var address = MemoryUtils.ScanVirtualMemory(
|
||||||
process.Handle,
|
process.Handle,
|
||||||
process.Modules[0].BaseAddress,
|
process.Modules[0].BaseAddress,
|
||||||
@@ -67,7 +83,7 @@ namespace WeModPatcher.Core
|
|||||||
|
|
||||||
if (address != IntPtr.Zero)
|
if (address != IntPtr.Zero)
|
||||||
{
|
{
|
||||||
MemoryUtils.SafeWriteVirtualMemory(
|
processIds[debugEvent.dwProcessId] = MemoryUtils.SafeWriteVirtualMemory(
|
||||||
process.Handle,
|
process.Handle,
|
||||||
address + Constants.ExePatchSignature.Offset,
|
address + Constants.ExePatchSignature.Offset,
|
||||||
Constants.ExePatchSignature.PatchBytes
|
Constants.ExePatchSignature.PatchBytes
|
||||||
@@ -87,12 +103,12 @@ namespace WeModPatcher.Core
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Imports.ContinueDebugEvent(debugEvent.dwProcessId, debugEvent.dwThreadId, Imports.DBG_CONTINUE);
|
Imports.ContinueDebugEvent(debugEvent.dwProcessId, debugEvent.dwThreadId, continueStatus);
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (var processId in processIds)
|
foreach (var entry in processIds)
|
||||||
{
|
{
|
||||||
Imports.DebugActiveProcessStop(processId);
|
Imports.DebugActiveProcessStop(entry.Key);
|
||||||
}
|
}
|
||||||
|
|
||||||
Imports.CloseHandle(processInfo.hProcess);
|
Imports.CloseHandle(processInfo.hProcess);
|
||||||
@@ -100,56 +116,29 @@ namespace WeModPatcher.Core
|
|||||||
|
|
||||||
public static void Patch(PatchConfig config, Action<string, ELogType> logger)
|
public static void Patch(PatchConfig config, Action<string, ELogType> logger)
|
||||||
{
|
{
|
||||||
if (config.Path == null)
|
if (config.AppProps == null)
|
||||||
{
|
{
|
||||||
throw new Exception("Path is not specified");
|
throw new Exception("Path is not specified");
|
||||||
}
|
}
|
||||||
|
|
||||||
var parent = Directory.GetParent(config.Path)?.FullName ?? config.Path;
|
var parent = Directory.GetParent(config.AppProps.RootDirectory)?.FullName ?? config.AppProps.RootDirectory;
|
||||||
var latestPath = Extensions.FindLatestWeMod(parent) ?? config.Path;
|
var latestWeModConfig = config.AutoApplyPatches ? Extensions.FindLatestWeMod(parent) ?? config.AppProps : config.AppProps;
|
||||||
|
|
||||||
if (!Extensions.CheckWeModPath(latestPath))
|
if (Extensions.CheckWeModPath(latestWeModConfig.RootDirectory) == null)
|
||||||
{
|
{
|
||||||
throw new Exception("Invalid WeMod path");
|
throw new Exception("Invalid WeMod path");
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!File.Exists(Path.Combine(latestPath, "resources", "app.asar.backup")))
|
if(!File.Exists(Path.Combine(latestWeModConfig.RootDirectory, "resources", "app.asar.backup")))
|
||||||
{
|
{
|
||||||
config.PatchMethod = EPatchProcessMethod.None;
|
config.PatchMethod = EPatchProcessMethod.None;
|
||||||
new StaticPatcher(latestPath, logger, config).Patch();
|
new StaticPatcher(latestWeModConfig, logger, config).Patch();
|
||||||
}
|
}
|
||||||
|
|
||||||
new RuntimePatcher(Path.Combine(latestPath, "WeMod.exe"))
|
new RuntimePatcher(latestWeModConfig)
|
||||||
.StartProcess();
|
.StartProcess();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public static void KillWeMod()
|
|
||||||
{
|
|
||||||
Process[] processes = Process.GetProcessesByName("WeMod");
|
|
||||||
for (int i = 0; processes.Length > i || i < 5; i++)
|
|
||||||
{
|
|
||||||
foreach (var process in processes)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
process.Kill();
|
|
||||||
}
|
|
||||||
catch
|
|
||||||
{
|
|
||||||
// ignored
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
processes = Process.GetProcessesByName("WeMod");
|
|
||||||
Thread.Sleep(250);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (processes.Length > 0)
|
|
||||||
{
|
|
||||||
throw new Exception("Failed to kill WeMod");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -46,25 +46,23 @@ namespace WeModPatcher.Core
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
private readonly string _weModRootFolder;
|
private readonly WeModConfig _weModConfig;
|
||||||
private readonly Action<string, ELogType> _logger;
|
private readonly Action<string, ELogType> _logger;
|
||||||
private readonly PatchConfig _config;
|
private readonly PatchConfig _config;
|
||||||
private readonly string _asarPath;
|
private readonly string _asarPath;
|
||||||
private readonly string _backupPath;
|
private readonly string _backupPath;
|
||||||
private readonly string _unpackedPath;
|
private readonly string _unpackedPath;
|
||||||
private int _sumOfPatches = 0;
|
private int _sumOfPatches = 0;
|
||||||
private readonly string _exePath;
|
|
||||||
|
|
||||||
public StaticPatcher(string weModRootFolder, Action<string, ELogType> logger, PatchConfig config)
|
public StaticPatcher(WeModConfig weModConfig, Action<string, ELogType> logger, PatchConfig config)
|
||||||
{
|
{
|
||||||
_weModRootFolder = weModRootFolder;
|
_weModConfig = weModConfig;
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
_config = config;
|
_config = config;
|
||||||
|
|
||||||
_asarPath = Path.Combine(weModRootFolder, "resources", "app.asar");
|
_asarPath = Path.Combine(weModConfig.RootDirectory, "resources", "app.asar");
|
||||||
_unpackedPath = Path.Combine(weModRootFolder, "resources", "app.asar.unpacked");
|
_unpackedPath = Path.Combine(weModConfig.RootDirectory, "resources", "app.asar.unpacked");
|
||||||
_backupPath = Path.Combine(weModRootFolder, "resources", "app.asar.backup");
|
_backupPath = Path.Combine(weModConfig.RootDirectory, "resources", "app.asar.backup");
|
||||||
_exePath = Path.Combine(_weModRootFolder, "WeMod.exe");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static string GetFetchFieldName(string targetFunction)
|
private static string GetFetchFieldName(string targetFunction)
|
||||||
@@ -143,7 +141,11 @@ namespace WeModPatcher.Core
|
|||||||
private void PatchPe()
|
private void PatchPe()
|
||||||
{
|
{
|
||||||
_logger("[PATCHER] Patching PE...", ELogType.Info);
|
_logger("[PATCHER] Patching PE...", ELogType.Info);
|
||||||
var patchResult = MemoryUtils.PatchFile(_exePath,Constants.ExePatchSignature, Constants.ExePatchSignature.PatchBytes);
|
var patchResult = MemoryUtils.PatchFile(
|
||||||
|
_weModConfig.ExecutablePath,
|
||||||
|
Constants.ExePatchSignature,
|
||||||
|
Constants.ExePatchSignature.PatchBytes
|
||||||
|
);
|
||||||
if(patchResult == -1)
|
if(patchResult == -1)
|
||||||
{
|
{
|
||||||
_logger("[PATCHER] Failed to patch PE", ELogType.Error);
|
_logger("[PATCHER] Failed to patch PE", ELogType.Error);
|
||||||
@@ -161,24 +163,29 @@ namespace WeModPatcher.Core
|
|||||||
CheckPathExists = true,
|
CheckPathExists = true,
|
||||||
AddExtension = true,
|
AddExtension = true,
|
||||||
SupportMultiDottedExtensions = false,
|
SupportMultiDottedExtensions = false,
|
||||||
FileName = "WeMod",
|
FileName = _weModConfig.BrandName,
|
||||||
};
|
};
|
||||||
|
|
||||||
if(fileDialog.ShowDialog() != DialogResult.OK)
|
if(fileDialog.ShowDialog() != DialogResult.OK)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
_config.Path = _weModRootFolder;
|
_config.Path = _weModConfig.RootDirectory;
|
||||||
|
var json = JsonConvert.SerializeObject(_config, new JsonSerializerSettings
|
||||||
var json = JsonConvert.SerializeObject(_config, Formatting.None);
|
{
|
||||||
|
NullValueHandling = NullValueHandling.Ignore,
|
||||||
|
DefaultValueHandling = DefaultValueHandling.Ignore,
|
||||||
|
Formatting = Formatting.None
|
||||||
|
});
|
||||||
|
|
||||||
Utils.Win32.Shortcut.CreateShortcut(
|
Utils.Win32.Shortcut.CreateShortcut(
|
||||||
fileName: fileDialog.FileName + ".lnk",
|
fileName: fileDialog.FileName + ".lnk",
|
||||||
targetPath: Assembly.GetExecutingAssembly().Location,
|
targetPath: Assembly.GetExecutingAssembly().Location,
|
||||||
arguments: Extensions.Base64Encode(json),
|
arguments: Extensions.Base64Encode(json),
|
||||||
workingDirectory: Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location),
|
workingDirectory: Common.GetCurrentDir(),
|
||||||
description: null,
|
description: null,
|
||||||
iconPath: _exePath
|
iconPath: _weModConfig.ExecutablePath
|
||||||
);
|
);
|
||||||
|
|
||||||
_logger("[PATCHER] The shortcut has been created, now you should only run WeMod through this shortcut", ELogType.Success);
|
_logger("[PATCHER] The shortcut has been created, now you should only run WeMod through this shortcut", ELogType.Success);
|
||||||
@@ -186,7 +193,7 @@ namespace WeModPatcher.Core
|
|||||||
|
|
||||||
public void Patch()
|
public void Patch()
|
||||||
{
|
{
|
||||||
RuntimePatcher.KillWeMod();
|
Common.TryKillProcess(_weModConfig.BrandName);
|
||||||
if (!File.Exists(_backupPath))
|
if (!File.Exists(_backupPath))
|
||||||
{
|
{
|
||||||
_logger("[PATCHER] Creating backup...", ELogType.Info);
|
_logger("[PATCHER] Creating backup...", ELogType.Info);
|
||||||
|
|||||||
@@ -1,4 +1,8 @@
|
|||||||
using System.Collections.Generic;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
using WeModPatcher.Utils;
|
||||||
|
|
||||||
namespace WeModPatcher.Models
|
namespace WeModPatcher.Models
|
||||||
{
|
{
|
||||||
@@ -16,11 +20,106 @@ namespace WeModPatcher.Models
|
|||||||
Runtime = 1,
|
Runtime = 1,
|
||||||
Static = 2
|
Static = 2
|
||||||
}
|
}
|
||||||
|
|
||||||
public sealed class PatchConfig
|
/*public sealed class PatchConfigOld
|
||||||
{
|
{
|
||||||
public HashSet<EPatchType> PatchTypes { get; set; }
|
public HashSet<EPatchType> PatchTypes { get; set; }
|
||||||
public EPatchProcessMethod PatchMethod { get; set; }
|
public EPatchProcessMethod PatchMethod { get; set; }
|
||||||
public string Path { get; set; }
|
public string Path { get; set; }
|
||||||
|
}*/
|
||||||
|
|
||||||
|
public sealed class PatchConfig
|
||||||
|
{
|
||||||
|
private string _path;
|
||||||
|
public HashSet<EPatchType> PatchTypes { get; set; }
|
||||||
|
public EPatchProcessMethod PatchMethod { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("u")]
|
||||||
|
public bool AutoApplyPatches { get; set; }
|
||||||
|
|
||||||
|
[JsonIgnore]
|
||||||
|
public WeModConfig AppProps { get; private set; }
|
||||||
|
|
||||||
|
public string Path
|
||||||
|
{
|
||||||
|
get => _path;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
_path = value;
|
||||||
|
AppProps = Extensions.CheckWeModPath(_path) ?? throw new Exception("Invalid WeMod path");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*public static void PushConfig(PatchConfig config)
|
||||||
|
{
|
||||||
|
var hash = GetConfigHash(config);
|
||||||
|
var registry = _getRegistry();
|
||||||
|
registry[hash] = config;
|
||||||
|
_stashRegistry(registry);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void ActualizeRegistry()
|
||||||
|
{
|
||||||
|
var registry = _getRegistry();
|
||||||
|
foreach (var entry in registry)
|
||||||
|
{
|
||||||
|
if(Extensions.CheckWeModPath(entry.Value.AppProps.RootDirectory) == null)
|
||||||
|
{
|
||||||
|
registry.Remove(entry.Key);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_stashRegistry(registry);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static PatchConfig GetConfig(string hash)
|
||||||
|
{
|
||||||
|
var registry = _getRegistry();
|
||||||
|
return registry.TryGetValue(hash, out var config) ? config : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string GetConfigHash(PatchConfig config)
|
||||||
|
{
|
||||||
|
return Common.ComputeSha256Hash(config.AppProps.ExecutablePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Dictionary<string, PatchConfig> _getRegistry()
|
||||||
|
{
|
||||||
|
var currentDir = Common.GetCurrentDir();
|
||||||
|
var registryPath = Path.Combine(currentDir, Constants.PatchRegistryName);
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return JsonConvert.DeserializeObject<Dictionary<string, PatchConfig>>(
|
||||||
|
File.ReadAllText(registryPath)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
// ignored
|
||||||
|
}
|
||||||
|
|
||||||
|
return new Dictionary<string, PatchConfig>();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void _stashRegistry(Dictionary<string, PatchConfig> registry)
|
||||||
|
{
|
||||||
|
|
||||||
|
var currentDir = Common.GetCurrentDir();
|
||||||
|
var registryPath = Path.Combine(currentDir, Constants.PatchRegistryName);
|
||||||
|
|
||||||
|
if(registry.Count == 0)
|
||||||
|
{
|
||||||
|
if(File.Exists(registryPath))
|
||||||
|
{
|
||||||
|
File.Delete(registryPath);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
var json = JsonConvert.SerializeObject(registry, Formatting.Indented);
|
||||||
|
File.WriteAllText(registryPath, json);
|
||||||
|
}*/
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
using Newtonsoft.Json;
|
||||||
|
|
||||||
|
namespace WeModPatcher.Models
|
||||||
|
{
|
||||||
|
public class WeModConfig
|
||||||
|
{
|
||||||
|
public string BrandName { get; set; }
|
||||||
|
public string ExecutableName { get; set; }
|
||||||
|
public string RootDirectory { get; set; }
|
||||||
|
|
||||||
|
[JsonIgnore]
|
||||||
|
public string ExecutablePath => System.IO.Path.Combine(RootDirectory, ExecutableName);
|
||||||
|
|
||||||
|
public override string ToString()
|
||||||
|
{
|
||||||
|
return RootDirectory;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,6 +2,8 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Collections.ObjectModel;
|
using System.Collections.ObjectModel;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
|
using System.IO;
|
||||||
|
using System.Reflection;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using System.Windows.Forms;
|
using System.Windows.Forms;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
|
|||||||
@@ -51,5 +51,5 @@ using System.Windows;
|
|||||||
// You can specify all the values or you can default the Build and Revision Numbers
|
// You can specify all the values or you can default the Build and Revision Numbers
|
||||||
// by using the '*' as shown below:
|
// by using the '*' as shown below:
|
||||||
// [assembly: AssemblyVersion("1.0.*")]
|
// [assembly: AssemblyVersion("1.0.*")]
|
||||||
[assembly: AssemblyVersion("1.0.0.0")]
|
[assembly: AssemblyVersion("1.0.4.0")]
|
||||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
[assembly: AssemblyFileVersion("1.0.4.0")]
|
||||||
@@ -0,0 +1,54 @@
|
|||||||
|
using System;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.IO;
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Threading;
|
||||||
|
|
||||||
|
namespace WeModPatcher.Utils
|
||||||
|
{
|
||||||
|
public static class Common
|
||||||
|
{
|
||||||
|
public static void TryKillProcess(string processName)
|
||||||
|
{
|
||||||
|
Process[] processes = Process.GetProcessesByName(processName);
|
||||||
|
for (int i = 0; processes.Length > i || i < 5; i++)
|
||||||
|
{
|
||||||
|
foreach (var process in processes)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
process.Kill();
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
// ignored
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
processes = Process.GetProcessesByName(processName);
|
||||||
|
Thread.Sleep(250);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (processes.Length > 0)
|
||||||
|
{
|
||||||
|
throw new Exception("Failed to kill WeMod");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string GetCurrentDir()
|
||||||
|
{
|
||||||
|
var assemblyLocation = Assembly.GetExecutingAssembly().Location;
|
||||||
|
return Path.GetDirectoryName(assemblyLocation) ?? throw new InvalidOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string ComputeSha256Hash(string input)
|
||||||
|
{
|
||||||
|
using (var sha256 = System.Security.Cryptography.SHA256.Create())
|
||||||
|
{
|
||||||
|
var bytes = System.Text.Encoding.UTF8.GetBytes(input);
|
||||||
|
var hashBytes = sha256.ComputeHash(bytes);
|
||||||
|
return BitConverter.ToString(hashBytes).Replace("-", "").ToLowerInvariant();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,36 +2,54 @@
|
|||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text.RegularExpressions;
|
using System.Text.RegularExpressions;
|
||||||
|
using WeModPatcher.Models;
|
||||||
|
|
||||||
namespace WeModPatcher.Utils
|
namespace WeModPatcher.Utils
|
||||||
{
|
{
|
||||||
public static class Extensions
|
public static class Extensions
|
||||||
{
|
{
|
||||||
public static bool CheckWeModPath(string root)
|
public static WeModConfig CheckWeModPath(string versionRoot)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
return File.Exists(Path.Combine(root, "WeMod.exe")) &&
|
|
||||||
File.Exists(Path.Combine(root, "resources", "app.asar"));
|
foreach (var name in Constants.WeModBrandNames)
|
||||||
|
{
|
||||||
|
var exeName = $"{name}.exe";
|
||||||
|
var path = Path.Combine(versionRoot, exeName);
|
||||||
|
if (File.Exists(path) && File.Exists(Path.Combine(versionRoot, "resources", "app.asar")))
|
||||||
|
{
|
||||||
|
return new WeModConfig
|
||||||
|
{
|
||||||
|
BrandName = name,
|
||||||
|
ExecutableName = exeName,
|
||||||
|
RootDirectory = versionRoot
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
{
|
{
|
||||||
return false;
|
// ignored
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static string FindWeModDirectory()
|
public static WeModConfig FindWeMod()
|
||||||
{
|
{
|
||||||
string localAppDataPath = Environment.GetEnvironmentVariable("LOCALAPPDATA");
|
string localAppDataPath = Environment.GetEnvironmentVariable("LOCALAPPDATA");
|
||||||
|
|
||||||
string defaultDir = Path.Combine(localAppDataPath ?? "", "WeMod");
|
|
||||||
|
|
||||||
if (!Directory.Exists(defaultDir))
|
foreach (var folder in Constants.WeModBrandNames)
|
||||||
{
|
{
|
||||||
return null;
|
var weModDir = Path.Combine(localAppDataPath ?? "", folder);
|
||||||
|
if(Directory.Exists(weModDir))
|
||||||
|
{
|
||||||
|
return FindLatestWeMod(weModDir);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return FindLatestWeMod(defaultDir);
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static string Base64Decode(string base64EncodedData)
|
public static string Base64Decode(string base64EncodedData)
|
||||||
@@ -46,7 +64,7 @@ namespace WeModPatcher.Utils
|
|||||||
return System.Convert.ToBase64String(plainTextBytes);
|
return System.Convert.ToBase64String(plainTextBytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static string FindLatestWeMod(string root)
|
public static WeModConfig FindLatestWeMod(string root)
|
||||||
{
|
{
|
||||||
var appFolders = Directory.EnumerateDirectories(root)
|
var appFolders = Directory.EnumerateDirectories(root)
|
||||||
.Select(folderPath => new DirectoryInfo(folderPath))
|
.Select(folderPath => new DirectoryInfo(folderPath))
|
||||||
@@ -59,13 +77,11 @@ namespace WeModPatcher.Utils
|
|||||||
})
|
})
|
||||||
.OrderByDescending(item => item.LastModified)
|
.OrderByDescending(item => item.LastModified)
|
||||||
.ToList();
|
.ToList();
|
||||||
|
|
||||||
|
|
||||||
return (
|
return appFolders
|
||||||
from folder
|
.Select(folder => CheckWeModPath(folder.Path))
|
||||||
in appFolders
|
.FirstOrDefault(config => config != null);
|
||||||
where CheckWeModPath(folder.Path)
|
|
||||||
select folder.Path
|
|
||||||
).FirstOrDefault();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -247,10 +247,12 @@ namespace WeModPatcher.Utils.Win32
|
|||||||
public const uint DEBUG_PROCESS = 0x00000001;
|
public const uint DEBUG_PROCESS = 0x00000001;
|
||||||
public const uint DBG_CONTINUE = 0x00010002;
|
public const uint DBG_CONTINUE = 0x00010002;
|
||||||
public const uint CREATE_PROCESS_DEBUG_EVENT = 3;
|
public const uint CREATE_PROCESS_DEBUG_EVENT = 3;
|
||||||
|
public const uint EXIT_PROCESS_DEBUG_EVENT = 5;
|
||||||
public const uint EXCEPTION_DEBUG_EVENT = 1;
|
public const uint EXCEPTION_DEBUG_EVENT = 1;
|
||||||
public const uint LOAD_DLL_DEBUG_EVENT = 6;
|
public const uint LOAD_DLL_DEBUG_EVENT = 6;
|
||||||
public const uint OUTPUT_DEBUG_STRING_EVENT = 8;
|
public const uint OUTPUT_DEBUG_STRING_EVENT = 8;
|
||||||
public const uint EXCEPTION_BREAKPOINT = 0x80000003;
|
public const uint EXCEPTION_BREAKPOINT = 0x80000003;
|
||||||
|
public const uint DBG_EXCEPTION_NOT_HANDLED = 0x80010001;
|
||||||
|
|
||||||
// Constants for VirtualProtectex
|
// Constants for VirtualProtectex
|
||||||
public const uint PAGE_EXECUTE_READWRITE = 0x40;
|
public const uint PAGE_EXECUTE_READWRITE = 0x40;
|
||||||
|
|||||||
@@ -90,7 +90,7 @@
|
|||||||
<Grid Margin="10" Cursor="Hand" Background="Transparent">
|
<Grid Margin="10" Cursor="Hand" Background="Transparent">
|
||||||
<TextBox Style="{StaticResource TitledTextBox}"
|
<TextBox Style="{StaticResource TitledTextBox}"
|
||||||
Uid="Folder path" IsReadOnly="True"
|
Uid="Folder path" IsReadOnly="True"
|
||||||
Text="{Binding WeModPath}"
|
Text="{Binding WeModInfo.RootDirectory, Mode=OneWay}"
|
||||||
VerticalAlignment="Center" Tag="Folder not found">
|
VerticalAlignment="Center" Tag="Folder not found">
|
||||||
</TextBox>
|
</TextBox>
|
||||||
<Grid.InputBindings>
|
<Grid.InputBindings>
|
||||||
|
|||||||
@@ -1,13 +1,8 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.ObjectModel;
|
using System.Collections.ObjectModel;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
|
||||||
using System.Security.Cryptography.X509Certificates;
|
|
||||||
using System.Text.RegularExpressions;
|
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using System.Windows.Forms;
|
using System.Windows.Forms;
|
||||||
using System.Windows.Threading;
|
|
||||||
using AsarSharp;
|
|
||||||
using WeModPatcher.Core;
|
using WeModPatcher.Core;
|
||||||
using WeModPatcher.Models;
|
using WeModPatcher.Models;
|
||||||
using WeModPatcher.ReactiveUICore;
|
using WeModPatcher.ReactiveUICore;
|
||||||
@@ -24,18 +19,18 @@ namespace WeModPatcher.View.MainWindow
|
|||||||
public ObservableCollection<LogEntry> LogList { get; set; } = new ObservableCollection<LogEntry>();
|
public ObservableCollection<LogEntry> LogList { get; set; } = new ObservableCollection<LogEntry>();
|
||||||
private static Updater _updater = new Updater();
|
private static Updater _updater = new Updater();
|
||||||
|
|
||||||
private string _weModPath;
|
private WeModConfig _weModConfig;
|
||||||
|
|
||||||
public string WeModPath
|
public WeModConfig WeModInfo
|
||||||
{
|
{
|
||||||
get => _weModPath;
|
get => _weModConfig;
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
SetProperty(ref _weModPath, value);
|
SetProperty(ref _weModConfig, value);
|
||||||
if (value == null) return;
|
if (value == null) return;
|
||||||
|
|
||||||
Log($"WeMod directory found at '{_weModPath}'", ELogType.Success);
|
Log($"WeMod directory found at '{_weModConfig}' ({_weModConfig.ExecutableName})", ELogType.Success);
|
||||||
if (File.Exists(Path.Combine(_weModPath, "resources", "app.asar.backup")))
|
if (File.Exists(Path.Combine(_weModConfig.RootDirectory, "resources", "app.asar.backup")))
|
||||||
{
|
{
|
||||||
Log("WeMod already patched. If you want to patch again, please restore the backup first.", ELogType.Warn);
|
Log("WeMod already patched. If you want to patch again, please restore the backup first.", ELogType.Warn);
|
||||||
IsPatchEnabled = false;
|
IsPatchEnabled = false;
|
||||||
@@ -85,10 +80,12 @@ namespace WeModPatcher.View.MainWindow
|
|||||||
if (dialog.ShowDialog() != DialogResult.OK) return;
|
if (dialog.ShowDialog() != DialogResult.OK) return;
|
||||||
string selectedPath = dialog.SelectedPath;
|
string selectedPath = dialog.SelectedPath;
|
||||||
string fileName = Path.GetFileName(selectedPath);
|
string fileName = Path.GetFileName(selectedPath);
|
||||||
|
|
||||||
|
var info = Extensions.CheckWeModPath(selectedPath);
|
||||||
|
|
||||||
if (Extensions.CheckWeModPath(selectedPath))
|
if (info != null)
|
||||||
{
|
{
|
||||||
WeModPath = selectedPath;
|
WeModInfo = info;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -103,7 +100,7 @@ namespace WeModPatcher.View.MainWindow
|
|||||||
private void OnBackupRestoring(object param)
|
private void OnBackupRestoring(object param)
|
||||||
{
|
{
|
||||||
|
|
||||||
var backupPath = Path.Combine(WeModPath, "resources", "app.asar.backup");
|
var backupPath = Path.Combine(WeModInfo.RootDirectory, "resources", "app.asar.backup");
|
||||||
if (!File.Exists(backupPath))
|
if (!File.Exists(backupPath))
|
||||||
{
|
{
|
||||||
Log("Backup not found. Please dont delete it manually", ELogType.Error);
|
Log("Backup not found. Please dont delete it manually", ELogType.Error);
|
||||||
@@ -119,8 +116,11 @@ namespace WeModPatcher.View.MainWindow
|
|||||||
// This shit doesn't look at the hash and verify() always returns true
|
// This shit doesn't look at the hash and verify() always returns true
|
||||||
//using X509Certificate2 cert = new X509Certificate2(X509Certificate.CreateFromSignedFile(filePath));
|
//using X509Certificate2 cert = new X509Certificate2(X509Certificate.CreateFromSignedFile(filePath));
|
||||||
|
|
||||||
var restoreExeResult = MemoryUtils.PatchFile( Path.Combine( WeModPath, "WeMod.exe"),
|
var restoreExeResult = MemoryUtils.PatchFile(
|
||||||
Constants.ExePatchSignature, Constants.ExePatchSignature.OriginalBytes);
|
WeModInfo.ExecutablePath,
|
||||||
|
Constants.ExePatchSignature,
|
||||||
|
Constants.ExePatchSignature.OriginalBytes
|
||||||
|
);
|
||||||
if (restoreExeResult == -1)
|
if (restoreExeResult == -1)
|
||||||
{
|
{
|
||||||
Log("Failed to restore the backup. Please close the WeMod and try again.", ELogType.Error);
|
Log("Failed to restore the backup. Please close the WeMod and try again.", ELogType.Error);
|
||||||
@@ -129,7 +129,7 @@ namespace WeModPatcher.View.MainWindow
|
|||||||
{
|
{
|
||||||
Log(restoreExeResult == 0 ?
|
Log(restoreExeResult == 0 ?
|
||||||
"Signature exe is original, does not require restoration"
|
"Signature exe is original, does not require restoration"
|
||||||
: "WeMod.exe restored successfully", ELogType.Success);
|
: $"{WeModInfo.ExecutableName} restored successfully", ELogType.Success);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
@@ -138,7 +138,7 @@ namespace WeModPatcher.View.MainWindow
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
File.Copy(backupPath, Path.Combine(WeModPath, "resources", "app.asar"), true);
|
File.Copy(backupPath, Path.Combine(WeModInfo.RootDirectory, "resources", "app.asar"), true);
|
||||||
File.Delete(backupPath);
|
File.Delete(backupPath);
|
||||||
Log("Backup restored successfully.", ELogType.Success);
|
Log("Backup restored successfully.", ELogType.Success);
|
||||||
AlreadyPatched = false;
|
AlreadyPatched = false;
|
||||||
@@ -147,7 +147,7 @@ namespace WeModPatcher.View.MainWindow
|
|||||||
|
|
||||||
private void OnPatching(object param)
|
private void OnPatching(object param)
|
||||||
{
|
{
|
||||||
if (WeModPath == null)
|
if (WeModInfo == null)
|
||||||
{
|
{
|
||||||
Log("Can't be done. Please specify the directory first.", ELogType.Warn);
|
Log("Can't be done. Please specify the directory first.", ELogType.Warn);
|
||||||
return;
|
return;
|
||||||
@@ -161,7 +161,7 @@ namespace WeModPatcher.View.MainWindow
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
new StaticPatcher(WeModPath, Log, config).Patch();
|
new StaticPatcher(WeModInfo, Log, config).Patch();
|
||||||
AlreadyPatched = true;
|
AlreadyPatched = true;
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
@@ -217,8 +217,8 @@ namespace WeModPatcher.View.MainWindow
|
|||||||
RestoreBackupCommand = new RelayCommand(OnBackupRestoring);
|
RestoreBackupCommand = new RelayCommand(OnBackupRestoring);
|
||||||
UpdateCommand = new AsyncRelayCommand(OnUpdate);
|
UpdateCommand = new AsyncRelayCommand(OnUpdate);
|
||||||
|
|
||||||
WeModPath = Extensions.FindWeModDirectory();
|
WeModInfo = Extensions.FindWeMod();
|
||||||
if (WeModPath == null)
|
if (WeModInfo == null)
|
||||||
{
|
{
|
||||||
Log("WeMod directory not found.", ELogType.Error);
|
Log("WeMod directory not found.", ELogType.Error);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,6 +23,7 @@
|
|||||||
<RowDefinition Height="27"/>
|
<RowDefinition Height="27"/>
|
||||||
<RowDefinition Height="27"/>
|
<RowDefinition Height="27"/>
|
||||||
<RowDefinition Height="27"/>
|
<RowDefinition Height="27"/>
|
||||||
|
<RowDefinition Height="37"/>
|
||||||
<RowDefinition Height="Auto"/>
|
<RowDefinition Height="Auto"/>
|
||||||
</Grid.RowDefinitions>
|
</Grid.RowDefinitions>
|
||||||
|
|
||||||
@@ -34,8 +35,15 @@
|
|||||||
|
|
||||||
<TextBlock Grid.Row="2" VerticalAlignment="Center" Text="Disable updates"/>
|
<TextBlock Grid.Row="2" VerticalAlignment="Center" Text="Disable updates"/>
|
||||||
<CheckBox Grid.Row="2" x:Name="DisableUpdateBox" HorizontalAlignment="Right" VerticalAlignment="Center"/>
|
<CheckBox Grid.Row="2" x:Name="DisableUpdateBox" HorizontalAlignment="Right" VerticalAlignment="Center"/>
|
||||||
|
|
||||||
|
<TextBlock ToolTip="Disable if you want to use older versions separately and manage versions manually via different shortcuts"
|
||||||
|
ToolTipService.InitialShowDelay="300"
|
||||||
|
Grid.Row="3" VerticalAlignment="Center">
|
||||||
|
Apply the patch to new versions <LineBreak/> automatically (hover to see more)
|
||||||
|
</TextBlock>
|
||||||
|
<CheckBox Grid.Row="3" x:Name="AutoUpdates" HorizontalAlignment="Right" VerticalAlignment="Center" IsChecked="True"/>
|
||||||
|
|
||||||
<Button Grid.Row="3" Padding="0 5 0 5" Margin="0 15 0 0" Content="Continue"
|
<Button Grid.Row="4" Padding="0 5 0 5" Margin="0 15 0 0" Content="Continue"
|
||||||
Click="NextClicked"/>
|
Click="NextClicked"/>
|
||||||
</Grid>
|
</Grid>
|
||||||
|
|
||||||
|
|||||||
@@ -57,7 +57,8 @@ namespace WeModPatcher.View.Popups
|
|||||||
_onApply(new PatchConfig
|
_onApply(new PatchConfig
|
||||||
{
|
{
|
||||||
PatchTypes = result,
|
PatchTypes = result,
|
||||||
PatchMethod = method
|
PatchMethod = method,
|
||||||
|
AutoApplyPatches = AutoUpdates.IsChecked == true
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -67,12 +67,14 @@
|
|||||||
<Compile Include="Converters\ToVisibilityConverter.cs" />
|
<Compile Include="Converters\ToVisibilityConverter.cs" />
|
||||||
<Compile Include="Core\RuntimePatcher.cs" />
|
<Compile Include="Core\RuntimePatcher.cs" />
|
||||||
<Compile Include="Core\StaticPatcher.cs" />
|
<Compile Include="Core\StaticPatcher.cs" />
|
||||||
|
<Compile Include="Models\WeModConfig.cs" />
|
||||||
<Compile Include="Models\PatchConfig.cs" />
|
<Compile Include="Models\PatchConfig.cs" />
|
||||||
<Compile Include="Models\Signature.cs" />
|
<Compile Include="Models\Signature.cs" />
|
||||||
<Compile Include="Program.cs" />
|
<Compile Include="Program.cs" />
|
||||||
<Compile Include="ReactiveUICore\AsyncRelayCommand.cs" />
|
<Compile Include="ReactiveUICore\AsyncRelayCommand.cs" />
|
||||||
<Compile Include="ReactiveUICore\ObservableObject.cs" />
|
<Compile Include="ReactiveUICore\ObservableObject.cs" />
|
||||||
<Compile Include="ReactiveUICore\RelayCommand.cs" />
|
<Compile Include="ReactiveUICore\RelayCommand.cs" />
|
||||||
|
<Compile Include="Utils\Common.cs" />
|
||||||
<Compile Include="Utils\Extensions.cs" />
|
<Compile Include="Utils\Extensions.cs" />
|
||||||
<Compile Include="Utils\MemoryUtils.cs" />
|
<Compile Include="Utils\MemoryUtils.cs" />
|
||||||
<Compile Include="Utils\Updater.cs" />
|
<Compile Include="Utils\Updater.cs" />
|
||||||
|
|||||||
@@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0,0,256,256" width="170px" height="170px" fill-rule="nonzero"><g transform="translate(17.92,17.92) scale(0.86,0.86)"><g fill="#27272a" fill-rule="nonzero" stroke="none" stroke-width="1" stroke-linecap="butt" stroke-linejoin="miter" stroke-miterlimit="10" stroke-dasharray="" stroke-dashoffset="0" font-family="none" font-weight="none" font-size="none" text-anchor="none" style="mix-blend-mode: normal"><path d="M53.5814,276.83721c-41.10026,0 -74.4186,-33.31834 -74.4186,-74.4186v-148.83721c0,-41.10026 33.31834,-74.4186 74.4186,-74.4186h148.83721c41.10026,0 74.4186,33.31834 74.4186,74.4186v148.83721c0,41.10026 -33.31834,74.4186 -74.4186,74.4186z" id="shape"></path></g><g fill="#ffffff" fill-rule="nonzero" stroke="none" stroke-width="1" stroke-linecap="butt" stroke-linejoin="miter" stroke-miterlimit="10" stroke-dasharray="" stroke-dashoffset="0" font-family="none" font-weight="none" font-size="none" text-anchor="none" style="mix-blend-mode: normal"><g transform="scale(5.12,5.12)"><path d="M47.845,22.185l-20.03,-20.03c-1.543,-1.543 -4.046,-1.553 -5.729,0.002l-19.931,20.028c-1.542,1.542 -1.554,4.045 0,5.727l19.934,19.934c0.772,0.772 1.785,1.16 2.816,1.16c1.026,0 2.07,-0.385 2.91,-1.16l19.933,-19.934c1.605,-1.605 1.648,-4.175 0.097,-5.727zM18,27c-1.105,0 -2,-0.895 -2,-2c0,-1.105 0.895,-2 2,-2c1.105,0 2,0.895 2,2c0,1.105 -0.895,2 -2,2zM25,34c-1.105,0 -2,-0.895 -2,-2c0,-1.105 0.895,-2 2,-2c1.105,0 2,0.895 2,2c0,1.105 -0.895,2 -2,2zM25,20c-1.105,0 -2,-0.895 -2,-2c0,-1.105 0.895,-2 2,-2c1.105,0 2,0.895 2,2c0,1.105 -0.895,2 -2,2zM32,27c-1.105,0 -2,-0.895 -2,-2c0,-1.105 0.895,-2 2,-2c1.105,0 2,0.895 2,2c0,1.105 -0.895,2 -2,2z"></path></g></g></g></svg>
|
||||||
|
After Width: | Height: | Size: 1.7 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 77 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 115 KiB |
Reference in New Issue
Block a user