mirror of
https://github.com/gwdevhub/Daybreak.git
synced 2026-07-15 15:19:57 +00:00
Release 0.9.9.13 (#560)
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -19,7 +19,7 @@ jobs:
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
targetplatform: [x64]
|
||||
targetplatform: [x86]
|
||||
|
||||
runs-on: windows-latest
|
||||
|
||||
|
||||
@@ -1,19 +0,0 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<RootNamespace>Daybreak.Injector</RootNamespace>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<Platforms>AnyCPU;x86</Platforms>
|
||||
<PublishSingleFile>True</PublishSingleFile>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="8.0.0" />
|
||||
<PackageReference Include="SystemExtensions.NetCore" Version="1.0.1" />
|
||||
<PackageReference Include="SystemExtensions.NetStandard" Version="1.6.2" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -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);
|
||||
}
|
||||
@@ -1,141 +0,0 @@
|
||||
using System.Diagnostics;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
|
||||
namespace Daybreak.Injector;
|
||||
internal static class ProcessInjector
|
||||
{
|
||||
public static Task<bool> 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;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
@@ -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
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
<LangVersion>preview</LangVersion>
|
||||
<ApplicationIcon>Daybreak.ico</ApplicationIcon>
|
||||
<IncludePackageReferencesDuringMarkupCompilation>true</IncludePackageReferencesDuringMarkupCompilation>
|
||||
<Version>0.9.9.12</Version>
|
||||
<Version>0.9.9.13</Version>
|
||||
<EnableWindowsTargeting>true</EnableWindowsTargeting>
|
||||
<UserSecretsId>cfb2a489-db80-448d-a969-80270f314c46</UserSecretsId>
|
||||
<AllowUnsafeBlocks>True</AllowUnsafeBlocks>
|
||||
|
||||
@@ -411,7 +411,11 @@ internal sealed class ApplicationLauncher : IApplicationLauncher
|
||||
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<LauncherView>("Insufficient privileges to kill Guild Wars process. Please restart as administrator and try again.");
|
||||
|
||||
@@ -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<ProcessInjector> logger;
|
||||
|
||||
public ProcessInjector(
|
||||
@@ -21,51 +23,133 @@ internal sealed class ProcessInjector : IProcessInjector
|
||||
|
||||
public Task<bool> 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("Could not find Daybreak injector");
|
||||
scopedLogger.LogError("Unable to get a handle of kernel32.dll");
|
||||
return false;
|
||||
}
|
||||
|
||||
var injectionProcess = new Process
|
||||
var hLoadLib = NativeMethods.GetProcAddress(hKernel32, "LoadLibraryW");
|
||||
if (hLoadLib == IntPtr.Zero)
|
||||
{
|
||||
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.LogInformation("Injected into process");
|
||||
return true;
|
||||
scopedLogger.LogError("Unable to get the address of LoadLibraryW");
|
||||
return false;
|
||||
}
|
||||
|
||||
var stdout = injectionProcess.StandardOutput.ReadToEnd();
|
||||
var stderr = injectionProcess.StandardError.ReadToEnd();
|
||||
scopedLogger.LogError($"Failed to inject. Details:\n{stdout}\n{stderr}");
|
||||
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($"Injected dll returned non-success status code {dllResult}");
|
||||
return false;
|
||||
}
|
||||
|
||||
var memoryFreeResult = NativeMethods.VirtualFreeEx(process.Handle, hStringBuffer, 0, 0x8000 /* MEM_RELEASE */);
|
||||
if (!memoryFreeResult)
|
||||
{
|
||||
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'))
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user