mirror of
https://github.com/gwdevhub/Daybreak.git
synced 2026-07-15 15:19:57 +00:00
138 lines
4.5 KiB
C#
138 lines
4.5 KiB
C#
using Daybreak.Shared.Models;
|
|
using System.Diagnostics;
|
|
using System.Runtime.InteropServices;
|
|
using System.Text;
|
|
|
|
namespace Daybreak.Injector;
|
|
|
|
public static class ProcessInjector
|
|
{
|
|
public static InjectorResponses.InjectResult InjectWithApi(Process process, string pathToDll)
|
|
{
|
|
var modulefullpath = Path.GetFullPath(pathToDll);
|
|
|
|
if (!File.Exists(modulefullpath))
|
|
{
|
|
Console.WriteLine("Dll to inject not found");
|
|
return InjectorResponses.InjectResult.InvalidDllPath;
|
|
}
|
|
|
|
var hKernel32 = NativeMethods.GetModuleHandle("kernel32.dll");
|
|
if (hKernel32 == IntPtr.Zero)
|
|
{
|
|
Console.WriteLine("Unable to get a handle of kernel32.dll");
|
|
return InjectorResponses.InjectResult.InvalidKernel32;
|
|
}
|
|
|
|
var hLoadLib = NativeMethods.GetProcAddress(hKernel32, "LoadLibraryW");
|
|
if (hLoadLib == IntPtr.Zero)
|
|
{
|
|
Console.WriteLine("Unable to get the address of LoadLibraryW");
|
|
return InjectorResponses.InjectResult.InvalidLoadLibraryW;
|
|
}
|
|
|
|
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 InjectorResponses.InjectResult.ModulePathAllocationFailed;
|
|
}
|
|
|
|
WriteWString(process, hStringBuffer, modulefullpath);
|
|
if (ReadWString(process, hStringBuffer, 260) != modulefullpath)
|
|
{
|
|
Console.WriteLine("Module path string is not correct");
|
|
return InjectorResponses.InjectResult.DllPathWriteFailed;
|
|
}
|
|
|
|
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 InjectorResponses.InjectResult.CreateRemoteThreadFailed;
|
|
}
|
|
|
|
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 InjectorResponses.InjectResult.RemoteThreadTimeout;
|
|
}
|
|
|
|
var dllResult = NativeMethods.GetExitCodeThread(hThread, out _);
|
|
if (dllResult == 0)
|
|
{
|
|
Console.WriteLine($"Injected dll returned non-success status code {dllResult}");
|
|
return InjectorResponses.InjectResult.DllExitCodeFailed;
|
|
}
|
|
|
|
var memoryFreeResult = NativeMethods.VirtualFreeEx(process.Handle, hStringBuffer, 0, 0x8000 /* MEM_RELEASE */);
|
|
if (!memoryFreeResult)
|
|
{
|
|
Console.WriteLine($"Failed to free dll memory");
|
|
}
|
|
|
|
return memoryFreeResult
|
|
? InjectorResponses.InjectResult.Success
|
|
: InjectorResponses.InjectResult.MemoryFreeFailed;
|
|
}
|
|
|
|
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;
|
|
}
|
|
}
|