mirror of
https://github.com/HolographicHat/Yae.git
synced 2025-12-16 19:38:13 +08:00
optimize code and update
This commit is contained in:
5
src/Events/IEventBase.cs
Normal file
5
src/Events/IEventBase.cs
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
namespace YaeAchievement.Events;
|
||||||
|
|
||||||
|
public interface IEventBase {
|
||||||
|
|
||||||
|
}
|
||||||
14
src/Events/PipeRecvEvent.cs
Normal file
14
src/Events/PipeRecvEvent.cs
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
namespace YaeAchievement.Events;
|
||||||
|
|
||||||
|
public class PipeRecvEvent : IEventBase {
|
||||||
|
|
||||||
|
private readonly byte[] _data;
|
||||||
|
|
||||||
|
public PipeRecvEvent(string content) {
|
||||||
|
_data = Convert.FromBase64String(content);
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte[] GetData() {
|
||||||
|
return _data;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,4 +2,7 @@
|
|||||||
|
|
||||||
public static class GlobalVars {
|
public static class GlobalVars {
|
||||||
public static bool Verbose = false;
|
public static bool Verbose = false;
|
||||||
}
|
public const string LibName = "YaeAchievementLib.dll";
|
||||||
|
public const string PipeName = "YaeAchievementPipe";
|
||||||
|
public static bool UnexpectedExit = true;
|
||||||
|
}
|
||||||
|
|||||||
@@ -5,22 +5,17 @@ namespace YaeAchievement;
|
|||||||
|
|
||||||
public static class Injector {
|
public static class Injector {
|
||||||
|
|
||||||
public static bool CreateProcess(string path, ref IntPtr phThread, ref IntPtr phProcess) {
|
public static unsafe bool CreateProcess(string path, out IntPtr hProc, out IntPtr hThread, out uint pid) {
|
||||||
ProcessInformation pi;
|
var si = new StartupInfo();
|
||||||
unsafe {
|
SecurityAttributes* attr = null;
|
||||||
var si = new StartupInfo();
|
var result = Native.CreateProcess(
|
||||||
SecurityAttributes* attr = null;
|
path, null, ref *attr, ref *attr, false,
|
||||||
var result = Native.CreateProcess(
|
CreationFlags.CreateSuspended, IntPtr.Zero, null, ref si, out var pi
|
||||||
path, null, ref *attr, ref *attr, false,
|
);
|
||||||
CreationFlags.CreateSuspended, IntPtr.Zero, null, ref si, out pi
|
pid = pi.dwProcessID;
|
||||||
);
|
hProc = pi.hProcess;
|
||||||
if (!result) {
|
hThread = pi.hThread;
|
||||||
return false;
|
return result;
|
||||||
}
|
|
||||||
}
|
|
||||||
phThread = pi.hThread;
|
|
||||||
phProcess = pi.hProcess;
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int LoadLibraryAndInject(IntPtr handle, string libPath) {
|
public static int LoadLibraryAndInject(IntPtr handle, string libPath) {
|
||||||
|
|||||||
@@ -1,46 +1,66 @@
|
|||||||
using System.ComponentModel;
|
using System.ComponentModel;
|
||||||
|
using System.Diagnostics;
|
||||||
using System.IO.Pipes;
|
using System.IO.Pipes;
|
||||||
using YaeAchievement;
|
using YaeAchievement;
|
||||||
|
using YaeAchievement.Events;
|
||||||
using YaeAchievement.Win32;
|
using YaeAchievement.Win32;
|
||||||
|
|
||||||
var hThread = IntPtr.Zero;
|
// ReSharper disable once UnusedLocalFunctionReturnValue
|
||||||
var hProcess = IntPtr.Zero;
|
Thread StartAndWaitResult(string exePath, Func<IEventBase, bool> onEvent) {
|
||||||
if (!Injector.CreateProcess("exePath", ref hThread, ref hProcess)) {
|
if (!Injector.CreateProcess(exePath, out var hProcess, out var hThread, out var pid)) {
|
||||||
Environment.Exit(new Win32Exception().PrintMsgAndReturnErrCode("ICreateProcess fail"));
|
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 (Injector.LoadLibraryAndInject(hProcess, GlobalVars.LibName) != 0) {
|
||||||
if (Native.ResumeThread(hThread) == 0xFFFFFFFF) {
|
if (!Native.TerminateProcess(hProcess, 0)) {
|
||||||
var e = new Win32Exception();
|
Environment.Exit(new Win32Exception().PrintMsgAndReturnErrCode("TerminateProcess fail"));
|
||||||
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();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
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 proc = Process.GetProcessById(Convert.ToInt32(pid));
|
||||||
|
proc.EnableRaisingEvents = true;
|
||||||
|
proc.Exited += (_, _) => {
|
||||||
|
if (GlobalVars.UnexpectedExit) {
|
||||||
|
Console.WriteLine($"Game process exit at {proc.ExitTime:HH:mm:ss}");
|
||||||
|
Environment.Exit(114514);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
var ts = new ThreadStart(() => {
|
||||||
|
var server = new NamedPipeServerStream(GlobalVars.PipeName);
|
||||||
|
server.WaitForConnection();
|
||||||
|
var reader = new StreamReader(server);
|
||||||
|
while (true) {
|
||||||
|
var line = reader.ReadLine();
|
||||||
|
if (line?.Length > 0) {
|
||||||
|
if (onEvent(new PipeRecvEvent(line))) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
server.Disconnect();
|
||||||
|
server.WaitForConnection();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
var th = new Thread(ts);
|
||||||
|
th.Start();
|
||||||
|
return th;
|
||||||
|
}
|
||||||
|
|
||||||
|
StartAndWaitResult(@"D:\Genshin Impact Dev\2.8\YuanShen.exe", evt => {
|
||||||
|
switch (evt) {
|
||||||
|
case PipeRecvEvent @event: {
|
||||||
|
var bytes = @event.GetData();
|
||||||
|
GlobalVars.UnexpectedExit = false;
|
||||||
|
return BitConverter.ToUInt32(bytes, 2) == 123456;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
});
|
});
|
||||||
new Thread(ts).Start();
|
|
||||||
|
|||||||
@@ -1,13 +1,14 @@
|
|||||||
namespace YaeAchievement.Win32;
|
namespace YaeAchievement.Win32;
|
||||||
|
|
||||||
public static class AllocationType {
|
[Flags]
|
||||||
public const int Commit = 0x1000;
|
public enum AllocationType : uint {
|
||||||
public const int Reserve = 0x2000;
|
Commit = 0x1000,
|
||||||
public const int Decommit = 0x4000;
|
Reserve = 0x2000,
|
||||||
public const int Release = 0x8000;
|
Decommit = 0x4000,
|
||||||
public const int Reset = 0x80000;
|
Release = 0x8000,
|
||||||
public const int Physical = 0x400000;
|
Reset = 0x80000,
|
||||||
public const int TopDown = 0x100000;
|
Physical = 0x400000,
|
||||||
public const int WriteWatch = 0x200000;
|
TopDown = 0x100000,
|
||||||
public const int LargePages = 0x20000000;
|
WriteWatch = 0x200000,
|
||||||
|
LargePages = 0x20000000
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
namespace YaeAchievement.Win32;
|
namespace YaeAchievement.Win32;
|
||||||
|
|
||||||
public static class CreationFlags {
|
[Flags]
|
||||||
public const int CreateSuspended = 0x00000004;
|
public enum CreationFlags : uint {
|
||||||
public const int DetachedProcess = 0x00000008;
|
CreateSuspended = 0x00000004,
|
||||||
public const int CreateNoWindow = 0x08000000;
|
DetachedProcess = 0x00000008,
|
||||||
public const int ExtendedStartupInfoPresent = 0x00080000;
|
CreateNoWindow = 0x08000000,
|
||||||
|
ExtendedStartupInfoPresent = 0x00080000
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,15 +1,16 @@
|
|||||||
namespace YaeAchievement.Win32;
|
namespace YaeAchievement.Win32;
|
||||||
|
|
||||||
public static class MemoryProtection {
|
[Flags]
|
||||||
public const int Execute = 0x10;
|
public enum MemoryProtection : uint {
|
||||||
public const int ExecuteRead = 0x20;
|
Execute = 0x10,
|
||||||
public const int ExecuteReadWrite = 0x40;
|
ExecuteRead = 0x20,
|
||||||
public const int ExecuteWriteCopy = 0x80;
|
ExecuteReadWrite = 0x40,
|
||||||
public const int NoAccess = 0x01;
|
ExecuteWriteCopy = 0x80,
|
||||||
public const int ReadOnly = 0x02;
|
NoAccess = 0x01,
|
||||||
public const int ReadWrite = 0x04;
|
ReadOnly = 0x02,
|
||||||
public const int WriteCopy = 0x08;
|
ReadWrite = 0x04,
|
||||||
public const int GuardModifierFlag = 0x100;
|
WriteCopy = 0x08,
|
||||||
public const int NoCacheModifierFlag = 0x200;
|
GuardModifierFlag = 0x100,
|
||||||
public const int WriteCombineModifierFlag = 0x400;
|
NoCacheModifierFlag = 0x200,
|
||||||
|
WriteCombineModifierFlag = 0x400
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ public static class Native {
|
|||||||
ref SecurityAttributes lpProcessAttributes,
|
ref SecurityAttributes lpProcessAttributes,
|
||||||
ref SecurityAttributes lpThreadAttributes,
|
ref SecurityAttributes lpThreadAttributes,
|
||||||
bool bInheritHandles,
|
bool bInheritHandles,
|
||||||
int dwCreationFlags,
|
CreationFlags dwCreationFlags,
|
||||||
IntPtr lpEnvironment,
|
IntPtr lpEnvironment,
|
||||||
string? lpCurrentDirectory,
|
string? lpCurrentDirectory,
|
||||||
[In] ref StartupInfo lpStartupInfo,
|
[In] ref StartupInfo lpStartupInfo,
|
||||||
@@ -46,12 +46,12 @@ public static class Native {
|
|||||||
IntPtr hProcess,
|
IntPtr hProcess,
|
||||||
IntPtr lpAddress,
|
IntPtr lpAddress,
|
||||||
int dwSize,
|
int dwSize,
|
||||||
int flAllocationType,
|
AllocationType flAllocationType,
|
||||||
int flProtect
|
MemoryProtection flProtect
|
||||||
);
|
);
|
||||||
|
|
||||||
[DllImport("kernel32.dll", SetLastError=true, ExactSpelling=true)]
|
[DllImport("kernel32.dll", SetLastError=true, ExactSpelling=true)]
|
||||||
public static extern bool VirtualFreeEx(IntPtr hProcess, IntPtr lpAddress, int dwSize, int dwFreeType);
|
public static extern bool VirtualFreeEx(IntPtr hProcess, IntPtr lpAddress, int dwSize, AllocationType dwFreeType);
|
||||||
|
|
||||||
[DllImport("kernel32.dll", SetLastError = true)]
|
[DllImport("kernel32.dll", SetLastError = true)]
|
||||||
public static extern uint ResumeThread(IntPtr hThread);
|
public static extern uint ResumeThread(IntPtr hThread);
|
||||||
|
|||||||
@@ -9,6 +9,6 @@ namespace YaeAchievement.Win32;
|
|||||||
public struct ProcessInformation {
|
public struct ProcessInformation {
|
||||||
public IntPtr hProcess;
|
public IntPtr hProcess;
|
||||||
public IntPtr hThread;
|
public IntPtr hThread;
|
||||||
public int dwProcessId;
|
public uint dwProcessID;
|
||||||
public int dwThreadId;
|
public uint dwThreadID;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,20 +7,20 @@ namespace YaeAchievement.Win32;
|
|||||||
|
|
||||||
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
|
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
|
||||||
public struct StartupInfo {
|
public struct StartupInfo {
|
||||||
public int cb;
|
public uint cb;
|
||||||
public string lpReserved;
|
public string lpReserved;
|
||||||
public string lpDesktop;
|
public string lpDesktop;
|
||||||
public string lpTitle;
|
public string lpTitle;
|
||||||
public int dwX;
|
public uint dwX;
|
||||||
public int dwY;
|
public uint dwY;
|
||||||
public int dwXSize;
|
public uint dwXSize;
|
||||||
public int dwYSize;
|
public uint dwYSize;
|
||||||
public int dwXCountChars;
|
public uint dwXCountChars;
|
||||||
public int dwYCountChars;
|
public uint dwYCountChars;
|
||||||
public int dwFillAttribute;
|
public uint dwFillAttribute;
|
||||||
public int dwFlags;
|
public uint dwFlags;
|
||||||
public short wShowWindow;
|
public ushort wShowWindow;
|
||||||
public short cbReserved2;
|
public ushort cbReserved2;
|
||||||
public IntPtr lpReserved2;
|
public IntPtr lpReserved2;
|
||||||
public IntPtr hStdInput;
|
public IntPtr hStdInput;
|
||||||
public IntPtr hStdOutput;
|
public IntPtr hStdOutput;
|
||||||
|
|||||||
Reference in New Issue
Block a user