fixup native call

This commit is contained in:
DismissedLight
2023-02-26 14:41:24 +08:00
parent 50007c2c53
commit 5f8ff734f2
3 changed files with 86 additions and 75 deletions

View File

@@ -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<char> 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<byte> 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<LPTHREAD_START_ROUTINE>();
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<LPTHREAD_START_ROUTINE>();
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;
}
}
}

View File

@@ -2,5 +2,5 @@
"$schema": "https://aka.ms/CsWin32.schema.json",
"className": "Native",
"allowMarshaling": true,
"public": false
"public": true
}

View File

@@ -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<char> 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();