mirror of
https://github.com/HolographicHat/Yae.git
synced 2025-12-15 02:48:12 +08:00
win32 define and injector
This commit is contained in:
5
src/GlobalVars.cs
Normal file
5
src/GlobalVars.cs
Normal file
@@ -0,0 +1,5 @@
|
||||
namespace YaeAchievement;
|
||||
|
||||
public static class GlobalVars {
|
||||
public static bool Verbose = false;
|
||||
}
|
||||
53
src/Injector.cs
Normal file
53
src/Injector.cs
Normal file
@@ -0,0 +1,53 @@
|
||||
using System.ComponentModel;
|
||||
using YaeAchievement.Win32;
|
||||
|
||||
namespace YaeAchievement;
|
||||
|
||||
public static class Injector {
|
||||
|
||||
public static bool CreateProcess(string path, ref IntPtr phThread, ref IntPtr phProcess) {
|
||||
ProcessInformation pi;
|
||||
unsafe {
|
||||
var si = new StartupInfo();
|
||||
SecurityAttributes* attr = null;
|
||||
var result = Native.CreateProcess(
|
||||
path, null, ref *attr, ref *attr, false,
|
||||
CreationFlags.CreateSuspended, IntPtr.Zero, null, ref si, out pi
|
||||
);
|
||||
if (!result) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
phThread = pi.hThread;
|
||||
phProcess = pi.hProcess;
|
||||
return true;
|
||||
}
|
||||
|
||||
public static int LoadLibraryAndInject(IntPtr handle, string libPath) {
|
||||
var hKernel = Native.GetModuleHandle("kernel32.dll");
|
||||
if (hKernel == IntPtr.Zero) {
|
||||
return new Win32Exception().PrintMsgAndReturnErrCode("GetModuleHandle fail");
|
||||
}
|
||||
var pLoadLibrary = Native.GetProcAddress(hKernel, "LoadLibraryA");
|
||||
if (pLoadLibrary == IntPtr.Zero) {
|
||||
return new Win32Exception().PrintMsgAndReturnErrCode("GetProcAddress fail");
|
||||
}
|
||||
var pBase = Native.VirtualAllocEx(handle, IntPtr.Zero, libPath.Length + 1, AllocationType.Reserve | AllocationType.Commit, MemoryProtection.ReadWrite);
|
||||
if (pBase == IntPtr.Zero) {
|
||||
return new Win32Exception().PrintMsgAndReturnErrCode("VirtualAllocEx fail");
|
||||
}
|
||||
if (!Native.WriteProcessMemory(handle, pBase, libPath.ToCharArray(), libPath.Length, out _)) {
|
||||
return new Win32Exception().PrintMsgAndReturnErrCode("WriteProcessMemory fail");
|
||||
}
|
||||
var hThread = Native.CreateRemoteThread(handle, IntPtr.Zero, 0, pLoadLibrary, pBase, 0, out _);
|
||||
if (hThread == IntPtr.Zero) {
|
||||
var e = new Win32Exception();
|
||||
if (!Native.VirtualFreeEx(handle, pBase, 0, AllocationType.Release)) {
|
||||
new Win32Exception().PrintMsgAndReturnErrCode("VirtualFreeEx fail");
|
||||
}
|
||||
return e.PrintMsgAndReturnErrCode("CreateRemoteThread fail");
|
||||
}
|
||||
return !Native.CloseHandle(hThread) ? new Win32Exception().PrintMsgAndReturnErrCode("CloseHandle fail") : 0;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,3 +1,46 @@
|
||||
// See https://aka.ms/new-console-template for more information
|
||||
using System.ComponentModel;
|
||||
using System.IO.Pipes;
|
||||
using YaeAchievement;
|
||||
using YaeAchievement.Win32;
|
||||
|
||||
Console.WriteLine("Hello, World!");
|
||||
var hThread = IntPtr.Zero;
|
||||
var hProcess = IntPtr.Zero;
|
||||
if (!Injector.CreateProcess("exePath", ref hThread, ref hProcess)) {
|
||||
Environment.Exit(new Win32Exception().PrintMsgAndReturnErrCode("ICreateProcess fail"));
|
||||
}
|
||||
if (Injector.LoadLibraryAndInject(hProcess, "YaeAchievementLib.dll") != 0) {
|
||||
if (!Native.TerminateProcess(hProcess, 0)) {
|
||||
Environment.Exit(new Win32Exception().PrintMsgAndReturnErrCode("TerminateProcess fail"));
|
||||
}
|
||||
}
|
||||
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"));
|
||||
}
|
||||
|
||||
bool OnXXXReceived(string something) {
|
||||
return true;
|
||||
}
|
||||
|
||||
var ts = new ThreadStart(() => {
|
||||
var server = new NamedPipeServerStream("");
|
||||
server.WaitForConnection();
|
||||
var reader = new StreamReader(server);
|
||||
while (true) {
|
||||
var line = reader.ReadLine();
|
||||
if (line?.Length > 0) {
|
||||
if (OnXXXReceived(line)) {
|
||||
break;
|
||||
}
|
||||
server.Disconnect();
|
||||
server.WaitForConnection();
|
||||
}
|
||||
}
|
||||
});
|
||||
new Thread(ts).Start();
|
||||
|
||||
13
src/Win32/AllocationType.cs
Normal file
13
src/Win32/AllocationType.cs
Normal file
@@ -0,0 +1,13 @@
|
||||
namespace YaeAchievement.Win32;
|
||||
|
||||
public static class AllocationType {
|
||||
public const int Commit = 0x1000;
|
||||
public const int Reserve = 0x2000;
|
||||
public const int Decommit = 0x4000;
|
||||
public const int Release = 0x8000;
|
||||
public const int Reset = 0x80000;
|
||||
public const int Physical = 0x400000;
|
||||
public const int TopDown = 0x100000;
|
||||
public const int WriteWatch = 0x200000;
|
||||
public const int LargePages = 0x20000000;
|
||||
}
|
||||
8
src/Win32/CreationFlags.cs
Normal file
8
src/Win32/CreationFlags.cs
Normal file
@@ -0,0 +1,8 @@
|
||||
namespace YaeAchievement.Win32;
|
||||
|
||||
public static class CreationFlags {
|
||||
public const int CreateSuspended = 0x00000004;
|
||||
public const int DetachedProcess = 0x00000008;
|
||||
public const int CreateNoWindow = 0x08000000;
|
||||
public const int ExtendedStartupInfoPresent = 0x00080000;
|
||||
}
|
||||
15
src/Win32/Extensions.cs
Normal file
15
src/Win32/Extensions.cs
Normal file
@@ -0,0 +1,15 @@
|
||||
using System.ComponentModel;
|
||||
|
||||
namespace YaeAchievement.Win32;
|
||||
|
||||
public static class Extensions {
|
||||
|
||||
public static int PrintMsgAndReturnErrCode(this Win32Exception ex, string msg) {
|
||||
Console.WriteLine($"{msg}: {ex.Message}");
|
||||
if (GlobalVars.Verbose) {
|
||||
Console.WriteLine(ex.StackTrace);
|
||||
}
|
||||
return ex.NativeErrorCode;
|
||||
}
|
||||
|
||||
}
|
||||
15
src/Win32/MemoryProtection.cs
Normal file
15
src/Win32/MemoryProtection.cs
Normal file
@@ -0,0 +1,15 @@
|
||||
namespace YaeAchievement.Win32;
|
||||
|
||||
public static class MemoryProtection {
|
||||
public const int Execute = 0x10;
|
||||
public const int ExecuteRead = 0x20;
|
||||
public const int ExecuteReadWrite = 0x40;
|
||||
public const int ExecuteWriteCopy = 0x80;
|
||||
public const int NoAccess = 0x01;
|
||||
public const int ReadOnly = 0x02;
|
||||
public const int ReadWrite = 0x04;
|
||||
public const int WriteCopy = 0x08;
|
||||
public const int GuardModifierFlag = 0x100;
|
||||
public const int NoCacheModifierFlag = 0x200;
|
||||
public const int WriteCombineModifierFlag = 0x400;
|
||||
}
|
||||
74
src/Win32/Native.cs
Normal file
74
src/Win32/Native.cs
Normal file
@@ -0,0 +1,74 @@
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Security;
|
||||
|
||||
namespace YaeAchievement.Win32;
|
||||
|
||||
[SuppressMessage("Interoperability", "CA1401:P/Invokes 应该是不可见的")]
|
||||
public static class Native {
|
||||
|
||||
[DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
|
||||
public static extern bool CreateProcess(
|
||||
string lpApplicationName,
|
||||
string? lpCommandLine,
|
||||
ref SecurityAttributes lpProcessAttributes,
|
||||
ref SecurityAttributes lpThreadAttributes,
|
||||
bool bInheritHandles,
|
||||
int dwCreationFlags,
|
||||
IntPtr lpEnvironment,
|
||||
string? lpCurrentDirectory,
|
||||
[In] ref StartupInfo lpStartupInfo,
|
||||
out ProcessInformation lpProcessInformation
|
||||
);
|
||||
|
||||
[return: MarshalAs(UnmanagedType.Bool)]
|
||||
[DllImport("kernel32.dll", SetLastError = true)]
|
||||
public static extern bool TerminateProcess(IntPtr hProcess, uint uExitCode);
|
||||
|
||||
[DllImport("kernel32.dll")]
|
||||
public static extern bool WriteProcessMemory(
|
||||
IntPtr hProcess,
|
||||
IntPtr lpBaseAddress,
|
||||
char[] lpBuffer,
|
||||
int nSize,
|
||||
out IntPtr lpNumberOfBytesWritten
|
||||
);
|
||||
|
||||
[DllImport("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
|
||||
public static extern IntPtr GetModuleHandle(string lpModuleName);
|
||||
|
||||
[DllImport("kernel32.dll", CharSet = CharSet.Ansi, SetLastError = true)]
|
||||
[SuppressMessage("Globalization", "CA2101:指定对 P/Invoke 字符串参数进行封送处理")]
|
||||
public static extern IntPtr GetProcAddress(IntPtr hModule, string lpProcName);
|
||||
|
||||
[DllImport("kernel32.dll", SetLastError = true, ExactSpelling=true)]
|
||||
public static extern IntPtr VirtualAllocEx(
|
||||
IntPtr hProcess,
|
||||
IntPtr lpAddress,
|
||||
int dwSize,
|
||||
int flAllocationType,
|
||||
int flProtect
|
||||
);
|
||||
|
||||
[DllImport("kernel32.dll", SetLastError=true, ExactSpelling=true)]
|
||||
public static extern bool VirtualFreeEx(IntPtr hProcess, IntPtr lpAddress, int dwSize, int dwFreeType);
|
||||
|
||||
[DllImport("kernel32.dll", SetLastError = true)]
|
||||
public static extern uint ResumeThread(IntPtr hThread);
|
||||
|
||||
[SuppressUnmanagedCodeSecurity]
|
||||
[return: MarshalAs(UnmanagedType.Bool)]
|
||||
[DllImport("kernel32.dll", SetLastError = true)]
|
||||
public static extern bool CloseHandle(IntPtr hObject);
|
||||
|
||||
[DllImport("kernel32.dll")]
|
||||
public static extern IntPtr CreateRemoteThread(
|
||||
IntPtr hProcess,
|
||||
IntPtr lpThreadAttributes,
|
||||
int dwStackSize,
|
||||
IntPtr lpStartAddress,
|
||||
IntPtr lpParameter,
|
||||
uint dwCreationFlags,
|
||||
out IntPtr lpThreadId
|
||||
);
|
||||
}
|
||||
14
src/Win32/ProcessInformation.cs
Normal file
14
src/Win32/ProcessInformation.cs
Normal file
@@ -0,0 +1,14 @@
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
// ReSharper disable MemberCanBePrivate.Global
|
||||
// ReSharper disable FieldCanBeMadeReadOnly.Global
|
||||
|
||||
namespace YaeAchievement.Win32;
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct ProcessInformation {
|
||||
public IntPtr hProcess;
|
||||
public IntPtr hThread;
|
||||
public int dwProcessId;
|
||||
public int dwThreadId;
|
||||
}
|
||||
12
src/Win32/SecurityAttributes.cs
Normal file
12
src/Win32/SecurityAttributes.cs
Normal file
@@ -0,0 +1,12 @@
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
// ReSharper disable MemberCanBePrivate.Global
|
||||
// ReSharper disable FieldCanBeMadeReadOnly.Global
|
||||
|
||||
namespace YaeAchievement.Win32;
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct SecurityAttributes {
|
||||
public int nLength;
|
||||
public IntPtr lpSecurityDescriptor;
|
||||
}
|
||||
28
src/Win32/StartupInfo.cs
Normal file
28
src/Win32/StartupInfo.cs
Normal file
@@ -0,0 +1,28 @@
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
// ReSharper disable MemberCanBePrivate.Global
|
||||
// ReSharper disable FieldCanBeMadeReadOnly.Global
|
||||
|
||||
namespace YaeAchievement.Win32;
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
|
||||
public struct StartupInfo {
|
||||
public int cb;
|
||||
public string lpReserved;
|
||||
public string lpDesktop;
|
||||
public string lpTitle;
|
||||
public int dwX;
|
||||
public int dwY;
|
||||
public int dwXSize;
|
||||
public int dwYSize;
|
||||
public int dwXCountChars;
|
||||
public int dwYCountChars;
|
||||
public int dwFillAttribute;
|
||||
public int dwFlags;
|
||||
public short wShowWindow;
|
||||
public short cbReserved2;
|
||||
public IntPtr lpReserved2;
|
||||
public IntPtr hStdInput;
|
||||
public IntPtr hStdOutput;
|
||||
public IntPtr hStdError;
|
||||
}
|
||||
Reference in New Issue
Block a user