Decompiled source of ByteFiddler v0.7.0

BepInEx/patchers/Patcher_ByteFiddler.dll

Decompiled a month ago
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;
	}
}