diff --git a/SRLWrapper/Wrapper/Base/Wrapper.cs b/SRLWrapper/Wrapper/Base/Wrapper.cs index 5737ffc..f562314 100644 --- a/SRLWrapper/Wrapper/Base/Wrapper.cs +++ b/SRLWrapper/Wrapper/Base/Wrapper.cs @@ -51,7 +51,10 @@ static unsafe class Wrapper void* Handler = RealHandler = LoadLibraryW(DllPath); if (Handler == null) + { + MessageBoxW(null, "Library: " + DllPath, "SRL WRAPPER ERROR", 0x10); Environment.Exit(0x505);//ERROR_DELAY_LOAD_FAILED + } return Handler; } @@ -67,6 +70,7 @@ internal static T GetDelegate(void* Handler, string Function, bool Optional = return null; } + MessageBoxW(null, "Function: " + Function, "SRL WRAPPER ERROR", 0x10); Environment.Exit(0x505);//ERROR_DELAY_LOAD_FAILED } return (T)Marshal.GetDelegateForFunctionPointer(new IntPtr(Address), typeof(T)); diff --git a/SRLWrapper/Wrapper/D3D11.cs b/SRLWrapper/Wrapper/D3D11.cs index dd1cd0d..9de3d4d 100644 --- a/SRLWrapper/Wrapper/D3D11.cs +++ b/SRLWrapper/Wrapper/D3D11.cs @@ -25,8 +25,8 @@ public static void LoadRetail() dD3D11CreateDeviceAndSwapChain = GetDelegate(RealHandler, "D3D11CreateDeviceAndSwapChain", false); dD3D11CreateDevice = GetDelegate(RealHandler, "D3D11CreateDevice", false); dD3DKMTWaitForVerticalBlankEvent = GetDelegate(RealHandler, "D3DKMTWaitForVerticalBlankEvent", false); - dD3D11CreateDeviceForD3D12 = GetDelegate(RealHandler, "D3D11CreateDeviceForD3D12", false); - dD3D11On12CreateDevice = GetDelegate(RealHandler, "D3D11On12CreateDevice", false); + dD3D11CreateDeviceForD3D12 = GetDelegate(RealHandler, "D3D11CreateDeviceForD3D12", true); + dD3D11On12CreateDevice = GetDelegate(RealHandler, "D3D11On12CreateDevice", true); dD3DPerformance_BeginEvent = GetDelegate(RealHandler, "D3DPerformance_BeginEvent", false); dD3DPerformance_EndEvent = GetDelegate(RealHandler, "D3DPerformance_EndEvent", false); dD3DPerformance_GetStatus = GetDelegate(RealHandler, "D3DPerformance_GetStatus", false); @@ -38,8 +38,8 @@ public static void LoadRetail() dD3DKMTGetDeviceState = GetDelegate(RealHandler, "D3DKMTGetDeviceState", false); dD3DKMTOpenAdapterFromHdc = GetDelegate(RealHandler, "D3DKMTOpenAdapterFromHdc", false); dD3DKMTQueryResourceInfo = GetDelegate(RealHandler, "D3DKMTQueryResourceInfo", false); - dCreateDirect3D11DeviceFromDXGIDevice = GetDelegate(RealHandler, "CreateDirect3D11DeviceFromDXGIDevice", false); - dCreateDirect3D11SurfaceFromDXGISurface = GetDelegate(RealHandler, "CreateDirect3D11SurfaceFromDXGISurface", false); + dCreateDirect3D11DeviceFromDXGIDevice = GetDelegate(RealHandler, "CreateDirect3D11DeviceFromDXGIDevice", true); + dCreateDirect3D11SurfaceFromDXGISurface = GetDelegate(RealHandler, "CreateDirect3D11SurfaceFromDXGISurface", true); InitializeSRL(); } diff --git a/SRLWrapper/Wrapper/DXGI.cs b/SRLWrapper/Wrapper/DXGI.cs index 865eeac..d57df73 100644 --- a/SRLWrapper/Wrapper/DXGI.cs +++ b/SRLWrapper/Wrapper/DXGI.cs @@ -22,17 +22,17 @@ public static void LoadRetail() dCreateDXGIFactory1 = GetDelegate(RealHandler, "CreateDXGIFactory1", false); dCompatValue = GetDelegate(RealHandler, "CompatValue", false); dCompatString = GetDelegate(RealHandler, "CompatString", false); - dApplyCompatResolutionQuirking = GetDelegate(RealHandler, "ApplyCompatResolutionQuirking", false); - dCreateDXGIFactory2 = GetDelegate(RealHandler, "CreateDXGIFactory2", false); + dApplyCompatResolutionQuirking = GetDelegate(RealHandler, "ApplyCompatResolutionQuirking", true); + dCreateDXGIFactory2 = GetDelegate(RealHandler, "CreateDXGIFactory2", true); dDXGID3D10RegisterLayers = GetDelegate(RealHandler, "DXGID3D10RegisterLayers", false); - dPIXEndCapture = GetDelegate(RealHandler, "PIXEndCapture", false); + dPIXEndCapture = GetDelegate(RealHandler, "PIXEndCapture", true); dDXGID3D10GetLayeredDeviceSize = GetDelegate(RealHandler, "DXGID3D10GetLayeredDeviceSize", false); dDXGID3D10CreateLayeredDevice = GetDelegate(RealHandler, "DXGID3D10CreateLayeredDevice", false); dDXGID3D10CreateDevice = GetDelegate(RealHandler, "DXGID3D10CreateDevice", false); dDXGIReportAdapterConfiguration = GetDelegate(RealHandler, "DXGIReportAdapterConfiguration", false); dSetAppCompatStringPointer = GetDelegate(RealHandler, "SetAppCompatStringPointer", false); - dUpdateHMDEmulationStatus = GetDelegate(RealHandler, "UpdateHMDEmulationStatus", false); - dDXGIGetDebugInterface1 = GetDelegate(RealHandler, "DXGIGetDebugInterface1", false); + dUpdateHMDEmulationStatus = GetDelegate(RealHandler, "UpdateHMDEmulationStatus", true); + dDXGIGetDebugInterface1 = GetDelegate(RealHandler, "DXGIGetDebugInterface1", true); InitializeSRL(); } diff --git a/StringReloads/Engine/Main.cs b/StringReloads/Engine/Main.cs index 639b6be..b33b266 100644 --- a/StringReloads/Engine/Main.cs +++ b/StringReloads/Engine/Main.cs @@ -37,7 +37,8 @@ unsafe class Main new CreateFontIndirectW(), new GetGlyphOutlineA(), new GetGlyphOutlineW(), - new SysAllocString() + new SysAllocString(), + new MultiByteToWideChar() }); internal Mods.Base.IMod[] _Mods = null; diff --git a/StringReloads/Hook/Base/Hook.cs b/StringReloads/Hook/Base/Hook.cs index 35c7333..8a90409 100644 --- a/StringReloads/Hook/Base/Hook.cs +++ b/StringReloads/Hook/Base/Hook.cs @@ -1,10 +1,10 @@ using System; using Iced.Intel; using System.Runtime.InteropServices; - using static StringReloads.Hook.Base.Extensions; using System.Linq; using System.Collections.Generic; +using System.Reflection.Emit; namespace StringReloads.Hook.Base { @@ -89,7 +89,7 @@ public void Compile(void* Function) } #if x64 - const int JmpSize = 12; + public const int JmpSize = 12; private void AssemblyHook() { //Copy Minimal Instructions Amount @@ -107,10 +107,11 @@ private void AssemblyHook() var Writer = new MemoryCodeWriter(); var Compiler = Encoder.Create(64, Writer); - int HookSize = Instructions.GetEncodedSize(64); + int RHookSize = Instructions.GetEncodedSize(64, (ulong)Function); + int BypassSize = Instructions.GetAutoEncodedSize(64, (ulong)Function); - RealBuffer = new byte[HookSize]; - BypassBuffer = new byte[HookSize + JmpSize]; + RealBuffer = new byte[RHookSize]; + BypassBuffer = new byte[BypassSize]; DeprotectMemory(Function, (uint)BypassBuffer.LongLength); Marshal.Copy(new IntPtr(Function), RealBuffer, 0, RealBuffer.Length); @@ -124,7 +125,7 @@ private void AssemblyHook() Instructions.Add(Instruction.Create(Code.Mov_r64_imm64, Register.RAX, RetAddr)); Instructions.Add(Instruction.Create(Code.Jmp_rm64, Register.RAX)); - Compiler.Encode(Instructions, (ulong)phBuffer); + Compiler.AutoEncode(Instructions, (ulong)phBuffer); Writer.CopyTo(phBuffer, 0); @@ -142,7 +143,7 @@ private void AssemblyHook() HookBuffer = Writer.ToArray(); } #else - const int JmpSize = 5; + public const int JmpSize = 5; private void AssemblyHook() { //Copy Minimal Instructions Amount @@ -206,22 +207,39 @@ public void Uninstall() public static partial class Extensions { - public static int GetEncodedSize(this InstructionList List, int bitness) + public static int GetEncodedSize(this InstructionList List, int bitness, ulong IP = 0) + { + var Writer = new MemoryCodeWriter(); + var Compiler = Encoder.Create(bitness, Writer); + foreach (var Instruction in List) + { + Compiler.Encode(Instruction, (ulong)Writer.Count + IP); + } + + return Writer.Count; + } + public static int GetEncodedSize(this Instruction Instruction, int bitness, ulong IP = 0) + { + var Writer = new MemoryCodeWriter(); + var Compiler = Encoder.Create(bitness, Writer); + return (int)Compiler.Encode(Instruction, (ulong)Writer.Count + IP); + } + public static int GetAutoEncodedSize(this InstructionList List, int bitness, ulong IP = 0) { var Writer = new MemoryCodeWriter(); var Compiler = Encoder.Create(bitness, Writer); foreach (var Instruction in List) { - Compiler.Encode(Instruction, (ulong)Writer.Count); + Compiler.AutoEncode(Instruction, (ulong)Writer.Count + IP); } return Writer.Count; } - public static int GetEncodedSize(this Instruction Instruction, int bitness) + public static int GetAutoEncodedSize(this Instruction Instruction, int bitness, ulong IP = 0) { var Writer = new MemoryCodeWriter(); var Compiler = Encoder.Create(bitness, Writer); - return (int)Compiler.Encode(Instruction, (ulong)Writer.Count); + return (int)Compiler.AutoEncode(Instruction, (ulong)Writer.Count + IP); } public static uint Encode(this Encoder Encoder, InstructionList List, ulong IP) @@ -231,6 +249,13 @@ public static uint Encode(this Encoder Encoder, InstructionList List, ulong IP) Len += Encoder.Encode(Instruction, IP + Len); return Len; } + public static uint AutoEncode(this Encoder Encoder, InstructionList List, ulong IP) + { + uint Len = 0; + foreach (var Instruction in List) + Len += Encoder.AutoEncode(Instruction, IP + Len); + return Len; + } public static InstructionList DecodeMany(this Decoder Decoder, uint MinLength) { @@ -243,6 +268,85 @@ public static InstructionList DecodeMany(this Decoder Decoder, uint MinLength) return List; } + public static uint AutoEncode(this Encoder Encoder, Instruction Instruction, ulong IP) { + InstructionList List = new InstructionList(); + if (Encoder.Bitness <= 32) { + List.Add(Instruction); + } + else { + if (Instruction.IsJmp() && !Instruction.IsCallFar && Instruction.Op0Kind != OpKind.Register) { + + if (!Instruction.IsANotJmp()) + Instruction.NegateConditionCode(); + + var Jmp = Instruction.IPRelativeMemoryAddress.x64FarJmp(); + List.Add(Instruction.ConditionCode.ToShortJmp(14)); + List.AddRange(Jmp); + } + else + { + switch (Instruction.Code) + { + case Code.Mov_r64_rm64: + List.Add(Instruction.Create(Code.Mov_r64_imm64, Instruction.Op0Register, Instruction.IPRelativeMemoryAddress)); + List.Add(Instruction.Create(Code.Mov_r64_rm64, Instruction.Op0Register, new MemoryOperand(Instruction.Op0Register))); + break; + default: + List.Add(Instruction); + break; + } + } + } + uint TotalSize = 0; + foreach (var Inst in List) + TotalSize += Encoder.Encode(Inst, IP + TotalSize); + return TotalSize; + } + + public static bool IsANotJmp(this Instruction Instruction) => Instruction.ConditionCode switch { + ConditionCode.ne => true, + ConditionCode.no => true, + ConditionCode.np => true, + ConditionCode.ns => true, + _ => false + }; + + public static InstructionList x64FarJmp(this ulong Address) { + InstructionList List = new InstructionList(); + List.Add(Instruction.Create(Code.Pushq_imm32, unchecked((int)(Address & uint.MaxValue)))); + List.Add(Instruction.Create(Code.Mov_rm32_imm32, new MemoryOperand(Register.RSP), (uint)(Address >> 8 * 4))); + List.Add(Instruction.Create(Code.Retnq)); + return List; + } + + public static Instruction ToShortJmp(this ConditionCode Condition, ulong Address) { + return Condition switch { + ConditionCode.a => Instruction.CreateBranch(Code.Jae_rel16, Address), + ConditionCode.ae => Instruction.CreateBranch(Code.Jae_rel16, Address), + ConditionCode.b => Instruction.CreateBranch(Code.Jb_rel16, Address), + ConditionCode.be => Instruction.CreateBranch(Code.Jbe_rel16, Address), + ConditionCode.e => Instruction.CreateBranch(Code.Je_rel16, Address), + ConditionCode.g => Instruction.CreateBranch(Code.Jg_rel16, Address), + ConditionCode.ge => Instruction.CreateBranch(Code.Jge_rel16, Address), + ConditionCode.l => Instruction.CreateBranch(Code.Jl_rel16, Address), + ConditionCode.ne => Instruction.CreateBranch(Code.Jne_rel16, Address), + ConditionCode.no => Instruction.CreateBranch(Code.Jno_rel16, Address), + ConditionCode.np => Instruction.CreateBranch(Code.Jnp_rel16, Address), + ConditionCode.ns => Instruction.CreateBranch(Code.Jns_rel16, Address), + ConditionCode.o => Instruction.CreateBranch(Code.Jo_rel16, Address), + ConditionCode.p => Instruction.CreateBranch(Code.Jp_rel16, Address), + ConditionCode.s => Instruction.CreateBranch(Code.Js_rel16, Address), + _ => Instruction.CreateBranch(Code.Jmp_rel16, Address), + }; + } + + public static bool IsJmp(this Instruction Instruction) => + Instruction.IsJmpNear || Instruction.IsJmpNearIndirect || + Instruction.IsJmpShort || Instruction.IsJmpFar || + Instruction.IsJmpFarIndirect || Instruction.IsJmpShortOrNear || + Instruction.IsJccNear || Instruction.IsJccShort || + Instruction.IsJccShortOrNear; + public unsafe static byte* AllocUnsafe(uint Bytes) { return VirtualAlloc(null, Bytes, AllocationType.Reserve | AllocationType.Commit, MemoryProtection.ExecuteReadWrite);; diff --git a/StringReloads/Hook/Types/Delegates.cs b/StringReloads/Hook/Types/Delegates.cs index e2e34c5..706465b 100644 --- a/StringReloads/Hook/Types/Delegates.cs +++ b/StringReloads/Hook/Types/Delegates.cs @@ -32,4 +32,6 @@ namespace StringReloads.Hook [UnmanagedFunctionPointer(CallingConvention.Cdecl)] public unsafe delegate void SoftPAL_DrawTextDelegate(byte* Text, void* a2, void* a3, void* a4, void* a5, void* a6, void* a7, void* a8, void* a9, void* a10, void* a11, void* a12, void* a13, void* a14, void* a15, void* a16, void* a17, void* a18, void* a19, void* a20, void* a21, void* a22, void* a23); + [UnmanagedFunctionPointer(CallingConvention.Winapi)] + public unsafe delegate int MultiByteToWideCharDelegate(uint CodePage, uint dwFlags, byte* lpMultiByteStr, int cbMultiByte, ushort* lpWideCharStr, int cchWideChar); } diff --git a/StringReloads/Hook/Win32/MultiByteToWideChar.cs b/StringReloads/Hook/Win32/MultiByteToWideChar.cs new file mode 100644 index 0000000..30878eb --- /dev/null +++ b/StringReloads/Hook/Win32/MultiByteToWideChar.cs @@ -0,0 +1,42 @@ +namespace StringReloads.Hook +{ + public unsafe class MultiByteToWideChar : Base.Hook + { + public override string Library => "Kernel32.dll"; + + public override string Export => "MultiByteToWideChar"; + + public override void Initialize() + { + HookDelegate = new MultiByteToWideCharDelegate(hMultiByteToWideChar); + Compile(); + } + + private int hMultiByteToWideChar(uint CodePage, uint dwFlags, byte* lpMultiByteStr, int cbMultiByte, ushort* lpWideCharStr, int cchWideChar) + { + int Rst = 0; + if (cbMultiByte > 0) + { + byte[] Buffer = new byte[cbMultiByte]; + for (int i = 0; i < Buffer.Length; i++) + { + Buffer[i] = *(lpMultiByteStr + i); + } + fixed (void* pBuffer = &Buffer[0]) + { + Uninstall(); + lpMultiByteStr = (byte*)EntryPoint.Process(pBuffer); + Install(); + Rst = Bypass(CodePage, dwFlags, lpMultiByteStr, cbMultiByte, lpWideCharStr, cchWideChar); + } + + } else { + Uninstall(); + lpMultiByteStr = (byte*)EntryPoint.Process((void*)lpMultiByteStr); + Install(); + Rst = Bypass(CodePage, dwFlags, lpMultiByteStr, cbMultiByte, lpWideCharStr, cchWideChar); + } + return Rst; + } + } +} diff --git a/StringReloads/SRL.ini b/StringReloads/SRL.ini index eff74c5..61e6f6f 100644 --- a/StringReloads/SRL.ini +++ b/StringReloads/SRL.ini @@ -21,6 +21,7 @@ CreateFontIndirectW=false GetGlyphOutlineA=false GetGlyphOutlineW=false SysAllocString=false +MultiByteToWideChar=false [Modifiers] Escape=false diff --git a/StringReloads/StringReloads.csproj b/StringReloads/StringReloads.csproj index 8fe1937..c8dafc1 100644 --- a/StringReloads/StringReloads.csproj +++ b/StringReloads/StringReloads.csproj @@ -55,6 +55,7 @@ +