Compare commits

..

4 Commits

10 changed files with 200 additions and 24 deletions
+30
View File
@@ -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.
+20
View File
@@ -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
View File
@@ -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!
+3
View File
@@ -10,6 +10,9 @@ namespace WeModPatcher
public const string Owner = "k1tbyte";
public static readonly string RepositoryUrl = $"https://github.com/{Owner}/{RepoName}";
public static readonly Version Version;
public static readonly string WeModBrandName = "Wand";
public static readonly string WeModExeName = "Wand.exe";
public static readonly string[] WeModRootFolders = { "WeMod", "Wand" };
// cmp dword ptr [rdx], 0
// jnz loc_XXXXXXXX
+20 -11
View File
@@ -43,13 +43,16 @@ namespace WeModPatcher.Core
}
var debugEvent = new Imports.DEBUG_EVENT();
var processIds = new List<uint>();
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)
{
processIds.Add(debugEvent.dwProcessId);
// Console.WriteLine("Spawning process: " + debugEvent.dwProcessId);
processIds.Add(debugEvent.dwProcessId, false);
}
else if (code == Imports.EXIT_PROCESS_DEBUG_EVENT)
{
@@ -62,11 +65,17 @@ namespace WeModPatcher.Core
}
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);
// Console.WriteLine("Scanning process: " + process.ProcessName + " " + process.Id);
var address = MemoryUtils.ScanVirtualMemory(
process.Handle,
process.Modules[0].BaseAddress,
@@ -76,7 +85,7 @@ namespace WeModPatcher.Core
if (address != IntPtr.Zero)
{
MemoryUtils.SafeWriteVirtualMemory(
processIds[debugEvent.dwProcessId] = MemoryUtils.SafeWriteVirtualMemory(
process.Handle,
address + Constants.ExePatchSignature.Offset,
Constants.ExePatchSignature.PatchBytes
@@ -96,12 +105,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);
@@ -128,7 +137,7 @@ namespace WeModPatcher.Core
new StaticPatcher(latestPath, logger, config).Patch();
}
new RuntimePatcher(Path.Combine(latestPath, "WeMod.exe"))
new RuntimePatcher(Path.Combine(latestPath, Constants.WeModExeName))
.StartProcess();
}
@@ -136,7 +145,7 @@ namespace WeModPatcher.Core
public static void KillWeMod()
{
Process[] processes = Process.GetProcessesByName("WeMod");
Process[] processes = Process.GetProcessesByName(Constants.WeModBrandName);
for (int i = 0; processes.Length > i || i < 5; i++)
{
foreach (var process in processes)
@@ -151,7 +160,7 @@ namespace WeModPatcher.Core
}
}
processes = Process.GetProcessesByName("WeMod");
processes = Process.GetProcessesByName(Constants.WeModBrandName);
Thread.Sleep(250);
}
+2 -2
View File
@@ -64,7 +64,7 @@ namespace WeModPatcher.Core
_asarPath = Path.Combine(weModRootFolder, "resources", "app.asar");
_unpackedPath = Path.Combine(weModRootFolder, "resources", "app.asar.unpacked");
_backupPath = Path.Combine(weModRootFolder, "resources", "app.asar.backup");
_exePath = Path.Combine(_weModRootFolder, "WeMod.exe");
_exePath = Path.Combine(_weModRootFolder, Constants.WeModExeName);
}
private static string GetFetchFieldName(string targetFunction)
@@ -161,7 +161,7 @@ namespace WeModPatcher.Core
CheckPathExists = true,
AddExtension = true,
SupportMultiDottedExtensions = false,
FileName = "WeMod",
FileName = Constants.WeModBrandName,
};
if(fileDialog.ShowDialog() != DialogResult.OK)
+2 -2
View File
@@ -51,5 +51,5 @@ using System.Windows;
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.1.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyVersion("1.0.3.0")]
[assembly: AssemblyFileVersion("1.0.3.0")]
+9 -7
View File
@@ -11,7 +11,7 @@ namespace WeModPatcher.Utils
{
try
{
return File.Exists(Path.Combine(root, "WeMod.exe")) &&
return File.Exists(Path.Combine(root, Constants.WeModExeName)) &&
File.Exists(Path.Combine(root, "resources", "app.asar"));
}
catch
@@ -23,15 +23,17 @@ namespace WeModPatcher.Utils
public static string FindWeModDirectory()
{
string localAppDataPath = Environment.GetEnvironmentVariable("LOCALAPPDATA");
string defaultDir = Path.Combine(localAppDataPath ?? "", "WeMod");
if (!Directory.Exists(defaultDir))
foreach (var folder in Constants.WeModRootFolders)
{
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)
+1
View File
@@ -252,6 +252,7 @@ namespace WeModPatcher.Utils.Win32
public const uint LOAD_DLL_DEBUG_EVENT = 6;
public const uint OUTPUT_DEBUG_STRING_EVENT = 8;
public const uint EXCEPTION_BREAKPOINT = 0x80000003;
public const uint DBG_EXCEPTION_NOT_HANDLED = 0x80010001;
// Constants for VirtualProtectex
public const uint PAGE_EXECUTE_READWRITE = 0x40;
+2 -2
View File
@@ -119,7 +119,7 @@ namespace WeModPatcher.View.MainWindow
// This shit doesn't look at the hash and verify() always returns true
//using X509Certificate2 cert = new X509Certificate2(X509Certificate.CreateFromSignedFile(filePath));
var restoreExeResult = MemoryUtils.PatchFile( Path.Combine( WeModPath, "WeMod.exe"),
var restoreExeResult = MemoryUtils.PatchFile( Path.Combine( WeModPath, Constants.WeModExeName),
Constants.ExePatchSignature, Constants.ExePatchSignature.OriginalBytes);
if (restoreExeResult == -1)
{
@@ -129,7 +129,7 @@ namespace WeModPatcher.View.MainWindow
{
Log(restoreExeResult == 0 ?
"Signature exe is original, does not require restoration"
: "WeMod.exe restored successfully", ELogType.Success);
: $"{Constants.WeModExeName} restored successfully", ELogType.Success);
}
}
catch