diff --git a/.github/workflows/cd.yaml b/.github/workflows/cd.yaml
index 0a1bca33..8af89fc3 100644
--- a/.github/workflows/cd.yaml
+++ b/.github/workflows/cd.yaml
@@ -20,7 +20,7 @@ jobs:
strategy:
matrix:
- targetplatform: [x64]
+ targetplatform: [x86]
runs-on: windows-latest
@@ -97,11 +97,6 @@ jobs:
env:
RuntimeIdentifier: win-${{ matrix.targetplatform }}
- - name: Create publish injector files
- run: dotnet publish .\Daybreak.Injector\Daybreak.Injector.csproj -c $env:Configuration -r $env:RuntimeIdentifier --property:SolutionDir=$env:GITHUB_WORKSPACE -p:PublishReadyToRun=true -p:PublishSingleFile=true --self-contained true -o .\Publish
- env:
- RuntimeIdentifier: win-x86
-
- name: Pack publish files
run: |
Write-Host $env
diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml
index 2d174def..a4f0493f 100644
--- a/.github/workflows/ci.yaml
+++ b/.github/workflows/ci.yaml
@@ -19,7 +19,7 @@ jobs:
strategy:
matrix:
- targetplatform: [x64]
+ targetplatform: [x86]
runs-on: windows-latest
diff --git a/Daybreak.Injector/Daybreak.Injector.csproj b/Daybreak.Injector/Daybreak.Injector.csproj
deleted file mode 100644
index 28794419..00000000
--- a/Daybreak.Injector/Daybreak.Injector.csproj
+++ /dev/null
@@ -1,19 +0,0 @@
-
-
-
- Exe
- net8.0
- Daybreak.Injector
- enable
- enable
- AnyCPU;x86
- True
-
-
-
-
-
-
-
-
-
diff --git a/Daybreak.Injector/NativeMethods.cs b/Daybreak.Injector/NativeMethods.cs
deleted file mode 100644
index 74531eb3..00000000
--- a/Daybreak.Injector/NativeMethods.cs
+++ /dev/null
@@ -1,469 +0,0 @@
-using System.Runtime.InteropServices;
-using System.Runtime.InteropServices.ComTypes;
-using System.Text;
-
-namespace Daybreak.Injector;
-
-internal static class NativeMethods
-{
- public static uint WM_KEYDOWN = 0x0100;
- public static uint SWP_SHOWWINDOW = 0x0040;
- public static IntPtr HWND_TOPMOST = new(-1);
- public static IntPtr HWND_TOP = IntPtr.Zero;
- public const int WH_KEYBOARD_LL = 13;
- public const uint LIST_MODULES_32BIT = 0x01;
-
- public delegate IntPtr HookProc(int nCode, IntPtr wParam, IntPtr lParam);
-
- [StructLayout(LayoutKind.Sequential)]
- internal struct ProcessEntry32
- {
- public uint dwSize;
- public uint cntUsage;
- public uint th32ProcessID;
- public IntPtr th32DefaultHeapID;
- public uint th32ModuleID;
- public uint cntThreads;
- public uint th32ParentProcessID;
- public int pcPriClassBase;
- public uint dwFlags;
- [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)]
- public string szExeFile;
- };
- [StructLayout(LayoutKind.Sequential)]
- internal struct PEB
- {
- private readonly byte InheritedAddressSpace;
- private readonly byte ReadImageFileExecOptions;
- private readonly byte BeingDebugged;
- private readonly byte BitField;
- private readonly IntPtr Mutant;
- internal IntPtr ImageBaseAddress;
- }
- [StructLayout(LayoutKind.Sequential)]
- public struct SecurityAttributes
- {
- public uint nLength;
- public IntPtr lpSecurityDescriptor;
- public bool bInheritHandle;
- }
- [Flags]
- public enum MemoryProtection : uint
- {
- PAGE_EXECUTE = 0x10,
- PAGE_EXECUTE_READ = 0x20,
- PAGE_EXECUTE_READ_WRITE = 0x40,
- PAGE_EXECUTE_WRITECOPY = 0x80,
- PAGE_NOACCESS = 0x01,
- PAGE_READONLY = 0x02,
- PAGE_READWRITE = 0x04,
- PAGE_WRITECOPY = 0x08,
- PAGE_GUARD = 0x100,
- PAGE_NOCACHE = 0x200,
- PAGE_WRITECOMBINE = 0x400
- }
- [Flags]
- public enum MemoryAllocationType : uint
- {
- MEM_COMMIT = 0x00001000,
- MEM_RESERVE = 0x00002000,
- MEM_RESET = 0x00080000,
- MEM_RESET_UNDO = 0x1000000,
- MEM_LARGE_PAGES = 0x20000000,
- MEM_PHYSICAL = 0x00400000,
- MEM_TOP_DOWN = 0x00100000,
- MEM_WRITE_WATCH = 0x00200000
- }
- [StructLayout(LayoutKind.Sequential)]
- public readonly struct RECT
- {
- public readonly int Left, Top, Right, Bottom;
-
- public int Height => this.Bottom - this.Top;
-
- public int Width => this.Right - this.Left;
-
- public RECT(int left, int top, int right, int bottom)
- {
- this.Left = left;
- this.Top = top;
- this.Right = right;
- this.Bottom = bottom;
- }
- }
- [StructLayout(LayoutKind.Sequential, Pack = 1)]
- public struct SystemHandleInformation
- {
- public uint OwnerPID;
- public byte ObjectType;
- public byte HandleFlags;
- public ushort HandleValue;
- public UIntPtr ObjectPointer;
- public IntPtr AccessMask;
- }
- [StructLayout(LayoutKind.Sequential)]
- public struct ObjectBasicInformation
- {
- public uint Attributes;
- public uint GrantedAccess;
- public uint HandleCount;
- public uint PointerCount;
- public uint PagedPoolUsage;
- public uint NonPagedPoolUsage;
- public uint Reserved1;
- public uint Reserved2;
- public uint Reserved3;
- public uint NameInformationLength;
- public uint TypeInformationLength;
- public uint SecurityDescriptorLength;
- public FILETIME CreateTime;
- }
- [StructLayout(LayoutKind.Sequential)]
- public struct IoStatusBlock
- {
- public uint Status;
- public ulong Information;
- }
- [StructLayout(LayoutKind.Sequential)]
- public struct WindowInfo
- {
- public uint cbSize;
- public RECT rcWindow;
- public RECT rcClient;
- public uint dwStyle;
- public uint dwExStyle;
- public uint dwWindowStatus;
- public uint cxWindowBorders;
- public uint cyWindowBorders;
- public ushort atomWindowType;
- public ushort wCreatorVersion;
-
- public WindowInfo(bool? _) : this() // Allows automatic initialization of "cbSize" with "new WINDOWINFO(null/true/false)".
- {
- this.cbSize = (uint)(Marshal.SizeOf(typeof(WindowInfo)));
- }
-
- }
- [Flags]
- public enum DuplicateOptions : uint
- {
- DUPLICATE_CLOSE_SOURCE = 0x00000001,
- DUPLICATE_SAME_ACCESS = 0x00000002
- }
- [Flags]
- public enum ProcessAccessFlags : uint
- {
- All = 0x001F0FFF,
- Terminate = 0x00000001,
- CreateThread = 0x00000002,
- VMOperation = 0x00000008,
- VMRead = 0x00000010,
- VMWrite = 0x00000020,
- DupHandle = 0x00000040,
- SetInformation = 0x00000200,
- QueryInformation = 0x00000400,
- QueryLimitedInformation = 0x00001000,
- Synchronize = 0x00100000
- }
- [Flags]
- public enum NtStatus : uint
- {
- STATUS_SUCCESS = 0x00000000,
- STATUS_INFO_LENGTH_MISMATCH = 0xC0000004
- }
- [Flags]
- public enum ObjectInformationClass : uint
- {
- ObjectBasicInformation = 0,
- ObjectNameInformation = 1,
- ObjectTypeInformation = 2,
- ObjectAllTypesInformation = 3,
- ObjectHandleInformation = 4
- }
- [Flags]
- public enum SystemInformationClass : uint
- {
- SystemHandleInformation = 16
- }
- [Flags]
- public enum FileInformationClass
- {
- FileNameInformation = 9
- }
- [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;
- }
- [StructLayout(LayoutKind.Sequential)]
- public struct ProcessInformation
- {
- public IntPtr hProcess;
- public IntPtr hThread;
- public int dwProcessId;
- public int dwThreadId;
- }
- public enum ProcessInfoClass : uint
- {
- ProcessBasicInformation = 0x00,
- ProcessDebugPort = 0x07,
- ProcessExceptionPort = 0x08,
- ProcessAccessToken = 0x09,
- ProcessWow64Information = 0x1A,
- ProcessImageFileName = 0x1B,
- ProcessDebugObjectHandle = 0x1E,
- ProcessDebugFlags = 0x1F,
- ProcessExecuteFlags = 0x22,
- ProcessInstrumentationCallback = 0x28,
- MaxProcessInfoClass = 0x64
- }
- [StructLayout(LayoutKind.Sequential)]
- internal struct ProcessBasicInformation
- {
- private readonly IntPtr Reserved1;
- internal IntPtr PebBaseAddress;
- private readonly IntPtr Reserved2;
- private readonly IntPtr Reserved3;
- private readonly UIntPtr UniqueProcessId;
- private readonly IntPtr Reserved4;
- }
- public enum SaferLevel : uint
- {
- Disallowed = 0,
- Untrusted = 0x1000,
- Constrained = 0x10000,
- NormalUser = 0x20000,
- FullyTrusted = 0x40000
- }
- public enum SaferLevelScope : uint
- {
- Machine = 1,
- User = 2
- }
- public enum SaferOpen : uint
- {
- Open = 1
- }
- public enum SaferTokenBehaviour : uint
- {
- Default = 0x0,
- NullIfEqual = 0x1,
- CompareOnly = 0x2,
- MakeInert = 0x4,
- WantFlags = 0x8
- }
- public enum TokenInformationClass : uint
- {
- TokenUser = 1,
- TokenGroups,
- TokenPrivileges,
- TokenOwner,
- TokenPrimaryGroup,
- TokenDefaultDacl,
- TokenSource,
- TokenType,
- TokenImpersonationLevel,
- TokenStatistics,
- TokenRestrictedSids,
- TokenSessionId,
- TokenGroupsAndPrivileges,
- TokenSessionReference,
- TokenSandBoxInert,
- TokenAuditPolicy,
- TokenOrigin,
- TokenElevationType,
- TokenLinkedToken,
- TokenElevation,
- TokenHasRestrictions,
- TokenAccessInformation,
- TokenVirtualizationAllowed,
- TokenVirtualizationEnabled,
- TokenIntegrityLevel,
- TokenUiAccess,
- TokenMandatoryPolicy,
- TokenLogonSid,
- MaxTokenInfoClass
- }
- [StructLayout(LayoutKind.Sequential)]
- public struct TokenMandatoryLabel
- {
- public SidAndAttributes Label;
- }
- [StructLayout(LayoutKind.Sequential)]
- public struct SidAndAttributes
- {
- public IntPtr Sid;
- public int Attributes;
- }
- [StructLayout(LayoutKind.Sequential)]
- public struct Sid_Identifier_Authority
- {
- [MarshalAs(UnmanagedType.ByValArray, SizeConst = 6)]
- public byte[] Value;
- }
- [Flags]
- public enum CreationFlags : uint
- {
- CreateSuspended = 0x00000004,
- DetachedProcess = 0x00000008,
- CreateNoWindow = 0x08000000,
- ExtendedStartupInfoPresent = 0x00080000
- }
-
- public const int WM_SYSCOMMAND = 0x112;
-
- [DllImport("kernel32.dll", SetLastError = true)]
- public static extern IntPtr CreateToolhelp32Snapshot(uint dwFlags, uint th32ProcessID);
- [DllImport("kernel32.dll")]
- public static extern bool Process32First(IntPtr hSnapshot, ref ProcessEntry32 lppe);
- [DllImport("kernel32.dll")]
- public static extern bool Process32Next(IntPtr hSnapshot, ref ProcessEntry32 lppe);
- [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
- public static extern IntPtr SendMessage(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam);
- [DllImport("kernel32.dll")]
- public static extern bool CloseHandle(IntPtr hObject);
- [DllImport("kernel32.dll")]
- public static extern bool DuplicateHandle(IntPtr hSourceProcessHandle, IntPtr hSourceHandle, IntPtr hTargetProcessHandle, out IntPtr lpTargetHandle, uint dwDesiredAccess, [MarshalAs(UnmanagedType.Bool)] bool bInheritHandle, DuplicateOptions dwOptions);
- [DllImport("kernel32.dll")]
- public static extern IntPtr OpenProcess(ProcessAccessFlags dwDesiredAccess, bool bInheritHandle, uint dwProcessID);
- [DllImport("ntdll.dll", SetLastError = true)]
- public static extern NtStatus NtQueryInformationFile(IntPtr FileHandle, ref IoStatusBlock IoStatusBlock, IntPtr FileInformation, int FileInformationLength, FileInformationClass FileInformationClass);
- [DllImport("ntdll.dll")]
- public static extern NtStatus NtQueryObject(IntPtr ObjectHandle, ObjectInformationClass ObjectInformationClass, IntPtr ObjectInformation, int ObjectInformationLength, out int ReturnLength);
- [DllImport("ntdll.dll")]
- public static extern NtStatus NtQuerySystemInformation(SystemInformationClass SystemInformationClass, IntPtr SystemInformation, int SystemInformationLength, out int ReturnLength);
- [DllImport("kernel32.dll", CharSet = CharSet.Unicode)]
- public static extern bool QueryFullProcessImageName(IntPtr hProcess, uint dwFlags, StringBuilder lpExeName, ref uint lpdwSize);
- [DllImport("user32.dll")]
- public static extern bool SetWindowPos(IntPtr hwnd, IntPtr insertAfter, int x, int y, int cx, int cy, uint flags);
- [DllImport("user32.dll")]
- public static extern bool ShowWindow(IntPtr hwnd, int cmd);
- [DllImport("user32.dll", CharSet = CharSet.Auto)]
- public static extern int GetWindowTextLength(IntPtr hWnd);
- [DllImport("user32.dll", CharSet = CharSet.Unicode)]
- public static extern int GetWindowText(IntPtr hWnd, StringBuilder lpString, int nMaxCount);
- [DllImport("kernel32.dll", CharSet = CharSet.Unicode)]
- public static extern IntPtr LoadLibrary(string lpFileName);
- [DllImport("kernel32.dll", CharSet = CharSet.Auto)]
- public static extern bool FreeLibrary(IntPtr hModule);
- [DllImport("user32.dll", SetLastError = true)]
- public static extern IntPtr SetWindowsHookEx(int idHook, HookProc lpfn, IntPtr hMod, int dwThreadId);
- [DllImport("user32.dll", SetLastError = true)]
- public static extern bool UnhookWindowsHookEx(IntPtr hHook);
- [DllImport("user32.dll", SetLastError = true)]
- public static extern IntPtr CallNextHookEx(IntPtr hHook, int code, IntPtr wParam, IntPtr lParam);
- [DllImport("user32.dll")]
- public static extern IntPtr GetForegroundWindow();
- [DllImport("kernel32.dll", SetLastError = true)]
- public static extern bool ReadProcessMemory(IntPtr hProcess, uint lpBaseAddress, IntPtr lpBuffer, uint nSize, out uint lpNumberOfBytesRead);
- [DllImport("kernel32.dll", CallingConvention = CallingConvention.Winapi)]
- internal static extern bool ReadProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, [Out] byte[] lpBuffer, int dwSize, out IntPtr lpNumberOfBytesRead);
- [return: MarshalAs(UnmanagedType.Bool)]
- [DllImport("user32.dll", SetLastError = true)]
- public static extern bool GetWindowInfo(IntPtr hwnd, ref WindowInfo pwi);
- [DllImport("kernel32.dll", CallingConvention = CallingConvention.Winapi)]
- public static extern bool CreateProcess(
- string lpApplicationName, string lpCommandLine, ref SecurityAttributes lpProcessAttributes,
- ref SecurityAttributes lpThreadAttributes, bool bInheritHandles, uint dwCreationFlags,
- IntPtr lpEnvironment, string lpCurrentDirectory, [In] ref StartupInfo lpStartupInfo,
- out ProcessInformation lpProcessInformation);
- [DllImport("kernel32.dll", CallingConvention = CallingConvention.Winapi)]
- public static extern uint ResumeThread(IntPtr hThread);
- [DllImport("kernel32.dll", SetLastError = true)]
- public static extern IntPtr LocalFree(IntPtr hMem);
- [DllImport("kernel32.dll", CallingConvention = CallingConvention.Winapi)]
- public static extern bool WriteProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, byte[] lpBuffer, int dwSize, out IntPtr lpNumberOfBytesWritten);
- [DllImport("ntdll.dll", SetLastError = true, CallingConvention = CallingConvention.Winapi)]
- public static extern int NtQueryInformationProcess(IntPtr hProcess, ProcessInfoClass pic, out ProcessBasicInformation pbi, int cb, out int pSize);
- [DllImport("advapi32.dll", SetLastError = true, CallingConvention = CallingConvention.Winapi)]
- public static extern bool SaferCreateLevel(SaferLevelScope scopeId, SaferLevel levelId, SaferOpen openFlags, out IntPtr levelHandle, IntPtr reserved);
- [DllImport("advapi32.dll", SetLastError = true, CallingConvention = CallingConvention.Winapi)]
- public static extern bool SaferComputeTokenFromLevel(IntPtr levelHandle, IntPtr inAccessToken, out IntPtr outAccessToken, SaferTokenBehaviour flags, IntPtr lpReserved);
- [DllImport("advapi32.dll", SetLastError = true, CallingConvention = CallingConvention.Winapi)]
- public static extern bool SaferCloseLevel(IntPtr levelHandle);
- [DllImport("advapi32.dll", SetLastError = true, CallingConvention = CallingConvention.Winapi)]
- public static extern bool SetTokenInformation(IntPtr tokenHandle, TokenInformationClass tokenInformationokenInformationClass, ref TokenMandatoryLabel tokenInformation, uint tokenInformationLength);
- [DllImport("advapi32.dll", SetLastError = true, CallingConvention = CallingConvention.Winapi)]
- public static extern bool ConvertStringSidToSid(string stringSid, out IntPtr ptrSid);
- [DllImport("advapi32.dll")]
- public static extern uint GetLengthSid(IntPtr pSid);
- [DllImport("advapi32.dll", SetLastError = true, CallingConvention = CallingConvention.Winapi)]
- public static extern bool CreateProcessAsUser(
- IntPtr hToken,
- string lpApplicationName,
- string lpCommandLine,
- ref SecurityAttributes lpProcessAttributes,
- ref SecurityAttributes lpThreadAttributes,
- bool bInheritHandles,
- uint dwCreationFlags,
- IntPtr lpEnvironment,
- string lpCurrentDirectory,
- ref StartupInfo lpStartupInfo,
- out ProcessInformation lpProcessInformation);
- [DllImport("kernel32.dll", CharSet = CharSet.Unicode)]
- public static extern IntPtr GetModuleHandle(string lpModuleName);
- [DllImport("kernel32.dll")]
- public static extern IntPtr CreateRemoteThread(
- IntPtr hProcess,
- IntPtr lpThreadAttributes,
- uint dwStackSize,
- IntPtr lpStartAddress,
- IntPtr lpParameter,
- uint dwCreationFlags,
- out IntPtr lpThreadId);
-
- [DllImport("kernel32.dll", SetLastError = true, ExactSpelling = true)]
- public static extern IntPtr VirtualAllocEx(
- IntPtr hProcess,
- IntPtr lpAddress,
- IntPtr dwSize,
- uint dwAllocationType,
- uint dwProtect);
-
- [DllImport("kernel32.dll", SetLastError = true, ExactSpelling = true)]
- public static extern bool VirtualFreeEx(
- IntPtr hProcess,
- IntPtr lpAddress,
- uint dwSize,
- uint dwFreeType);
-
- [DllImport("kernel32.dll", CharSet = CharSet.Ansi, ExactSpelling = true, SetLastError = true)]
- public static extern IntPtr GetProcAddress(IntPtr hModule, string procName);
-
- [DllImport("kernel32.dll", SetLastError = true)]
- public static extern uint WaitForSingleObject(IntPtr hHandle, uint dwMilliseconds);
-
- [DllImport("kernel32.dll", SetLastError = true)]
- public static extern uint GetExitCodeThread(IntPtr hHandle, out IntPtr dwMilliseconds);
- [DllImport("kernel32.dll", SetLastError = true)]
- public static extern bool WriteProcessMemory(
- IntPtr hProcess,
- IntPtr lpBaseAddress,
- IntPtr lpBuffer,
- int nSize,
- out IntPtr lpNumberOfBytesWritten);
- [DllImport("kernel32.dll", SetLastError = true)]
- public static extern bool ReadProcessMemory(
- IntPtr hProcess,
- IntPtr lpBaseAddress,
- IntPtr lpBuffer,
- int nSize,
- out IntPtr lpNumberOfBytesRead);
-}
diff --git a/Daybreak.Injector/ProcessInjector.cs b/Daybreak.Injector/ProcessInjector.cs
deleted file mode 100644
index 6b716413..00000000
--- a/Daybreak.Injector/ProcessInjector.cs
+++ /dev/null
@@ -1,141 +0,0 @@
-using System.Diagnostics;
-using System.Runtime.InteropServices;
-using System.Text;
-
-namespace Daybreak.Injector;
-internal static class ProcessInjector
-{
- public static Task Inject(Process process, string pathToDll, CancellationToken cancellationToken)
- {
- return Task.Factory.StartNew(() =>
- {
- return InjectWithWinApi(process, pathToDll);
- }, cancellationToken, TaskCreationOptions.LongRunning, TaskScheduler.Current);
- }
-
- private static bool InjectWithWinApi(Process process, string pathToDll)
- {
- var modulefullpath = Path.GetFullPath(pathToDll);
-
- if (!File.Exists(modulefullpath))
- {
- Console.WriteLine("Dll to inject not found");
- return false;
- }
-
- var hKernel32 = NativeMethods.GetModuleHandle("kernel32.dll");
- if (hKernel32 == IntPtr.Zero)
- {
- Console.WriteLine("Unable to get a handle of kernel32.dll");
- return false;
- }
-
- var hLoadLib = NativeMethods.GetProcAddress(hKernel32, "LoadLibraryW");
- if (hLoadLib == IntPtr.Zero)
- {
- Console.WriteLine("Unable to get the address of LoadLibraryW");
- return false;
- }
-
- var hStringBuffer = NativeMethods.VirtualAllocEx(process.Handle, IntPtr.Zero, new IntPtr(2 * (modulefullpath.Length + 1)),
- 0x3000 /* MEM_COMMIT | MEM_RESERVE */, 0x4 /* PAGE_READWRITE */);
- if (hStringBuffer == IntPtr.Zero)
- {
- Console.WriteLine("Unable to allocate memory for module path");
- return false;
- }
-
- WriteWString(process, hStringBuffer, modulefullpath);
- if (ReadWString(process, hStringBuffer, 260) != modulefullpath)
- {
- Console.WriteLine("Module path string is not correct");
- return false;
- }
-
- var hThread = NativeMethods.CreateRemoteThread(process.Handle, IntPtr.Zero, 0, hLoadLib, hStringBuffer, 0, out _);
- if (hThread == IntPtr.Zero)
- {
- Console.WriteLine("Unable to create remote thread");
- return false;
- }
-
- var threadResult = NativeMethods.WaitForSingleObject(hThread, 30000u);
- if (threadResult is 0x102 or 0xFFFFFFFF /* WAIT_FAILED */)
- {
- Console.WriteLine($"Exception occurred while waiting for the remote thread. Result is {threadResult}");
- return false;
- }
-
- var dllResult = NativeMethods.GetExitCodeThread(hThread, out _);
- if (dllResult == 0)
- {
- Console.WriteLine($"Injected dll returned non-success status code {dllResult}");
- return false;
- }
-
- var memoryFreeResult = NativeMethods.VirtualFreeEx(process.Handle, hStringBuffer, 0, 0x8000 /* MEM_RELEASE */);
- if (!memoryFreeResult)
- {
- Console.WriteLine($"Failed to free dll memory");
- }
-
- return memoryFreeResult;
- }
-
- private static void WriteBytes(Process process, IntPtr address, byte[] data)
- {
- var size = data.Length;
- var buffer = Marshal.AllocHGlobal(size);
- Marshal.Copy(data, 0, buffer, size);
-
- NativeMethods.WriteProcessMemory(
- process.Handle,
- address,
- buffer,
- size,
- out _);
-
- Marshal.FreeHGlobal(buffer);
- }
-
- private static void WriteWString(Process process, IntPtr address, string data)
- {
- WriteBytes(process, address, Encoding.Unicode.GetBytes(data));
- }
-
- private static string ReadWString(Process process, IntPtr address, int maxsize, Encoding? encoding = null)
- {
- encoding ??= Encoding.Unicode;
- var rawbytes = ReadBytes(process, address, maxsize);
- if (rawbytes.Length == 0)
- {
- return "";
- }
-
- var ret = encoding.GetString(rawbytes);
- if (ret.Contains('\0'))
- {
- ret = ret[..ret.IndexOf('\0')];
- }
-
- return ret;
- }
-
- private static byte[] ReadBytes(Process process, IntPtr address, int size)
- {
- var buffer = Marshal.AllocHGlobal(size);
-
- NativeMethods.ReadProcessMemory(process.Handle,
- address,
- buffer,
- size,
- out _
- );
-
- var ret = new byte[size];
- Marshal.Copy(buffer, ret, 0, size);
- Marshal.FreeHGlobal(buffer);
-
- return ret;
- }
-}
diff --git a/Daybreak.Injector/Program.cs b/Daybreak.Injector/Program.cs
deleted file mode 100644
index 2ab72a1a..00000000
--- a/Daybreak.Injector/Program.cs
+++ /dev/null
@@ -1,63 +0,0 @@
-using Daybreak.Injector;
-using System.Diagnostics;
-
-var processId = -1;
-var pathToDll = string.Empty;
-
-if (args.Length != 4)
-{
- Console.WriteLine("Daybreak Injector");
- Console.WriteLine("Usage:");
- Console.WriteLine("Daybreak.Injector.exe -p [PROCESS_ID] -d [PATH_TO_DLL]");
- return -1;
-}
-
-for (var i = 0; i < args.Length - 1; i++)
-{
- if (args[i].ToLower() == "-p" &&
- int.TryParse(args[i + 1], out var parsedId))
- {
- processId = parsedId;
- i++;
- }
- else if (args[i].ToLower() == "-d")
- {
- pathToDll = args[i + 1];
- i++;
- }
-}
-
-if (processId == -1)
-{
- Console.WriteLine("Error: Process id was not specified");
- return -1;
-}
-
-if (pathToDll == string.Empty)
-{
- Console.WriteLine("Error: Path to dll was not specified");
- return -1;
-}
-
-if (!File.Exists(pathToDll))
-{
- Console.WriteLine("Error: Provided dll could not be found");
- return -1;
-}
-
-var maybeProcess = Process.GetProcessById(processId);
-if (maybeProcess is null)
-{
- Console.WriteLine("Error: Could not find desired process");
- return -1;
-}
-
-var result = await ProcessInjector.Inject(maybeProcess, pathToDll, CancellationToken.None);
-if (result is false)
-{
- Console.WriteLine("Error: Failed to inject dll");
- return -1;
-}
-
-Console.WriteLine("Injected dll");
-return 0;
diff --git a/Daybreak.sln b/Daybreak.sln
index 23d2fb88..91c3028b 100644
--- a/Daybreak.sln
+++ b/Daybreak.sln
@@ -34,8 +34,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Daybreak.7ZipExtractor", "Daybreak.7ZipExtractor\Daybreak.7ZipExtractor.csproj", "{CA60F9AC-A496-4DB6-970E-ECE73B051C05}"
EndProject
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Daybreak.Injector", "Daybreak.Injector\Daybreak.Injector.csproj", "{2C1AB589-A533-41B6-9F8B-4328AD122437}"
-EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -94,18 +92,6 @@ Global
{CA60F9AC-A496-4DB6-970E-ECE73B051C05}.Release|x64.Build.0 = Release|Any CPU
{CA60F9AC-A496-4DB6-970E-ECE73B051C05}.Release|x86.ActiveCfg = Release|x64
{CA60F9AC-A496-4DB6-970E-ECE73B051C05}.Release|x86.Build.0 = Release|x64
- {2C1AB589-A533-41B6-9F8B-4328AD122437}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {2C1AB589-A533-41B6-9F8B-4328AD122437}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {2C1AB589-A533-41B6-9F8B-4328AD122437}.Debug|x64.ActiveCfg = Debug|x86
- {2C1AB589-A533-41B6-9F8B-4328AD122437}.Debug|x64.Build.0 = Debug|x86
- {2C1AB589-A533-41B6-9F8B-4328AD122437}.Debug|x86.ActiveCfg = Debug|x86
- {2C1AB589-A533-41B6-9F8B-4328AD122437}.Debug|x86.Build.0 = Debug|x86
- {2C1AB589-A533-41B6-9F8B-4328AD122437}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {2C1AB589-A533-41B6-9F8B-4328AD122437}.Release|Any CPU.Build.0 = Release|Any CPU
- {2C1AB589-A533-41B6-9F8B-4328AD122437}.Release|x64.ActiveCfg = Release|Any CPU
- {2C1AB589-A533-41B6-9F8B-4328AD122437}.Release|x64.Build.0 = Release|Any CPU
- {2C1AB589-A533-41B6-9F8B-4328AD122437}.Release|x86.ActiveCfg = Release|Any CPU
- {2C1AB589-A533-41B6-9F8B-4328AD122437}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
diff --git a/Daybreak/Daybreak.csproj b/Daybreak/Daybreak.csproj
index 719d8a9b..c750dfb6 100644
--- a/Daybreak/Daybreak.csproj
+++ b/Daybreak/Daybreak.csproj
@@ -11,7 +11,7 @@
preview
Daybreak.ico
true
- 0.9.9.12
+ 0.9.9.13
true
cfb2a489-db80-448d-a969-80270f314c46
True
diff --git a/Daybreak/Services/ApplicationLauncher/ApplicationLauncher.cs b/Daybreak/Services/ApplicationLauncher/ApplicationLauncher.cs
index 33632514..2716e492 100644
--- a/Daybreak/Services/ApplicationLauncher/ApplicationLauncher.cs
+++ b/Daybreak/Services/ApplicationLauncher/ApplicationLauncher.cs
@@ -411,7 +411,11 @@ public void KillGuildWarsProcess(GuildWarsApplicationLaunchContext guildWarsAppl
return;
}
}
- catch (Win32Exception e)
+ catch (Win32Exception e) when (e.Message.Contains("Only part of a ReadProcessMemory or WriteProcessMemory request was completed"))
+ {
+ guildWarsApplicationLaunchContext.GuildWarsProcess.Kill();
+ }
+ catch (Win32Exception e) when (e.Message.Contains("Access is denied"))
{
this.logger.LogError(e, $"Insuficient privileges to kill GuildWars process with id {guildWarsApplicationLaunchContext.ProcessId}");
this.privilegeManager.RequestAdminPrivileges("Insufficient privileges to kill Guild Wars process. Please restart as administrator and try again.");
diff --git a/Daybreak/Services/Injection/ProcessInjector.cs b/Daybreak/Services/Injection/ProcessInjector.cs
index d4ac96e5..b6d3be39 100644
--- a/Daybreak/Services/Injection/ProcessInjector.cs
+++ b/Daybreak/Services/Injection/ProcessInjector.cs
@@ -1,16 +1,18 @@
-using Microsoft.Extensions.Logging;
+using Daybreak.Utils;
+using Microsoft.Extensions.Logging;
+using System;
using System.Core.Extensions;
using System.Diagnostics;
using System.Extensions;
using System.IO;
+using System.Runtime.InteropServices;
+using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace Daybreak.Services.Injection;
internal sealed class ProcessInjector : IProcessInjector
{
- private const string InjectorExe = "Daybreak.Injector.exe";
-
private readonly ILogger logger;
public ProcessInjector(
@@ -21,51 +23,133 @@ public ProcessInjector(
public Task Inject(Process process, string pathToDll, CancellationToken cancellationToken)
{
- return Task.Factory.StartNew(() => this.InjectWithInjector(process, pathToDll), cancellationToken, TaskCreationOptions.LongRunning, TaskScheduler.Current);
+ return Task.Factory.StartNew(() => this.InjectWithApi(process, pathToDll), cancellationToken, TaskCreationOptions.LongRunning, TaskScheduler.Current);
}
-
- private bool InjectWithInjector(Process process, string pathToDll)
+
+ private bool InjectWithApi(Process process, string pathToDll)
{
- var scopedLogger = this.logger.CreateScopedLogger(nameof(InjectWithInjector), pathToDll);
+ var scopedLogger = this.logger.CreateScopedLogger(nameof(this.InjectWithApi), pathToDll);
var modulefullpath = Path.GetFullPath(pathToDll);
+
if (!File.Exists(modulefullpath))
{
scopedLogger.LogError("Dll to inject not found");
return false;
}
- var injectorPath = Path.GetFullPath(InjectorExe);
- if (!File.Exists(injectorPath))
+ var hKernel32 = NativeMethods.GetModuleHandle("kernel32.dll");
+ if (hKernel32 == IntPtr.Zero)
+ {
+ scopedLogger.LogError("Unable to get a handle of kernel32.dll");
+ return false;
+ }
+
+ var hLoadLib = NativeMethods.GetProcAddress(hKernel32, "LoadLibraryW");
+ if (hLoadLib == IntPtr.Zero)
+ {
+ scopedLogger.LogError("Unable to get the address of LoadLibraryW");
+ return false;
+ }
+
+ var hStringBuffer = NativeMethods.VirtualAllocEx(process.Handle, IntPtr.Zero, new IntPtr(2 * (modulefullpath.Length + 1)),
+ 0x3000 /* MEM_COMMIT | MEM_RESERVE */, 0x4 /* PAGE_READWRITE */);
+ if (hStringBuffer == IntPtr.Zero)
+ {
+ scopedLogger.LogError("Unable to allocate memory for module path");
+ return false;
+ }
+
+ WriteWString(process, hStringBuffer, modulefullpath);
+ if (ReadWString(process, hStringBuffer, 260) != modulefullpath)
+ {
+ scopedLogger.LogError("Module path string is not correct");
+ return false;
+ }
+
+ var hThread = NativeMethods.CreateRemoteThread(process.Handle, IntPtr.Zero, 0, hLoadLib, hStringBuffer, 0, out _);
+ if (hThread == IntPtr.Zero)
+ {
+ scopedLogger.LogError("Unable to create remote thread");
+ return false;
+ }
+
+ var threadResult = NativeMethods.WaitForSingleObject(hThread, 30000u);
+ if (threadResult is 0x102 or 0xFFFFFFFF /* WAIT_FAILED */)
+ {
+ scopedLogger.LogError($"Exception occurred while waiting for the remote thread. Result is {threadResult}");
+ return false;
+ }
+
+ var dllResult = NativeMethods.GetExitCodeThread(hThread, out _);
+ if (dllResult == 0)
{
- scopedLogger.LogError("Could not find Daybreak injector");
+ scopedLogger.LogError($"Injected dll returned non-success status code {dllResult}");
return false;
}
- var injectionProcess = new Process
+ var memoryFreeResult = NativeMethods.VirtualFreeEx(process.Handle, hStringBuffer, 0, 0x8000 /* MEM_RELEASE */);
+ if (!memoryFreeResult)
{
- StartInfo = new ProcessStartInfo
- {
- Arguments = $"-p {process.Id} -d {pathToDll}",
- CreateNoWindow = true,
- RedirectStandardError = true,
- RedirectStandardInput = true,
- RedirectStandardOutput = true,
- FileName = injectorPath,
- }
- };
-
- injectionProcess.Start();
- injectionProcess.WaitForExit();
- var result = injectionProcess.ExitCode;
- if (result == 0)
+ scopedLogger.LogError($"Failed to free dll memory");
+ }
+
+ return memoryFreeResult;
+ }
+
+ private static void WriteBytes(Process process, IntPtr address, byte[] data)
+ {
+ var size = data.Length;
+ var buffer = Marshal.AllocHGlobal(size);
+ Marshal.Copy(data, 0, buffer, size);
+
+ NativeMethods.WriteProcessMemory(
+ process.Handle,
+ address,
+ buffer,
+ size,
+ out _);
+
+ Marshal.FreeHGlobal(buffer);
+ }
+
+ private static void WriteWString(Process process, IntPtr address, string data)
+ {
+ WriteBytes(process, address, Encoding.Unicode.GetBytes(data));
+ }
+
+ private static string ReadWString(Process process, IntPtr address, int maxsize, Encoding? encoding = null)
+ {
+ encoding ??= Encoding.Unicode;
+ var rawbytes = ReadBytes(process, address, maxsize);
+ if (rawbytes.Length == 0)
+ {
+ return "";
+ }
+
+ var ret = encoding.GetString(rawbytes);
+ if (ret.Contains('\0'))
{
- scopedLogger.LogInformation("Injected into process");
- return true;
+ ret = ret[..ret.IndexOf('\0')];
}
- var stdout = injectionProcess.StandardOutput.ReadToEnd();
- var stderr = injectionProcess.StandardError.ReadToEnd();
- scopedLogger.LogError($"Failed to inject. Details:\n{stdout}\n{stderr}");
- return false;
+ return ret;
+ }
+
+ private static byte[] ReadBytes(Process process, IntPtr address, int size)
+ {
+ var buffer = Marshal.AllocHGlobal(size);
+
+ NativeMethods.ReadProcessMemory(process.Handle,
+ address,
+ buffer,
+ size,
+ out _
+ );
+
+ var ret = new byte[size];
+ Marshal.Copy(buffer, ret, 0, size);
+ Marshal.FreeHGlobal(buffer);
+
+ return ret;
}
}