~ruther/csharp-dll-injector

ref: f606b7433c934d799b2c94bf8caf1a6f3bd38c13 csharp-dll-injector/DllUtils/Modules/RemoteModule.cs -rw-r--r-- 4.1 KiB
f606b743 — František Boháček chore: add license 4 years ago
                                                                                
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
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<T>(IntPtr function, T param)
        {
            return ExecuteFunctionRaw(function, GetParam(param));
        }

        public virtual FunctionResult ExecuteFunction(string function)
        {
            return ExecuteFunction(FindFunctionHandle(function));
        }

        public virtual FunctionResult ExecuteFunction<T>(string function, T param)
        {
            return ExecuteFunction(FindFunctionHandle(function), param);
        }

        public Task<IntPtr> FindFunctionHandleAsync(string name)
            => new Task<IntPtr>(() => FindFunctionHandle(name));

        public Task<FunctionResult> ExecuteFunctionAsync(IntPtr function)
            => new Task<FunctionResult>(() => ExecuteFunction(function));

        public Task<FunctionResult> ExecuteFunctionAsync(string function)
            => new Task<FunctionResult>(() => ExecuteFunction(function));

        public Task<FunctionResult> ExecuteFunctionAsync<T>(string function, T param)
            => new Task<FunctionResult>(() => ExecuteFunction(function, param));

        public virtual ParamData GetParam<T>(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; }
        }
    }
}
Do not follow this link