mirror of
https://github.com/gwdevhub/Daybreak.git
synced 2026-07-15 15:19:57 +00:00
fabb98f74e
Co-authored-by: Alexandru Macocian <amacocian@microsoft.com>
290 lines
8.9 KiB
C#
290 lines
8.9 KiB
C#
using Daybreak.Injector;
|
|
using Daybreak.Shared.Models;
|
|
using System.Diagnostics;
|
|
using System.Diagnostics.CodeAnalysis;
|
|
|
|
static void PrintUsage()
|
|
{
|
|
Console.WriteLine("======================================================");
|
|
Console.WriteLine("Usage: Daybreak.Injector [mode] <params>");
|
|
Console.WriteLine("Modes: ");
|
|
Console.WriteLine("- winapi");
|
|
Console.WriteLine("- stub");
|
|
Console.WriteLine("- launch");
|
|
Console.WriteLine("- resume");
|
|
Console.WriteLine("- resolve");
|
|
Console.WriteLine("Examples:");
|
|
Console.WriteLine("1) Daybreak.Injector winapi 1234 C:\\path\\to\\dll.dll");
|
|
Console.WriteLine("2) Daybreak.Injector stub 1234 entryPoint C:\\path\\to\\dll.dll");
|
|
Console.WriteLine("3) Daybreak.Injector launch true C:\\path\\to\\dll.dll arg1 arg2 arg3");
|
|
Console.WriteLine("4) Daybreak.Injector resume 1234");
|
|
Console.WriteLine("5) Daybreak.Injector resolve \"Z:\\path\\to\\Gw.exe\"");
|
|
Console.WriteLine("======================================================");
|
|
}
|
|
|
|
static bool TryParseInjectWinApiArgs(
|
|
string[] args,
|
|
[NotNullWhen(true)] out Process? process,
|
|
[NotNullWhen(true)] out string? dllPath,
|
|
out InjectorResponses.InjectResult exitCode)
|
|
{
|
|
process = default;
|
|
dllPath = default;
|
|
if (!int.TryParse(args[1], out var processId))
|
|
{
|
|
PrintUsage();
|
|
exitCode = InjectorResponses.InjectResult.InvalidProcess;
|
|
return false;
|
|
}
|
|
|
|
if (args.Length < 3)
|
|
{
|
|
PrintUsage();
|
|
exitCode = InjectorResponses.InjectResult.InvalidArgs;
|
|
return false;
|
|
}
|
|
|
|
dllPath = Path.GetFullPath(args[2]);
|
|
process = Process.GetProcessById(processId);
|
|
if (process is null)
|
|
{
|
|
Console.WriteLine($"Process {processId} could not be found");
|
|
exitCode = InjectorResponses.InjectResult.InvalidProcess;
|
|
return false;
|
|
}
|
|
|
|
|
|
if (!File.Exists(dllPath))
|
|
{
|
|
Console.WriteLine($"DLL path {dllPath} could not be found");
|
|
exitCode = InjectorResponses.InjectResult.InvalidDllPath;
|
|
return false;
|
|
}
|
|
|
|
exitCode = 0;
|
|
return true;
|
|
}
|
|
|
|
static bool TryParseInjectStubArgs(
|
|
string[] args,
|
|
[NotNullWhen(true)] out Process? process,
|
|
[NotNullWhen(true)] out string? dllPath,
|
|
[NotNullWhen(true)] out string? entryPoint,
|
|
out InjectorResponses.InjectResult exitCode)
|
|
{
|
|
process = default;
|
|
dllPath = default;
|
|
entryPoint = default;
|
|
if (!int.TryParse(args[1], out var processId))
|
|
{
|
|
PrintUsage();
|
|
exitCode = InjectorResponses.InjectResult.InvalidProcess;
|
|
return false;
|
|
}
|
|
|
|
if (args.Length < 4)
|
|
{
|
|
PrintUsage();
|
|
exitCode = InjectorResponses.InjectResult.InvalidArgs;
|
|
return false;
|
|
}
|
|
|
|
entryPoint = args[2];
|
|
dllPath = Path.GetFullPath(args[3]);
|
|
process = Process.GetProcessById(processId);
|
|
if (process is null)
|
|
{
|
|
Console.WriteLine($"Process {processId} could not be found");
|
|
exitCode = InjectorResponses.InjectResult.InvalidProcess;
|
|
return false;
|
|
}
|
|
|
|
|
|
if (!File.Exists(dllPath))
|
|
{
|
|
Console.WriteLine($"DLL path {dllPath} could not be found");
|
|
exitCode = InjectorResponses.InjectResult.InvalidDllPath;
|
|
return false;
|
|
}
|
|
|
|
exitCode = 0;
|
|
return true;
|
|
}
|
|
|
|
static bool TryParseLaunchArgs(
|
|
string[] args,
|
|
[NotNullWhen(true)] out string? gwPath,
|
|
[NotNullWhen(true)] out string? gwArgs,
|
|
[NotNullWhen(true)] out bool? elevated,
|
|
out InjectorResponses.LaunchResult exitCode)
|
|
{
|
|
gwPath = default;
|
|
gwArgs = default;
|
|
elevated = default;
|
|
if (args.Length < 3)
|
|
{
|
|
PrintUsage();
|
|
exitCode = InjectorResponses.LaunchResult.InvalidArgs;
|
|
return false;
|
|
}
|
|
|
|
gwPath = Path.GetFullPath(args[2]);
|
|
if (!bool.TryParse(args[1], out var parsedElevated))
|
|
{
|
|
PrintUsage();
|
|
exitCode = InjectorResponses.LaunchResult.InvalidElevated;
|
|
return false;
|
|
}
|
|
|
|
elevated = parsedElevated;
|
|
gwArgs = args.Length > 3 ? string.Join(" ", args.Skip(3)) : string.Empty;
|
|
|
|
if (!File.Exists(gwPath))
|
|
{
|
|
Console.WriteLine($"Guild Wars path {gwPath} could not be found");
|
|
exitCode = InjectorResponses.LaunchResult.InvalidPath;
|
|
return false;
|
|
}
|
|
|
|
exitCode = 0;
|
|
return true;
|
|
}
|
|
|
|
static bool TryParseThreadResumeArgs(
|
|
string[] args,
|
|
[NotNullWhen(true)] out IntPtr? threadHwnd,
|
|
out InjectorResponses.ResumeResult exitCode)
|
|
{
|
|
threadHwnd = default;
|
|
if (args.Length < 2)
|
|
{
|
|
PrintUsage();
|
|
exitCode = InjectorResponses.ResumeResult.InvalidArgs;
|
|
return false;
|
|
}
|
|
|
|
if (!IntPtr.TryParse(args[1], out var threadInt))
|
|
{
|
|
PrintUsage();
|
|
exitCode = InjectorResponses.ResumeResult.InvalidThreadHandle;
|
|
return false;
|
|
}
|
|
|
|
threadHwnd = threadInt;
|
|
exitCode = InjectorResponses.ResumeResult.Success;
|
|
return true;
|
|
}
|
|
|
|
static bool TryParseResolveArgs(
|
|
string[] args,
|
|
[NotNullWhen(true)] out string? executablePath,
|
|
out InjectorResponses.ResolveResult exitCode)
|
|
{
|
|
executablePath = default;
|
|
if (args.Length < 2 || string.IsNullOrWhiteSpace(args[1]))
|
|
{
|
|
PrintUsage();
|
|
exitCode = InjectorResponses.ResolveResult.InvalidArgs;
|
|
return false;
|
|
}
|
|
|
|
executablePath = args[1];
|
|
exitCode = InjectorResponses.ResolveResult.Success;
|
|
return true;
|
|
}
|
|
|
|
if (args.Length < 1)
|
|
{
|
|
PrintUsage();
|
|
return (int)InjectorResponses.GenericResults.InvalidArgs;
|
|
}
|
|
|
|
var mode = args[0];
|
|
|
|
switch (mode)
|
|
{
|
|
case "winapi":
|
|
{
|
|
if (!TryParseInjectWinApiArgs(args, out var process, out var dllPath, out var parseResult))
|
|
{
|
|
Console.WriteLine($"ExitCode: {(int)parseResult}");
|
|
return (int)parseResult;
|
|
}
|
|
|
|
Console.WriteLine($"Starting WinAPI injection. Process {process.Id}. DllPath: {dllPath}");
|
|
var result = (int)ProcessInjector.InjectWithApi(process, dllPath);
|
|
Console.WriteLine($"ExitCode: {result}");
|
|
return result;
|
|
}
|
|
case "stub":
|
|
{
|
|
if (!TryParseInjectStubArgs(args, out var process, out var dllPath, out var entryPoint, out var parseResult))
|
|
{
|
|
Console.WriteLine($"ExitCode: {(int)parseResult}");
|
|
return (int)parseResult;
|
|
}
|
|
|
|
Console.WriteLine($"Starting stub injection. Process {process.Id}. EntryPoint {entryPoint}. DllPath: {dllPath}");
|
|
var result = StubInjector.Inject(process, dllPath, entryPoint, out var exitCode);
|
|
if (result is not InjectorResponses.InjectResult.Success)
|
|
{
|
|
Console.WriteLine($"ExitCode: {(int)result}");
|
|
return (int)result;
|
|
}
|
|
|
|
Console.WriteLine($"Stub returned {exitCode}");
|
|
Console.WriteLine($"ExitCode: {exitCode}");
|
|
return exitCode;
|
|
}
|
|
case "launch":
|
|
{
|
|
if (!TryParseLaunchArgs(args, out var gwPath, out var gwArgs, out var elevated, out var parseResult))
|
|
{
|
|
Console.WriteLine($"ExitCode: {(int)parseResult}");
|
|
return (int)parseResult;
|
|
}
|
|
|
|
Console.WriteLine($"Launching Guild Wars. Path {gwPath}. Elevated {elevated}. Args {gwArgs}");
|
|
var result = ProcessLauncher.LaunchGuildWars(gwPath, gwArgs, elevated.Value, out var threadHandle, out var processId);
|
|
Console.WriteLine($"ThreadHandle: {threadHandle}");
|
|
Console.WriteLine($"ProcessId: {processId}");
|
|
Console.WriteLine($"ExitCode: {(int)result}");
|
|
return (int)result;
|
|
}
|
|
case "resume":
|
|
{
|
|
if (!TryParseThreadResumeArgs(args, out var threadHwnd, out var parseResult))
|
|
{
|
|
Console.WriteLine($"ExitCode: {(int)parseResult}");
|
|
return (int)parseResult;
|
|
}
|
|
|
|
Console.WriteLine($"Resuming thread {threadHwnd.Value}");
|
|
var result = (int) ThreadResumer.Resume(threadHwnd.Value);
|
|
Console.WriteLine($"ExitCode: {result}");
|
|
return result;
|
|
}
|
|
case "resolve":
|
|
{
|
|
if (!TryParseResolveArgs(args, out var executablePath, out var parseResult))
|
|
{
|
|
Console.WriteLine($"ExitCode: {(int)parseResult}");
|
|
return (int)parseResult;
|
|
}
|
|
|
|
Console.WriteLine($"Resolving Wine PID for {executablePath}");
|
|
var result = ProcessResolver.Resolve(executablePath, out var processId);
|
|
if (result is InjectorResponses.ResolveResult.Success)
|
|
{
|
|
Console.WriteLine($"ProcessId: {processId}");
|
|
}
|
|
|
|
Console.WriteLine($"ExitCode: {(int)result}");
|
|
return (int)result;
|
|
}
|
|
default:
|
|
PrintUsage();
|
|
Console.WriteLine($"ExitCode: {(int)InjectorResponses.GenericResults.InvalidMode}");
|
|
return (int)InjectorResponses.GenericResults.InvalidMode;
|
|
}
|