using System; using System.Collections.Generic; using System.Linq; using System.Runtime.InteropServices; using System.Text; using System.Threading.Tasks; using DllUtils.Exceptions; using DllUtils.Interop; using DllUtils.Memory; using DllUtils.Process; using DllUtils.Serializers; using DllUtils.Threads; namespace DllUtils.Modules { public class RemoteModule : IModule { public RemoteModule(IntPtr remoteHandle, IntPtr localHandle, RemoteProcessHandle processHandle) { Process = processHandle; RemoteHandle = remoteHandle; LocalHandle = localHandle; } public IntPtr LocalHandle { get; } public IntPtr RemoteHandle { get; } public RemoteProcessHandle Process { get; } public virtual IntPtr FindFunctionHandle(string name) { Process.Open(); IntPtr localAddress = Kernel32.GetProcAddress(LocalHandle, name); long functionOffset = ((long)localAddress) - ((long)LocalHandle); long remoteAddressLong = ((long)RemoteHandle) + functionOffset; IntPtr remoteAddress = new IntPtr(remoteAddressLong); if (remoteAddress == IntPtr.Zero) { throw new FunctionException($"Function {name} not found."); } return remoteAddress; } public virtual FunctionResult ExecuteFunction(IntPtr function) { return ExecuteFunctionRaw(function, null); } public virtual FunctionResult ExecuteFunction(IntPtr function, T param) { return ExecuteFunctionRaw(function, GetParam(param)); } public virtual FunctionResult ExecuteFunction(string function) { return ExecuteFunction(FindFunctionHandle(function)); } public virtual FunctionResult ExecuteFunction(string function, T param) { return ExecuteFunction(FindFunctionHandle(function), param); } public Task FindFunctionHandleAsync(string name) => new Task(() => FindFunctionHandle(name)); public Task ExecuteFunctionAsync(IntPtr function) => new Task(() => ExecuteFunction(function)); public Task ExecuteFunctionAsync(string function) => new Task(() => ExecuteFunction(function)); public Task ExecuteFunctionAsync(string function, T param) => new Task(() => ExecuteFunction(function, param)); public virtual ParamData GetParam(T param) { RemoteParamSerializer serializer = new RemoteParamSerializer(Process); if (param.GetType().IsPrimitive) { return new ParamData { IsRemote = false, Value = Marshal.ReadIntPtr(param, 0) }; } AllocatedMemory memory = serializer.Serialize(param); return new ParamData { Allocated = memory, IsRemote = true, Value = memory.Address }; } public virtual FunctionResult ExecuteFunctionRaw(IntPtr function, ParamData param) { Process.Open(); RemoteThread thread = new RemoteThread(Process, function, param?.Value ?? IntPtr.Zero, IntPtr.Zero); if (!thread.Create()) { throw new ThreadCreationException("Could not create remote thread. Check if architecture of the remote process matches local process"); } thread.WaitForResult(10 * 1000); thread.CheckResult(); FunctionResult result = new FunctionResult(Process, thread.GetResult()); if (param?.IsRemote ?? false) { param.Allocated.Free(); } return result; } public class ParamData { public bool IsRemote { get; set; } public IntPtr Value { get; set; } public AllocatedMemory Allocated { get; set; } } } }