optimize code and update

This commit is contained in:
HolographicHat
2022-06-11 00:36:54 +08:00
parent 3917f3e6c7
commit ef6a72312c
11 changed files with 139 additions and 99 deletions

5
src/Events/IEventBase.cs Normal file
View File

@@ -0,0 +1,5 @@
namespace YaeAchievement.Events;
public interface IEventBase {
}

View 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;
}
}

View File

@@ -2,4 +2,7 @@
public static class GlobalVars {
public static bool Verbose = false;
}
public const string LibName = "YaeAchievementLib.dll";
public const string PipeName = "YaeAchievementPipe";
public static bool UnexpectedExit = true;
}

View File

@@ -5,22 +5,17 @@ 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 unsafe bool CreateProcess(string path, out IntPtr hProc, out IntPtr hThread, out uint pid) {
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 var pi
);
pid = pi.dwProcessID;
hProc = pi.hProcess;
hThread = pi.hThread;
return result;
}
public static int LoadLibraryAndInject(IntPtr handle, string libPath) {

View File

@@ -1,46 +1,66 @@
using System.ComponentModel;
using System.Diagnostics;
using System.IO.Pipes;
using YaeAchievement;
using YaeAchievement.Events;
using YaeAchievement.Win32;
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"));
// ReSharper disable once UnusedLocalFunctionReturnValue
Thread StartAndWaitResult(string exePath, Func<IEventBase, bool> onEvent) {
if (!Injector.CreateProcess(exePath, out var hProcess, out var hThread, out var pid)) {
Environment.Exit(new Win32Exception().PrintMsgAndReturnErrCode("ICreateProcess 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();
if (Injector.LoadLibraryAndInject(hProcess, GlobalVars.LibName) != 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"));
}
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();

View File

@@ -1,13 +1,14 @@
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;
[Flags]
public enum AllocationType : uint {
Commit = 0x1000,
Reserve = 0x2000,
Decommit = 0x4000,
Release = 0x8000,
Reset = 0x80000,
Physical = 0x400000,
TopDown = 0x100000,
WriteWatch = 0x200000,
LargePages = 0x20000000
}

View File

@@ -1,8 +1,9 @@
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;
[Flags]
public enum CreationFlags : uint {
CreateSuspended = 0x00000004,
DetachedProcess = 0x00000008,
CreateNoWindow = 0x08000000,
ExtendedStartupInfoPresent = 0x00080000
}

View File

@@ -1,15 +1,16 @@
namespace YaeAchievement.Win32;
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;
[Flags]
public enum MemoryProtection : uint {
Execute = 0x10,
ExecuteRead = 0x20,
ExecuteReadWrite = 0x40,
ExecuteWriteCopy = 0x80,
NoAccess = 0x01,
ReadOnly = 0x02,
ReadWrite = 0x04,
WriteCopy = 0x08,
GuardModifierFlag = 0x100,
NoCacheModifierFlag = 0x200,
WriteCombineModifierFlag = 0x400
}

View File

@@ -14,7 +14,7 @@ public static class Native {
ref SecurityAttributes lpProcessAttributes,
ref SecurityAttributes lpThreadAttributes,
bool bInheritHandles,
int dwCreationFlags,
CreationFlags dwCreationFlags,
IntPtr lpEnvironment,
string? lpCurrentDirectory,
[In] ref StartupInfo lpStartupInfo,
@@ -46,12 +46,12 @@ public static class Native {
IntPtr hProcess,
IntPtr lpAddress,
int dwSize,
int flAllocationType,
int flProtect
AllocationType flAllocationType,
MemoryProtection flProtect
);
[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)]
public static extern uint ResumeThread(IntPtr hThread);

View File

@@ -9,6 +9,6 @@ namespace YaeAchievement.Win32;
public struct ProcessInformation {
public IntPtr hProcess;
public IntPtr hThread;
public int dwProcessId;
public int dwThreadId;
public uint dwProcessID;
public uint dwThreadID;
}

View File

@@ -7,20 +7,20 @@ namespace YaeAchievement.Win32;
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public struct StartupInfo {
public int cb;
public uint 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 uint dwX;
public uint dwY;
public uint dwXSize;
public uint dwYSize;
public uint dwXCountChars;
public uint dwYCountChars;
public uint dwFillAttribute;
public uint dwFlags;
public ushort wShowWindow;
public ushort cbReserved2;
public IntPtr lpReserved2;
public IntPtr hStdInput;
public IntPtr hStdOutput;