From 5f8ff734f2171ff8f4ee42774bbc96f6197d1ea2 Mon Sep 17 00:00:00 2001 From: DismissedLight <1686188646@qq.com> Date: Sun, 26 Feb 2023 14:41:24 +0800 Subject: [PATCH] fixup native call --- src/Injector.cs | 80 +++++++++++++++++++++++------------------- src/NativeMethods.json | 2 +- src/Utils.cs | 79 ++++++++++++++++++++++------------------- 3 files changed, 86 insertions(+), 75 deletions(-) diff --git a/src/Injector.cs b/src/Injector.cs index 1c9ccc7..5b37ac5 100644 --- a/src/Injector.cs +++ b/src/Injector.cs @@ -3,6 +3,7 @@ using System.ComponentModel; using System.Runtime.InteropServices; using System.Runtime.Versioning; using Windows.Win32; +using Windows.Win32.Foundation; using Windows.Win32.System.Memory; using Windows.Win32.System.Threading; using YaeAchievement.Win32; @@ -10,7 +11,7 @@ using YaeAchievement.Win32; namespace YaeAchievement; public static class Injector { - public static unsafe bool CreateProcess(string path, out SafeHandle hProc, out SafeHandle hThread, out uint pid) { + public static unsafe bool CreateProcess(string path, out HANDLE hProc, out HANDLE hThread, out uint pid) { Span cmdLines = stackalloc char[1]; // "\0" var si = new STARTUPINFOW() { cb = unchecked((uint)sizeof(STARTUPINFOW)) }; var dir = Path.GetDirectoryName(path)!; @@ -19,53 +20,58 @@ public static class Injector { PROCESS_CREATION_FLAGS.CREATE_SUSPENDED, default, dir, in si, out var pi ); pid = pi.dwProcessId; - hProc = new SafeFileHandle(pi.hProcess, true); - hThread = new SafeFileHandle(pi.hThread, true); + hProc = pi.hProcess; + hThread = pi.hThread; return result; } // todo: refactor - public static unsafe int LoadLibraryAndInject(SafeHandle hProc, string libPath) + public static unsafe int LoadLibraryAndInject(HANDLE hProc, ReadOnlySpan libPath) { - var hKernel = Native.GetModuleHandle("kernel32.dll"); - if (hKernel.IsInvalid) + fixed (char* lpModelName = "kernel32.dll") { - return new Win32Exception().PrintMsgAndReturnErrCode("GetModuleHandle fail"); - } - var pLoadLibrary = Native.GetProcAddress(hKernel, "LoadLibraryA"); - if (pLoadLibrary.IsNull) - { - return new Win32Exception().PrintMsgAndReturnErrCode("GetProcAddress fail"); - } - var pBase = Native.VirtualAllocEx(hProc, default, unchecked((uint)libPath.Length + 1), VIRTUAL_ALLOCATION_TYPE.MEM_RESERVE | VIRTUAL_ALLOCATION_TYPE.MEM_COMMIT, PAGE_PROTECTION_FLAGS.PAGE_READWRITE); - if ((nint)pBase == 0) - { - return new Win32Exception().PrintMsgAndReturnErrCode("VirtualAllocEx fail"); - } - fixed (void* lpBuffer = libPath.ToCharArray()) - { - if (!Native.WriteProcessMemory(hProc, pBase, lpBuffer, unchecked((uint)libPath.Length), default)) - { - return new Win32Exception().PrintMsgAndReturnErrCode("WriteProcessMemory fail"); - } - } - var lpStartAddress = pLoadLibrary.CreateDelegate(); + HINSTANCE hKernel = Native.GetModuleHandle(lpModelName); - using (var hThread = Native.CreateRemoteThread(hProc, default, 0, lpStartAddress, pBase, 0, default)) - { - if (hThread.IsInvalid) + if (hKernel.IsNull) { - var e = new Win32Exception(); - Native.VirtualFreeEx(hProc, pBase, 0, VIRTUAL_FREE_TYPE.MEM_RELEASE); - return e.PrintMsgAndReturnErrCode("CreateRemoteThread fail"); + return new Win32Exception().PrintMsgAndReturnErrCode("GetModuleHandle fail"); } - if (Native.WaitForSingleObject(hThread, 2000) == 0) + + fixed(byte* lpProcName = "LoadLibraryA"u8) { - Native.VirtualFreeEx(hProc, pBase, 0, VIRTUAL_FREE_TYPE.MEM_RELEASE); + var pLoadLibrary = Native.GetProcAddress(hKernel, (PCSTR)lpProcName); + if (pLoadLibrary.IsNull) + { + return new Win32Exception().PrintMsgAndReturnErrCode("GetProcAddress fail"); + } + var pBase = Native.VirtualAllocEx(hProc, default, unchecked((uint)libPath.Length + 1), VIRTUAL_ALLOCATION_TYPE.MEM_RESERVE | VIRTUAL_ALLOCATION_TYPE.MEM_COMMIT, PAGE_PROTECTION_FLAGS.PAGE_READWRITE); + if ((nint)pBase == 0) + { + return new Win32Exception().PrintMsgAndReturnErrCode("VirtualAllocEx fail"); + } + fixed (void* lpBuffer = libPath) + { + if (!Native.WriteProcessMemory(hProc, pBase, lpBuffer, unchecked((uint)libPath.Length), default)) + { + return new Win32Exception().PrintMsgAndReturnErrCode("WriteProcessMemory fail"); + } + } + + var lpStartAddress = pLoadLibrary.CreateDelegate(); + var hThread = Native.CreateRemoteThread(hProc, default, 0, lpStartAddress, pBase, 0, default); + + if (hThread.IsNull) + { + var e = new Win32Exception(); + Native.VirtualFreeEx(hProc, pBase, 0, VIRTUAL_FREE_TYPE.MEM_RELEASE); + return e.PrintMsgAndReturnErrCode("CreateRemoteThread fail"); + } + if (Native.WaitForSingleObject(hThread, 2000) == 0) + { + Native.VirtualFreeEx(hProc, pBase, 0, VIRTUAL_FREE_TYPE.MEM_RELEASE); + } + return !Native.CloseHandle(hThread) ? new Win32Exception().PrintMsgAndReturnErrCode("CloseHandle fail") : 0; } - //return !Native.CloseHandle(hThread) ? new Win32Exception().PrintMsgAndReturnErrCode("CloseHandle fail") : 0; - return 0; } } - } \ No newline at end of file diff --git a/src/NativeMethods.json b/src/NativeMethods.json index 2e55a35..1372a02 100644 --- a/src/NativeMethods.json +++ b/src/NativeMethods.json @@ -2,5 +2,5 @@ "$schema": "https://aka.ms/CsWin32.schema.json", "className": "Native", "allowMarshaling": true, - "public": false + "public": true } \ No newline at end of file diff --git a/src/Utils.cs b/src/Utils.cs index b0aa879..0b1664c 100644 --- a/src/Utils.cs +++ b/src/Utils.cs @@ -5,7 +5,8 @@ using System.IO.Pipes; using System.Net; using System.Net.Http.Headers; using System.Net.Sockets; -using System.Runtime.Versioning; +using System.Runtime.InteropServices; +using System.Text; using Windows.Win32; using Windows.Win32.Foundation; using Windows.Win32.System.Console; @@ -68,17 +69,20 @@ public static class Utils { return value != null && bool.TryParse(value, out var result) && result; } - [SupportedOSPlatform("windows5.0")] public static unsafe void CopyToClipboard(string text) { - if (Native.OpenClipboard(HWND.Null)) { + if (Native.OpenClipboard(HWND.Null)) + { Native.EmptyClipboard(); - Span textSpan = text.ToCharArray(); - fixed (char* lpBuffer = textSpan) - { - Native.SetClipboardData(/*CF_UNICODETEXT*/13, (HANDLE)(nint)lpBuffer); - Native.CloseClipboard(); - } - } else { + HANDLE hGlobal = (HANDLE)Marshal.AllocHGlobal((text.Length + 1) * 2); + IntPtr hPtr = (IntPtr)Native.GlobalLock(hGlobal); + Marshal.Copy(text.ToCharArray(), 0, hPtr, text.Length); + Native.GlobalUnlock(hPtr); + Native.SetClipboardData(13, hGlobal); + Marshal.FreeHGlobal(hGlobal); + Native.CloseClipboard(); + } + else + { throw new Win32Exception(); } } @@ -227,37 +231,38 @@ public static class Utils { if (!Injector.CreateProcess(exePath, out var hProcess, out var hThread, out var pid)) { Environment.Exit(new Win32Exception().PrintMsgAndReturnErrCode("ICreateProcess fail")); } - using (hProcess) + if (Injector.LoadLibraryAndInject(hProcess,Encoding.UTF8.GetBytes(GlobalVars.LibFilePath)) != 0) { - if (Injector.LoadLibraryAndInject(hProcess, GlobalVars.LibFilePath) != 0) + if (!Native.TerminateProcess(hProcess, 0)) { - if (!Native.TerminateProcess(hProcess, 0)) - { - Environment.Exit(new Win32Exception().PrintMsgAndReturnErrCode("TerminateProcess fail")); - } - } - Console.WriteLine(App.GameLoading, pid); - proc = Process.GetProcessById(Convert.ToInt32(pid)); - proc.EnableRaisingEvents = true; - proc.Exited += (_, _) => { - if (GlobalVars.UnexpectedExit) - { - proc = null; - Console.WriteLine(App.GameProcessExit); - Environment.Exit(114514); - } - }; - if (Native.ResumeThread(hThread) == 0xFFFFFFFF) - { - var e = new Win32Exception(); - if (!Native.TerminateProcess(hProcess, 0)) - { - new Win32Exception().PrintMsgAndReturnErrCode("TerminateProcess fail"); - } - Environment.Exit(e.PrintMsgAndReturnErrCode("ResumeThread fail")); + Environment.Exit(new Win32Exception().PrintMsgAndReturnErrCode("TerminateProcess fail")); } } - + Console.WriteLine(App.GameLoading, pid); + proc = Process.GetProcessById(Convert.ToInt32(pid)); + proc.EnableRaisingEvents = true; + proc.Exited += (_, _) => { + if (GlobalVars.UnexpectedExit) + { + proc = null; + Console.WriteLine(App.GameProcessExit); + Environment.Exit(114514); + } + }; + if (Native.ResumeThread(hThread) == 0xFFFFFFFF) + { + var e = new Win32Exception(); + if (!Native.TerminateProcess(hProcess, 0)) + { + new Win32Exception().PrintMsgAndReturnErrCode("TerminateProcess fail"); + } + Environment.Exit(e.PrintMsgAndReturnErrCode("ResumeThread fail")); + } + if (!Native.CloseHandle(hProcess)) + { + Environment.Exit(new Win32Exception().PrintMsgAndReturnErrCode("CloseHandle fail")); + } + var ts = new ThreadStart(() => { var server = new NamedPipeServerStream(GlobalVars.PipeName); server.WaitForConnection();