Skip to content

Commit

Permalink
Fix D3D11/DXGI Wrapper + Initial x64 Hook Compatibility
Browse files Browse the repository at this point in the history
  • Loading branch information
marcussacana committed Apr 9, 2020
1 parent 5131398 commit b74fbc1
Show file tree
Hide file tree
Showing 9 changed files with 176 additions and 21 deletions.
4 changes: 4 additions & 0 deletions SRLWrapper/Wrapper/Base/Wrapper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand All @@ -67,6 +70,7 @@ internal static T GetDelegate<T>(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));
Expand Down
8 changes: 4 additions & 4 deletions SRLWrapper/Wrapper/D3D11.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@ public static void LoadRetail()
dD3D11CreateDeviceAndSwapChain = GetDelegate<RET_13>(RealHandler, "D3D11CreateDeviceAndSwapChain", false);
dD3D11CreateDevice = GetDelegate<RET_11>(RealHandler, "D3D11CreateDevice", false);
dD3DKMTWaitForVerticalBlankEvent = GetDelegate<RET_1>(RealHandler, "D3DKMTWaitForVerticalBlankEvent", false);
dD3D11CreateDeviceForD3D12 = GetDelegate<RET_10>(RealHandler, "D3D11CreateDeviceForD3D12", false);
dD3D11On12CreateDevice = GetDelegate<RET_11>(RealHandler, "D3D11On12CreateDevice", false);
dD3D11CreateDeviceForD3D12 = GetDelegate<RET_10>(RealHandler, "D3D11CreateDeviceForD3D12", true);
dD3D11On12CreateDevice = GetDelegate<RET_11>(RealHandler, "D3D11On12CreateDevice", true);
dD3DPerformance_BeginEvent = GetDelegate<RET_2>(RealHandler, "D3DPerformance_BeginEvent", false);
dD3DPerformance_EndEvent = GetDelegate<RET_1>(RealHandler, "D3DPerformance_EndEvent", false);
dD3DPerformance_GetStatus = GetDelegate<RET_1>(RealHandler, "D3DPerformance_GetStatus", false);
Expand All @@ -38,8 +38,8 @@ public static void LoadRetail()
dD3DKMTGetDeviceState = GetDelegate<RET_1>(RealHandler, "D3DKMTGetDeviceState", false);
dD3DKMTOpenAdapterFromHdc = GetDelegate<RET_1>(RealHandler, "D3DKMTOpenAdapterFromHdc", false);
dD3DKMTQueryResourceInfo = GetDelegate<RET_1>(RealHandler, "D3DKMTQueryResourceInfo", false);
dCreateDirect3D11DeviceFromDXGIDevice = GetDelegate<RET_2>(RealHandler, "CreateDirect3D11DeviceFromDXGIDevice", false);
dCreateDirect3D11SurfaceFromDXGISurface = GetDelegate<RET_2>(RealHandler, "CreateDirect3D11SurfaceFromDXGISurface", false);
dCreateDirect3D11DeviceFromDXGIDevice = GetDelegate<RET_2>(RealHandler, "CreateDirect3D11DeviceFromDXGIDevice", true);
dCreateDirect3D11SurfaceFromDXGISurface = GetDelegate<RET_2>(RealHandler, "CreateDirect3D11SurfaceFromDXGISurface", true);

InitializeSRL();
}
Expand Down
10 changes: 5 additions & 5 deletions SRLWrapper/Wrapper/DXGI.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,17 +22,17 @@ public static void LoadRetail()
dCreateDXGIFactory1 = GetDelegate<RET_2>(RealHandler, "CreateDXGIFactory1", false);
dCompatValue = GetDelegate<RET_2>(RealHandler, "CompatValue", false);
dCompatString = GetDelegate<RET_4>(RealHandler, "CompatString", false);
dApplyCompatResolutionQuirking = GetDelegate<RET_3>(RealHandler, "ApplyCompatResolutionQuirking", false);
dCreateDXGIFactory2 = GetDelegate<RET_3>(RealHandler, "CreateDXGIFactory2", false);
dApplyCompatResolutionQuirking = GetDelegate<RET_3>(RealHandler, "ApplyCompatResolutionQuirking", true);
dCreateDXGIFactory2 = GetDelegate<RET_3>(RealHandler, "CreateDXGIFactory2", true);
dDXGID3D10RegisterLayers = GetDelegate<RET_2>(RealHandler, "DXGID3D10RegisterLayers", false);
dPIXEndCapture = GetDelegate<RET_1>(RealHandler, "PIXEndCapture", false);
dPIXEndCapture = GetDelegate<RET_1>(RealHandler, "PIXEndCapture", true);
dDXGID3D10GetLayeredDeviceSize = GetDelegate<RET_2>(RealHandler, "DXGID3D10GetLayeredDeviceSize", false);
dDXGID3D10CreateLayeredDevice = GetDelegate<RET_5>(RealHandler, "DXGID3D10CreateLayeredDevice", false);
dDXGID3D10CreateDevice = GetDelegate<RET_6>(RealHandler, "DXGID3D10CreateDevice", false);
dDXGIReportAdapterConfiguration = GetDelegate<RET_1>(RealHandler, "DXGIReportAdapterConfiguration", false);
dSetAppCompatStringPointer = GetDelegate<RET_2>(RealHandler, "SetAppCompatStringPointer", false);
dUpdateHMDEmulationStatus = GetDelegate<RET_2>(RealHandler, "UpdateHMDEmulationStatus", false);
dDXGIGetDebugInterface1 = GetDelegate<RET_3>(RealHandler, "DXGIGetDebugInterface1", false);
dUpdateHMDEmulationStatus = GetDelegate<RET_2>(RealHandler, "UpdateHMDEmulationStatus", true);
dDXGIGetDebugInterface1 = GetDelegate<RET_3>(RealHandler, "DXGIGetDebugInterface1", true);

InitializeSRL();
}
Expand Down
3 changes: 2 additions & 1 deletion StringReloads/Engine/Main.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
126 changes: 115 additions & 11 deletions StringReloads/Hook/Base/Hook.cs
Original file line number Diff line number Diff line change
@@ -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
{
Expand Down Expand Up @@ -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
Expand All @@ -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);
Expand All @@ -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);

Expand All @@ -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
Expand Down Expand Up @@ -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)
Expand All @@ -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)
{
Expand All @@ -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);;
Expand Down
2 changes: 2 additions & 0 deletions StringReloads/Hook/Types/Delegates.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
42 changes: 42 additions & 0 deletions StringReloads/Hook/Win32/MultiByteToWideChar.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
namespace StringReloads.Hook
{
public unsafe class MultiByteToWideChar : Base.Hook<MultiByteToWideCharDelegate>
{
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;
}
}
}
1 change: 1 addition & 0 deletions StringReloads/SRL.ini
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ CreateFontIndirectW=false
GetGlyphOutlineA=false
GetGlyphOutlineW=false
SysAllocString=false
MultiByteToWideChar=false

[Modifiers]
Escape=false
Expand Down
1 change: 1 addition & 0 deletions StringReloads/StringReloads.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="Iced" Version="1.5.0" />
<PackageReference Include="System.ValueTuple" Version="4.5.0" />
</ItemGroup>
<ItemGroup>
<Reference Include="System.Windows.Forms" />
Expand Down

0 comments on commit b74fbc1

Please sign in to comment.