using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx.Configuration;
using BepInEx.Core.Logging.Interpolation;
using BepInEx.Logging;
using BepInEx.Preloader.Core.Patching;
using HarmonyLib;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: AssemblyTitle("ByteFiddler")]
[assembly: AssemblyProduct("ByteFiddler")]
[assembly: AssemblyDescription("BepInEx IL2CPP preloader patcher that finds and replaces a byte pattern in current process memory.")]
[assembly: AssemblyFileVersion("1.0")]
[assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
namespace BepInEx;
[PatcherPluginInfo("ByteFiddler", "ByteFiddler", "1.0")]
public class ByteFiddlerPatcher : BasePatcher
{
private static class NativeMethods
{
public static uint PAGE_EXECUTE_READWRITE = 64u;
[DllImport("kernel32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool VirtualProtect(IntPtr lpAddress, UIntPtr dwSize, uint flNewProtect, out uint lpflOldProtect);
}
public const string GUID = "ByteFiddler";
public const string PatcherName = "ByteFiddler";
public const string PatcherVersion = "1.0";
public override void Initialize()
{
//IL_004c: Unknown result type (might be due to invalid IL or missing references)
//IL_0053: Expected O, but got Unknown
ReadPatches(((BasePatcher)this).Config);
string[] files = Directory.GetFiles(Path.Join(Paths.BepInExRootPath, "hexpatches"));
foreach (string text in files)
{
((BasePatcher)this).Log.LogInfo((object)text);
if (text.EndsWith(".cfg"))
{
ConfigFile cfg = new ConfigFile(text, false);
ReadPatches(cfg);
}
}
}
private void ReadPatches(ConfigFile cfg)
{
Traverse val = Traverse.Create((object)cfg).Property("OrphanedEntries", (object[])null);
Dictionary<ConfigDefinition, string> dictionary = (val.PropertyExists() ? (val.GetValue() as Dictionary<ConfigDefinition, string>) : new Dictionary<ConfigDefinition, string>());
List<string> list = (from x in dictionary.Keys.Select((ConfigDefinition x) => x.Section).Distinct()
where x.StartsWith("Edit ")
orderby x
select x).ToList();
foreach (string item in list)
{
Apply(cfg, item);
}
}
private unsafe void Apply(ConfigFile cfg, string sectionName)
{
//IL_0101: Unknown result type (might be due to invalid IL or missing references)
//IL_0108: Expected O, but got Unknown
//IL_008d: Unknown result type (might be due to invalid IL or missing references)
//IL_0094: Expected O, but got Unknown
//IL_0224: Unknown result type (might be due to invalid IL or missing references)
//IL_022b: Expected O, but got Unknown
//IL_02f8: Unknown result type (might be due to invalid IL or missing references)
//IL_02ff: Expected O, but got Unknown
//IL_02ae: Unknown result type (might be due to invalid IL or missing references)
//IL_02b5: Expected O, but got Unknown
//IL_0418: Unknown result type (might be due to invalid IL or missing references)
//IL_041f: Expected O, but got Unknown
//IL_039c: Unknown result type (might be due to invalid IL or missing references)
//IL_03a3: Expected O, but got Unknown
Stopwatch stopwatch = Stopwatch.StartNew();
string moduleName = cfg.Bind<string>(sectionName, "Target Module Name", "GameAssembly.dll", "").Value.Trim();
string value = cfg.Bind<string>(sectionName, "Bytes To Find", "", "").Value;
string value2 = cfg.Bind<string>(sectionName, "Bytes To Write", "", "").Value;
bool flag = default(bool);
if (moduleName.Length == 0)
{
ManualLogSource log = ((BasePatcher)this).Log;
BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(36, 1, ref flag);
if (flag)
{
((BepInExLogInterpolatedStringHandler)val).AppendLiteral("[");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(sectionName);
((BepInExLogInterpolatedStringHandler)val).AppendLiteral("] Empty module name, doing nothing.");
}
log.LogInfo(val);
return;
}
ProcessModule processModule;
try
{
processModule = ((IEnumerable)Process.GetCurrentProcess().Modules).Cast<ProcessModule>().First((ProcessModule x) => x.ModuleName == moduleName);
}
catch (Exception ex)
{
ManualLogSource log2 = ((BasePatcher)this).Log;
BepInExErrorLogInterpolatedStringHandler val2 = new BepInExErrorLogInterpolatedStringHandler(28, 3, ref flag);
if (flag)
{
((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("[");
((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>(sectionName);
((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("] Failed to find module ");
((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>(moduleName);
((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(" - ");
((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<Exception>(ex);
}
log2.LogError(val2);
return;
}
byte[] array;
byte[] array2;
try
{
array = (from x in value.Split(' ', StringSplitOptions.RemoveEmptyEntries)
select Convert.ToByte(x, 16)).ToArray();
array2 = (from x in value2.Split(' ', StringSplitOptions.RemoveEmptyEntries)
select Convert.ToByte(x, 16)).ToArray();
}
catch (Exception ex2)
{
((BasePatcher)this).Log.LogError((object)("[" + sectionName + "] Failed to parse settings: " + ex2));
return;
}
if (array.Length == 0 || array2.Length == 0)
{
ManualLogSource log3 = ((BasePatcher)this).Log;
BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(41, 1, ref flag);
if (flag)
{
((BepInExLogInterpolatedStringHandler)val).AppendLiteral("[");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(sectionName);
((BepInExLogInterpolatedStringHandler)val).AppendLiteral("] Empty pattern or patch, doing nothing.");
}
log3.LogInfo(val);
return;
}
IntPtr baseAddress = processModule.BaseAddress;
int moduleMemorySize = processModule.ModuleMemorySize;
using UnmanagedMemoryStream unmanagedMemoryStream = new UnmanagedMemoryStream((byte*)(void*)baseAddress, moduleMemorySize, moduleMemorySize, FileAccess.ReadWrite);
long num = FindPosition(unmanagedMemoryStream, array);
if (num < 0)
{
ManualLogSource log4 = ((BasePatcher)this).Log;
BepInExWarningLogInterpolatedStringHandler val3 = new BepInExWarningLogInterpolatedStringHandler(55, 1, ref flag);
if (flag)
{
((BepInExLogInterpolatedStringHandler)val3).AppendLiteral("[");
((BepInExLogInterpolatedStringHandler)val3).AppendFormatted<string>(sectionName);
((BepInExLogInterpolatedStringHandler)val3).AppendLiteral("] Could not find the byte pattern, check the settings!");
}
log4.LogWarning(val3);
return;
}
ManualLogSource log5 = ((BasePatcher)this).Log;
BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(41, 2, ref flag);
if (flag)
{
((BepInExLogInterpolatedStringHandler)val).AppendLiteral("[");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(sectionName);
((BepInExLogInterpolatedStringHandler)val).AppendLiteral("] Found byte pattern at 0x");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<long>(baseAddress.ToInt64() + num, "X");
((BepInExLogInterpolatedStringHandler)val).AppendLiteral(", replacing...");
}
log5.LogInfo(val);
unmanagedMemoryStream.Seek(num, SeekOrigin.Begin);
IntPtr lpAddress = (IntPtr)unmanagedMemoryStream.PositionPointer;
if (!NativeMethods.VirtualProtect(lpAddress, (UIntPtr)(ulong)array2.Length, NativeMethods.PAGE_EXECUTE_READWRITE, out var lpflOldProtect))
{
ManualLogSource log6 = ((BasePatcher)this).Log;
BepInExErrorLogInterpolatedStringHandler val2 = new BepInExErrorLogInterpolatedStringHandler(61, 2, ref flag);
if (flag)
{
((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("[");
((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>(sectionName);
((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("] Failed to change memory protection, aborting. Error code: ");
((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<int>(Marshal.GetLastWin32Error());
}
log6.LogError(val2);
return;
}
unmanagedMemoryStream.Write(array2, 0, array2.Length);
NativeMethods.VirtualProtect(lpAddress, (UIntPtr)(ulong)array2.Length, lpflOldProtect, out var _);
ManualLogSource log7 = ((BasePatcher)this).Log;
val = new BepInExInfoLogInterpolatedStringHandler(40, 2, ref flag);
if (flag)
{
((BepInExLogInterpolatedStringHandler)val).AppendLiteral("[");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(sectionName);
((BepInExLogInterpolatedStringHandler)val).AppendLiteral("] Bytes overwritten successfully in ");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<long>(stopwatch.ElapsedMilliseconds);
((BepInExLogInterpolatedStringHandler)val).AppendLiteral("ms!");
}
log7.LogInfo(val);
}
private static long FindPosition(Stream stream, byte[] pattern)
{
long result = -1L;
int num = 0;
int num2;
while ((num2 = stream.ReadByte()) > -1)
{
if (pattern[num++] != num2)
{
stream.Position -= num - 1;
num = 0;
}
else if (num == pattern.Length)
{
result = stream.Position - num;
break;
}
}
return result;
}
}