feat: inject exception handler dll after EasyHook

This commit is contained in:
goat 2020-06-06 19:15:19 +02:00
parent e2ac9ddd43
commit 2ee990827b
3 changed files with 187 additions and 44 deletions

View file

@ -0,0 +1,123 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Runtime.ConstrainedExecution;
using System.Runtime.InteropServices;
using System.Security;
using System.Text;
using System.Threading.Tasks;
namespace Dalamud.Injector
{
static class NativeFunctions
{
// OpenProcess signture https://www.pinvoke.net/default.aspx/kernel32.openprocess
[Flags]
public enum ProcessAccessFlags : uint
{
All = 0x001F0FFF,
Terminate = 0x00000001,
CreateThread = 0x00000002,
VirtualMemoryOperation = 0x00000008,
VirtualMemoryRead = 0x00000010,
VirtualMemoryWrite = 0x00000020,
DuplicateHandle = 0x00000040,
CreateProcess = 0x000000080,
SetQuota = 0x00000100,
SetInformation = 0x00000200,
QueryInformation = 0x00000400,
QueryLimitedInformation = 0x00001000,
Synchronize = 0x00100000
}
[DllImport("kernel32.dll", SetLastError = true)]
public static extern IntPtr OpenProcess(
ProcessAccessFlags processAccess,
bool bInheritHandle,
int processId);
public static IntPtr OpenProcess(Process proc, ProcessAccessFlags flags)
{
return OpenProcess(flags, false, proc.Id);
}
// VirtualAllocEx signture https://www.pinvoke.net/default.aspx/kernel32.virtualallocex
[Flags]
public enum AllocationType
{
Commit = 0x1000,
Reserve = 0x2000,
Decommit = 0x4000,
Release = 0x8000,
Reset = 0x80000,
Physical = 0x400000,
TopDown = 0x100000,
WriteWatch = 0x200000,
LargePages = 0x20000000
}
// VirtualFreeEx signture https://www.pinvoke.net/default.aspx/kernel32.virtualfreeex
[DllImport("kernel32.dll", SetLastError = true, ExactSpelling = true)]
public static extern bool VirtualFreeEx(IntPtr hProcess, IntPtr lpAddress,
int dwSize, AllocationType dwFreeType);
[Flags]
public enum MemoryProtection
{
Execute = 0x10,
ExecuteRead = 0x20,
ExecuteReadWrite = 0x40,
ExecuteWriteCopy = 0x80,
NoAccess = 0x01,
ReadOnly = 0x02,
ReadWrite = 0x04,
WriteCopy = 0x08,
GuardModifierflag = 0x100,
NoCacheModifierflag = 0x200,
WriteCombineModifierflag = 0x400
}
[DllImport("kernel32.dll", SetLastError = true, ExactSpelling = true)]
public static extern IntPtr VirtualAllocEx(
IntPtr hProcess,
IntPtr lpAddress,
int dwSize,
AllocationType flAllocationType,
MemoryProtection flProtect);
// WriteProcessMemory signture https://www.pinvoke.net/default.aspx/kernel32/WriteProcessMemory.html
[DllImport("kernel32.dll", SetLastError = true)]
public static extern bool WriteProcessMemory(
IntPtr hProcess,
IntPtr lpBaseAddress,
[MarshalAs(UnmanagedType.AsAny)] object lpBuffer,
int dwSize,
out IntPtr lpNumberOfBytesWritten);
// GetProcAddress signture https://www.pinvoke.net/default.aspx/kernel32.getprocaddress
[DllImport("kernel32", CharSet = CharSet.Ansi, ExactSpelling = true, SetLastError = true)]
public static extern IntPtr GetProcAddress(IntPtr hModule, string procName);
// GetModuleHandle signture http://pinvoke.net/default.aspx/kernel32.GetModuleHandle
[DllImport("kernel32.dll", CharSet = CharSet.Auto)]
public static extern IntPtr GetModuleHandle(string lpModuleName);
// CreateRemoteThread signture https://www.pinvoke.net/default.aspx/kernel32.createremotethread
[DllImport("kernel32.dll")]
public static extern IntPtr CreateRemoteThread(
IntPtr hProcess,
IntPtr lpThreadAttributes,
uint dwStackSize,
IntPtr lpStartAddress,
IntPtr lpParameter,
uint dwCreationFlags,
IntPtr lpThreadId);
// CloseHandle signture https://www.pinvoke.net/default.aspx/kernel32.closehandle
[DllImport("kernel32.dll", SetLastError = true)]
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
[SuppressUnmanagedCodeSecurity]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool CloseHandle(IntPtr hObject);
}
}

View file

@ -1,8 +1,11 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics; using System.Diagnostics;
using System.Drawing;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Runtime.InteropServices;
using System.Text; using System.Text;
using System.Threading; using System.Threading;
using System.Windows.Forms; using System.Windows.Forms;
@ -29,7 +32,7 @@ namespace Dalamud.Injector {
}; };
var pid = -1; var pid = -1;
if (args.Length == 1) { if (args.Length == 1) {
pid = int.Parse(args[0]); pid = int.Parse(args[0]);
} }
@ -69,6 +72,9 @@ namespace Dalamud.Injector {
// Inject to process // Inject to process
Inject(process, startInfo); Inject(process, startInfo);
// Inject exception handler
NativeInject(process);
} }
private static void Inject(Process process, DalamudStartInfo info) { private static void Inject(Process process, DalamudStartInfo info) {
@ -86,6 +92,63 @@ namespace Dalamud.Injector {
Console.WriteLine("Injected"); Console.WriteLine("Injected");
} }
private static void NativeInject(Process process) {
var libPath = Path.GetFullPath("DalamudDebugStub.dll");
var handle = NativeFunctions.OpenProcess(
NativeFunctions.ProcessAccessFlags.All,
false,
process.Id);
if (handle == IntPtr.Zero)
throw new Win32Exception(Marshal.GetLastWin32Error(), "Could not OpenProcess");
var dllMem = NativeFunctions.VirtualAllocEx(
handle,
IntPtr.Zero,
libPath.Length,
NativeFunctions.AllocationType.Reserve | NativeFunctions.AllocationType.Commit,
NativeFunctions.MemoryProtection.ExecuteReadWrite);
if (dllMem == IntPtr.Zero)
throw new Win32Exception(Marshal.GetLastWin32Error(), "Could not alloc memory");
var pathBytes = Encoding.ASCII.GetBytes(libPath);
if (!NativeFunctions.WriteProcessMemory(
handle,
dllMem,
pathBytes,
pathBytes.Length,
out var bytesread
))
throw new Win32Exception(Marshal.GetLastWin32Error(), "Could not write DLL");
var kernel32 = NativeFunctions.GetModuleHandle("Kernel32.dll");
var loadLibA = NativeFunctions.GetProcAddress(kernel32, "LoadLibraryA");
var remoteThread = NativeFunctions.CreateRemoteThread(
handle,
IntPtr.Zero,
0,
loadLibA,
dllMem,
0,
IntPtr.Zero
);
if (remoteThread == IntPtr.Zero)
throw new Win32Exception(Marshal.GetLastWin32Error(), "Could not alloc memory");
NativeFunctions.VirtualFreeEx(
handle,
dllMem,
0,
NativeFunctions.AllocationType.Release);
NativeFunctions.CloseHandle(remoteThread);
NativeFunctions.CloseHandle(handle);
}
private static DalamudStartInfo GetDefaultStartInfo() { private static DalamudStartInfo GetDefaultStartInfo() {
var ffxivDir = Path.GetDirectoryName(process.MainModule.FileName); var ffxivDir = Path.GetDirectoryName(process.MainModule.FileName);
var startInfo = new DalamudStartInfo { var startInfo = new DalamudStartInfo {

View file

@ -5,49 +5,6 @@
#include <tchar.h> #include <tchar.h>
#include <cstdio> #include <cstdio>
#include <DbgHelp.h> #include <DbgHelp.h>
#include <TlHelp32.h>
BOOL ListProcessThreads(DWORD dwOwnerPID)
{
HANDLE hThreadSnap = INVALID_HANDLE_VALUE;
THREADENTRY32 te32;
// Take a snapshot of all running threads
hThreadSnap = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0);
if (hThreadSnap == INVALID_HANDLE_VALUE)
return(FALSE);
// Fill in the size of the structure before using it.
te32.dwSize = sizeof(THREADENTRY32);
// Retrieve information about the first thread,
// and exit if unsuccessful
if (!Thread32First(hThreadSnap, &te32))
{
CloseHandle(hThreadSnap); // Must clean up the snapshot object!
return(FALSE);
}
// Now walk the thread list of the system,
// and display information about each thread
// associated with the specified process
do
{
if (te32.th32OwnerProcessID == dwOwnerPID && te32.th32ThreadID != GetCurrentThreadId())
{
_tprintf(TEXT("\n THREAD ID = 0x%08X"), te32.th32ThreadID);
_tprintf(TEXT("\n base priority = %d"), te32.tpBasePri);
_tprintf(TEXT("\n delta priority = %d"), te32.tpDeltaPri);
SuspendThread(OpenThread(THREAD_ALL_ACCESS, FALSE, te32.th32ThreadID));
}
} while (Thread32Next(hThreadSnap, &te32));
_tprintf(TEXT("\n"));
// Don't forget to clean up the snapshot object.
CloseHandle(hThreadSnap);
return(TRUE);
}
bool isExcept = false; bool isExcept = false;