mirror of
https://github.com/goatcorp/Dalamud.git
synced 2025-12-12 18:27:23 +01:00
feat: inject exception handler dll after EasyHook
This commit is contained in:
parent
e2ac9ddd43
commit
2ee990827b
3 changed files with 187 additions and 44 deletions
123
Dalamud.Injector/NativeFunctions.cs
Normal file
123
Dalamud.Injector/NativeFunctions.cs
Normal 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -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 {
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue