Skip to content

Commit ee55fdb

Browse files
committed
Added interfaces to break down RemoteProcess functionality.
1 parent b7ebbae commit ee55fdb

File tree

8 files changed

+179
-106
lines changed

8 files changed

+179
-106
lines changed

ReClass.NET/AddressParser/DynamicCompiler.cs

Lines changed: 22 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -9,68 +9,68 @@ namespace ReClassNET.AddressParser
99
{
1010
public class DynamicCompiler : IExecuter
1111
{
12-
public IntPtr Execute(IExpression operation, RemoteProcess process)
12+
public IntPtr Execute(IExpression operation, IProcessReader processReader)
1313
{
1414
Contract.Requires(operation != null);
15-
Contract.Requires(process != null);
15+
Contract.Requires(processReader != null);
1616

17-
return CompileAddressFormula(operation)(process);
17+
return CompileAddressFormula(operation)(processReader);
1818
}
1919

20-
public static Func<RemoteProcess, IntPtr> CompileAddressFormula(IExpression expression)
20+
public static Func<IProcessReader, IntPtr> CompileAddressFormula(IExpression expression)
2121
{
2222
Contract.Requires(expression != null);
2323

24-
var processParameter = Expression.Parameter(typeof(RemoteProcess));
24+
var processParameter = Expression.Parameter(typeof(IProcessReader));
2525

26-
return Expression.Lambda<Func<RemoteProcess, IntPtr>>(
26+
return Expression.Lambda<Func<IProcessReader, IntPtr>>(
2727
GenerateMethodBody(expression, processParameter),
2828
processParameter
2929
).Compile();
3030
}
3131

32-
private static Expression GenerateMethodBody(IExpression operation, ParameterExpression processParameter)
32+
private static Expression GenerateMethodBody(IExpression operation, Expression parameter)
3333
{
3434
Contract.Requires(operation != null);
35-
Contract.Requires(processParameter != null);
35+
Contract.Requires(parameter != null);
3636

3737
switch (operation)
3838
{
3939
case AddExpression addExpression:
4040
{
41-
var argument1 = GenerateMethodBody(addExpression.Lhs, processParameter);
42-
var argument2 = GenerateMethodBody(addExpression.Rhs, processParameter);
41+
var argument1 = GenerateMethodBody(addExpression.Lhs, parameter);
42+
var argument2 = GenerateMethodBody(addExpression.Rhs, parameter);
4343

4444
return Expression.Call(null, GetIntPtrExtension(nameof(IntPtrExtension.Add)), argument1, argument2);
4545
}
4646
case SubtractExpression subtractExpression:
4747
{
48-
var argument1 = GenerateMethodBody(subtractExpression.Lhs, processParameter);
49-
var argument2 = GenerateMethodBody(subtractExpression.Rhs, processParameter);
48+
var argument1 = GenerateMethodBody(subtractExpression.Lhs, parameter);
49+
var argument2 = GenerateMethodBody(subtractExpression.Rhs, parameter);
5050

5151
return Expression.Call(null, GetIntPtrExtension(nameof(IntPtrExtension.Sub)), argument1, argument2);
5252
}
5353
case MultiplyExpression multiplyExpression:
5454
{
55-
var argument1 = GenerateMethodBody(multiplyExpression.Lhs, processParameter);
56-
var argument2 = GenerateMethodBody(multiplyExpression.Rhs, processParameter);
55+
var argument1 = GenerateMethodBody(multiplyExpression.Lhs, parameter);
56+
var argument2 = GenerateMethodBody(multiplyExpression.Rhs, parameter);
5757

5858
return Expression.Call(null, GetIntPtrExtension(nameof(IntPtrExtension.Mul)), argument1, argument2);
5959
}
6060
case DivideExpression divideExpression:
6161
{
62-
var argument1 = GenerateMethodBody(divideExpression.Lhs, processParameter);
63-
var argument2 = GenerateMethodBody(divideExpression.Rhs, processParameter);
62+
var argument1 = GenerateMethodBody(divideExpression.Lhs, parameter);
63+
var argument2 = GenerateMethodBody(divideExpression.Rhs, parameter);
6464

6565
return Expression.Call(null, GetIntPtrExtension(nameof(IntPtrExtension.Div)), argument1, argument2);
6666
}
6767
case ModuleExpression moduleExpression:
6868
{
69-
var getModuleByNameFunc = typeof(RemoteProcess).GetRuntimeMethod(nameof(RemoteProcess.GetModuleByName), new[] { typeof(string) });
69+
var getModuleByNameFunc = typeof(IProcessReader).GetRuntimeMethod(nameof(IProcessReader.GetModuleByName), new[] { typeof(string) });
7070
var moduleNameConstant = Expression.Constant(moduleExpression.Name);
7171

7272
var moduleVariable = Expression.Variable(typeof(Memory.Module));
73-
var assignExpression = Expression.Assign(moduleVariable, Expression.Call(processParameter, getModuleByNameFunc, moduleNameConstant));
73+
var assignExpression = Expression.Assign(moduleVariable, Expression.Call(parameter, getModuleByNameFunc, moduleNameConstant));
7474

7575
return Expression.Block(
7676
new[] { moduleVariable },
@@ -90,12 +90,12 @@ private static Expression GenerateMethodBody(IExpression operation, ParameterExp
9090
}
9191
case ReadMemoryExpression readMemoryExpression:
9292
{
93-
var argument = GenerateMethodBody(readMemoryExpression.Expression, processParameter);
93+
var argument = GenerateMethodBody(readMemoryExpression.Expression, parameter);
9494

95-
var functionName = readMemoryExpression.ByteCount == 4 ? nameof(RemoteProcess.ReadRemoteInt32) : nameof(RemoteProcess.ReadRemoteInt64);
96-
var readRemoteIntFn = typeof(RemoteProcess).GetRuntimeMethod(functionName, new[] { typeof(IntPtr) });
95+
var functionName = readMemoryExpression.ByteCount == 4 ? nameof(IProcessReader.ReadRemoteInt32) : nameof(IProcessReader.ReadRemoteInt64);
96+
var readRemoteIntFn = typeof(IProcessReader).GetRuntimeMethod(functionName, new[] { typeof(IntPtr) });
9797

98-
var callExpression = Expression.Call(processParameter, readRemoteIntFn, argument);
98+
var callExpression = Expression.Call(parameter, readRemoteIntFn, argument);
9999

100100
var paramType = readMemoryExpression.ByteCount == 4 ? typeof(int) : typeof(long);
101101
var convertFn = typeof(IntPtrExtension).GetRuntimeMethod(nameof(IntPtrExtension.From), new[] { paramType });

ReClass.NET/AddressParser/IExecuter.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,6 @@ namespace ReClassNET.AddressParser
55
{
66
public interface IExecuter
77
{
8-
IntPtr Execute(IExpression expression, RemoteProcess process);
8+
IntPtr Execute(IExpression expression, IProcessReader processReader);
99
}
1010
}

ReClass.NET/AddressParser/Interpreter.cs

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -7,18 +7,18 @@ namespace ReClassNET.AddressParser
77
{
88
public class Interpreter : IExecuter
99
{
10-
public IntPtr Execute(IExpression expression, RemoteProcess process)
10+
public IntPtr Execute(IExpression expression, IProcessReader processReader)
1111
{
1212
Contract.Requires(expression != null);
13-
Contract.Requires(process != null);
13+
Contract.Requires(processReader != null);
1414

1515
switch (expression)
1616
{
1717
case ConstantExpression constantExpression:
1818
return IntPtrExtension.From(constantExpression.Value);
1919
case ModuleExpression moduleExpression:
2020
{
21-
var module = process.GetModuleByName(moduleExpression.Name);
21+
var module = processReader.GetModuleByName(moduleExpression.Name);
2222
if (module != null)
2323
{
2424
return module.Start;
@@ -27,22 +27,22 @@ public IntPtr Execute(IExpression expression, RemoteProcess process)
2727
return IntPtr.Zero;
2828
}
2929
case AddExpression addExpression:
30-
return Execute(addExpression.Lhs, process).Add(Execute(addExpression.Rhs, process));
30+
return Execute(addExpression.Lhs, processReader).Add(Execute(addExpression.Rhs, processReader));
3131
case SubtractExpression subtractExpression:
32-
return Execute(subtractExpression.Lhs, process).Sub(Execute(subtractExpression.Rhs, process));
32+
return Execute(subtractExpression.Lhs, processReader).Sub(Execute(subtractExpression.Rhs, processReader));
3333
case MultiplyExpression multiplyExpression:
34-
return Execute(multiplyExpression.Lhs, process).Mul(Execute(multiplyExpression.Rhs, process));
34+
return Execute(multiplyExpression.Lhs, processReader).Mul(Execute(multiplyExpression.Rhs, processReader));
3535
case DivideExpression divideExpression:
36-
return Execute(divideExpression.Lhs, process).Div(Execute(divideExpression.Rhs, process));
36+
return Execute(divideExpression.Lhs, processReader).Div(Execute(divideExpression.Rhs, processReader));
3737
case ReadMemoryExpression readMemoryExpression:
38-
var readFromAddress = Execute(readMemoryExpression.Expression, process);
38+
var readFromAddress = Execute(readMemoryExpression.Expression, processReader);
3939
if (readMemoryExpression.ByteCount == 4)
4040
{
41-
return IntPtrExtension.From(process.ReadRemoteInt32(readFromAddress));
41+
return IntPtrExtension.From(processReader.ReadRemoteInt32(readFromAddress));
4242
}
4343
else
4444
{
45-
return IntPtrExtension.From(process.ReadRemoteInt64(readFromAddress));
45+
return IntPtrExtension.From(processReader.ReadRemoteInt64(readFromAddress));
4646
}
4747
default:
4848
throw new ArgumentException($"Unsupported operation '{expression.GetType().FullName}'.");
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
using System;
2+
using System.Collections.Generic;
3+
4+
namespace ReClassNET.Memory
5+
{
6+
public interface IProcessReader : IRemoteMemoryReader
7+
{
8+
Section GetSectionToPointer(IntPtr address);
9+
10+
Module GetModuleToPointer(IntPtr address);
11+
12+
Module GetModuleByName(string name);
13+
14+
bool EnumerateRemoteSectionsAndModules(out List<Section> sections, out List<Module> modules);
15+
}
16+
}
Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
using System;
2+
using System.Text;
3+
4+
namespace ReClassNET.Memory
5+
{
6+
public interface IRemoteMemoryReader
7+
{
8+
/// <summary>Reads remote memory from the address into the buffer.</summary>
9+
/// <param name="address">The address to read from.</param>
10+
/// <param name="buffer">[out] The data buffer to fill. If the remote process is not valid, the buffer will get filled with zeros.</param>
11+
bool ReadRemoteMemoryIntoBuffer(IntPtr address, ref byte[] buffer);
12+
13+
/// <summary>Reads remote memory from the address into the buffer.</summary>
14+
/// <param name="address">The address to read from.</param>
15+
/// <param name="buffer">[out] The data buffer to fill. If the remote process is not valid, the buffer will get filled with zeros.</param>
16+
/// <param name="offset">The offset in the data.</param>
17+
/// <param name="length">The number of bytes to read.</param>
18+
bool ReadRemoteMemoryIntoBuffer(IntPtr address, ref byte[] buffer, int offset, int length);
19+
20+
/// <summary>Reads <paramref name="size"/> bytes from the address in the remote process.</summary>
21+
/// <param name="address">The address to read from.</param>
22+
/// <param name="size">The size in bytes to read.</param>
23+
/// <returns>An array of bytes.</returns>
24+
byte[] ReadRemoteMemory(IntPtr address, int size);
25+
26+
/// <summary>Reads the object from the address in the remote process.</summary>
27+
/// <typeparam name="T">Type of the value to read.</typeparam>
28+
/// <param name="address">The address to read from.</param>
29+
/// <returns>The remote object.</returns>
30+
T ReadRemoteObject<T>(IntPtr address) where T : struct;
31+
32+
/// <summary>Reads a <see cref="sbyte"/> from the address in the remote process.</summary>
33+
/// <param name="address">The address to read from.</param>
34+
/// <returns>The data read as <see cref="sbyte"/> or 0 if the read fails.</returns>
35+
sbyte ReadRemoteInt8(IntPtr address);
36+
37+
/// <summary>Reads a <see cref="byte"/> from the address in the remote process.</summary>
38+
/// <param name="address">The address to read from.</param>
39+
/// <returns>The data read as <see cref="byte"/> or 0 if the read fails.</returns>
40+
byte ReadRemoteUInt8(IntPtr address);
41+
42+
/// <summary>Reads a <see cref="short"/> from the address in the remote process.</summary>
43+
/// <param name="address">The address to read from.</param>
44+
/// <returns>The data read as <see cref="short"/> or 0 if the read fails.</returns>
45+
short ReadRemoteInt16(IntPtr address);
46+
47+
/// <summary>Reads a <see cref="ushort"/> from the address in the remote process.</summary>
48+
/// <param name="address">The address to read from.</param>
49+
/// <returns>The data read as <see cref="ushort"/> or 0 if the read fails.</returns>
50+
ushort ReadRemoteUInt16(IntPtr address);
51+
52+
/// <summary>Reads a <see cref="int"/> from the address in the remote process.</summary>
53+
/// <param name="address">The address to read from.</param>
54+
/// <returns>The data read as <see cref="int"/> or 0 if the read fails.</returns>
55+
int ReadRemoteInt32(IntPtr address);
56+
57+
/// <summary>Reads a <see cref="uint"/> from the address in the remote process.</summary>
58+
/// <param name="address">The address to read from.</param>
59+
/// <returns>The data read as <see cref="uint"/> or 0 if the read fails.</returns>
60+
uint ReadRemoteUInt32(IntPtr address);
61+
62+
/// <summary>Reads a <see cref="long"/> from the address in the remote process.</summary>
63+
/// <param name="address">The address to read from.</param>
64+
/// <returns>The data read as <see cref="long"/> or 0 if the read fails.</returns>
65+
long ReadRemoteInt64(IntPtr address);
66+
67+
/// <summary>Reads a <see cref="ulong"/> from the address in the remote process.</summary>
68+
/// <param name="address">The address to read from.</param>
69+
/// <returns>The data read as <see cref="ulong"/> or 0 if the read fails.</returns>
70+
ulong ReadRemoteUInt64(IntPtr address);
71+
72+
/// <summary>Reads a <see cref="float"/> from the address in the remote process.</summary>
73+
/// <param name="address">The address to read from.</param>
74+
/// <returns>The data read as <see cref="float"/> or 0 if the read fails.</returns>
75+
float ReadRemoteFloat(IntPtr address);
76+
77+
/// <summary>Reads a <see cref="double"/> from the address in the remote process.</summary>
78+
/// <param name="address">The address to read from.</param>
79+
/// <returns>The data read as <see cref="double"/> or 0 if the read fails.</returns>
80+
double ReadRemoteDouble(IntPtr address);
81+
82+
/// <summary>Reads a <see cref="IntPtr"/> from the address in the remote process.</summary>
83+
/// <param name="address">The address to read from.</param>
84+
/// <returns>The data read as <see cref="IntPtr"/> or 0 if the read fails.</returns>
85+
IntPtr ReadRemoteIntPtr(IntPtr address);
86+
87+
/// <summary>Reads a string from the address in the remote process with the given length using the provided encoding.</summary>
88+
/// <param name="encoding">The encoding used by the string.</param>
89+
/// <param name="address">The address of the string.</param>
90+
/// <param name="length">The length of the string.</param>
91+
/// <returns>The string.</returns>
92+
string ReadRemoteString(Encoding encoding, IntPtr address, int length);
93+
94+
/// <summary>Reads a string from the address in the remote process with the given length and encoding. The string gets truncated at the first zero character.</summary>
95+
/// <param name="encoding">The encoding used by the string.</param>
96+
/// <param name="address">The address of the string.</param>
97+
/// <param name="length">The maximum length of the string.</param>
98+
/// <returns>The string.</returns>
99+
string ReadRemoteStringUntilFirstNullCharacter(Encoding encoding, IntPtr address, int length);
100+
101+
/// <summary>Reads remote runtime type information for the given address from the remote process.</summary>
102+
/// <param name="address">The address.</param>
103+
/// <returns>A string containing the runtime type information or null if no information could get found.</returns>
104+
string ReadRemoteRuntimeTypeInformation(IntPtr address);
105+
}
106+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
using System;
2+
3+
namespace ReClassNET.Memory
4+
{
5+
public interface IRemoteMemoryWriter
6+
{
7+
/// <summary>Writes the given <paramref name="data"/> to the <paramref name="address"/> in the remote process.</summary>
8+
/// <param name="address">The address to write to.</param>
9+
/// <param name="data">The data to write.</param>
10+
/// <returns>True if it succeeds, false if it fails.</returns>
11+
bool WriteRemoteMemory(IntPtr address, byte[] data);
12+
13+
/// <summary>Writes the given <paramref name="value"/> to the <paramref name="address"/> in the remote process.</summary>
14+
/// <typeparam name="T">Type of the value to write.</typeparam>
15+
/// <param name="address">The address to write to.</param>
16+
/// <param name="value">The value to write.</param>
17+
/// <returns>True if it succeeds, false if it fails.</returns>
18+
bool WriteRemoteMemory<T>(IntPtr address, T value) where T : struct;
19+
}
20+
}

0 commit comments

Comments
 (0)