~ruther/csharp-dll-injector

ref: da3477de37f81c8009d155d138a5ab42ad3fa8f4 csharp-dll-injector/DllUtils/Modules/RemoteModule.cs -rw-r--r-- 4.1 KiB
da3477de — František Boháček Add solution 5 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