Skip to content

Commit 303a0e5

Browse files
committed
1.2.3
1 parent d475bf5 commit 303a0e5

3 files changed

Lines changed: 96 additions & 10 deletions

File tree

MemoryEditLib2/IPatternFinder.cs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,12 @@ namespace MemoryEditLib2
44
{
55
public interface IPatternFinder
66
{
7-
IntPtr GetAddressForString(string text, Encoding encoding, int minAddr = 0);
7+
IntPtr GetAddressForString(string text, Encoding encoding, ulong minAddr = 0, ulong maxAddr = 0);
88
List<IntPtr> GetAddressesForString(string text, Encoding encoding, int minAddr = 0);
99
IntPtr GetAddressForStringInModule(string moduleName, string text, Encoding encoding, long maxBufferSize = -1, long offsetAddress = 0);
10-
IntPtr GetAddressForPattern(string pattern, int minAddr = 0);
11-
unsafe IntPtr GetAddressForPattern(byte[] pattern, int minAddr = 0);
10+
IntPtr GetAddressForPattern(string pattern, ulong minAddr = 0, ulong maxAddr = 0);
11+
unsafe IntPtr GetAddressForPatternWithWildcards(string pattern, ulong minAddr = 0);
12+
unsafe IntPtr GetAddressForPattern(byte[] pattern, ulong minAddr = 0, ulong maxAddr = 0);
1213
IntPtr GetAddressForPatternInModule(string moduleName, string pattern, long maxBufferSize = -1, long offsetAddress = 0);
1314
IntPtr GetAddressForPatternInModule(string moduleName, byte[] pattern, long maxBufferSize = -1, long offsetAddress = 0);
1415
IntPtr GetAddressForPatternInModuleWithWildcards(string moduleName, string pattern, long maxBufferSize = -1, long offsetAddress = 0);

MemoryEditLib2/MemoryEditLib2.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
<Authors>LEaN</Authors>
1010
<Description>Read, Pattern Search, Edit Process Memory</Description>
1111
<Copyright>LEaN</Copyright>
12-
<Version>1.2.2</Version>
12+
<Version>1.2.3</Version>
1313
<RepositoryUrl>https://github.com/leanleon93/MemoryEditLib2</RepositoryUrl>
1414
<RepositoryType>git</RepositoryType>
1515
<NeutralLanguage>en</NeutralLanguage>

MemoryEditLib2/Windows/WindowsPatternFinder.cs

Lines changed: 91 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,9 @@ public class WindowsPatternFinder(MemoryEditorConfig config) : IPatternFinder
99
{
1010
private const int MEM_COMMIT = 0x00001000;
1111
private const int PAGE_READWRITE = 0x04;
12+
private const int PAGE_EXECUTE_READ = 0x20;
13+
private const int PAGE_READONLY = 0x02;
14+
private const int PAGE_EXECUTE_READWRITE = 0x40;
1215

1316
private IntPtr _processHandle { get; } = config.ProcessHandle;
1417
private Process _process { get; } = config.Process;
@@ -73,12 +76,12 @@ unsafe public List<IntPtr> GetAddressesForPattern(byte[] pattern, int minAddr =
7376
return returnVal;
7477
}
7578

76-
public IntPtr GetAddressForPattern(string pattern, int minAddr = 0)
79+
public IntPtr GetAddressForPattern(string pattern, ulong minAddr = 0, ulong maxAddr = 0)
7780
{
78-
return GetAddressForPattern(DataConverter.HexStringToByteArray(pattern), minAddr);
81+
return GetAddressForPattern(DataConverter.HexStringToByteArray(pattern), minAddr, maxAddr);
7982
}
8083

81-
unsafe public IntPtr GetAddressForPattern(byte[] pattern, int minAddr = 0)
84+
unsafe public IntPtr GetAddressForPattern(byte[] pattern, ulong minAddr = 0, ulong maxAddr = 0)
8285
{
8386
var handle = _processHandle;
8487
SYSTEM_INFO sys_info = new SYSTEM_INFO();
@@ -97,10 +100,12 @@ unsafe public IntPtr GetAddressForPattern(byte[] pattern, int minAddr = 0)
97100

98101
while (proc_min_address_l < proc_max_address_l)
99102
{
103+
if (_process.HasExited)
104+
throw new InvalidOperationException("Process has exited.");
100105
// 28 = sizeof(MEMORY_BASIC_INFORMATION)
101106
Kernel32Wrapper.VirtualQueryEx(handle, proc_min_address, out mem_basic_info, (uint)sizeof(MEMORY_BASIC_INFORMATION));
102107

103-
if (mem_basic_info.BaseAddress.ToInt64() > minAddr)
108+
if (mem_basic_info.BaseAddress.ToInt64() > (long)minAddr && (maxAddr <= 0 || mem_basic_info.BaseAddress.ToInt64() <= (long)maxAddr))
104109
{
105110

106111
// if this memory chunk is accessible
@@ -124,6 +129,8 @@ unsafe public IntPtr GetAddressForPattern(byte[] pattern, int minAddr = 0)
124129
// move to the next memory chunk
125130
proc_min_address_l += mem_basic_info.RegionSize.ToInt64();
126131
proc_min_address = new IntPtr(proc_min_address_l);
132+
if (mem_basic_info.BaseAddress == 0 && mem_basic_info.RegionSize == 0)
133+
throw new InvalidOperationException("Process invalid.");
127134
}
128135

129136
return IntPtr.Zero;
@@ -153,10 +160,10 @@ public nint GetAddressForPatternInModule(string moduleName, byte[] pattern, long
153160
return IntPtr.Zero;
154161
}
155162

156-
public IntPtr GetAddressForString(string text, Encoding encoding, int minAddr = 0)
163+
public IntPtr GetAddressForString(string text, Encoding encoding, ulong minAddr = 0, ulong maxAddr = 0)
157164
{
158165
var asBytes = encoding.GetBytes(text);
159-
return GetAddressForPattern(asBytes, minAddr);
166+
return GetAddressForPattern(asBytes, minAddr, maxAddr);
160167
}
161168

162169
public List<IntPtr> GetAddressesForString(string text, Encoding encoding, int minAddr = 0)
@@ -216,6 +223,84 @@ private static List<int> SearchPatternMulti(byte[] src, byte[] pattern)
216223
return returnData;
217224
}
218225

226+
unsafe public nint GetAddressForPatternWithWildcards(string pattern, ulong minAddr = 0)
227+
{
228+
byte[] convertedByteArray = ConvertPattern(pattern);
229+
var handle = _processHandle;
230+
SYSTEM_INFO sys_info = new SYSTEM_INFO();
231+
Kernel32Wrapper.GetSystemInfo(out sys_info);
232+
233+
IntPtr proc_min_address = sys_info.minimumApplicationAddress;
234+
IntPtr proc_max_address = sys_info.maximumApplicationAddress;
235+
236+
// saving the values as long ints so I won't have to do a lot of casts later
237+
long proc_min_address_l = (long)proc_min_address;
238+
long proc_max_address_l = (long)proc_max_address;
239+
240+
241+
MEMORY_BASIC_INFORMATION mem_basic_info = new MEMORY_BASIC_INFORMATION();
242+
IntPtr bytesRead = IntPtr.Zero; // number of bytes read with ReadProcessMemory
243+
244+
while (proc_min_address_l < proc_max_address_l)
245+
{
246+
if (_process.HasExited)
247+
throw new InvalidOperationException("Process has exited.");
248+
// 28 = sizeof(MEMORY_BASIC_INFORMATION)
249+
Kernel32Wrapper.VirtualQueryEx(handle, proc_min_address, out mem_basic_info, (uint)sizeof(MEMORY_BASIC_INFORMATION));
250+
251+
if (mem_basic_info.BaseAddress.ToInt64() > (long)minAddr)
252+
{
253+
254+
// if this memory chunk is accessible
255+
if ((mem_basic_info.Protect == PAGE_READWRITE ||
256+
mem_basic_info.Protect == PAGE_EXECUTE_READ ||
257+
mem_basic_info.Protect == PAGE_READONLY ||
258+
mem_basic_info.Protect == PAGE_EXECUTE_READWRITE)
259+
&& mem_basic_info.State == MEM_COMMIT)
260+
{
261+
byte[] buffer = new byte[mem_basic_info.RegionSize.ToInt64()];
262+
263+
// read everything in the buffer above
264+
Kernel32Wrapper.ReadProcessMemory(handle, mem_basic_info.BaseAddress, buffer, buffer.Length, out bytesRead);
265+
if (bytesRead.ToInt64() > 0)
266+
{
267+
var ret = SearchPatternWithWildcards(buffer, convertedByteArray);
268+
if (ret > -1)
269+
{
270+
return new IntPtr(mem_basic_info.BaseAddress.ToInt64() + (nint)ret);
271+
}
272+
}
273+
}
274+
}
275+
// move to the next memory chunk
276+
proc_min_address_l += mem_basic_info.RegionSize.ToInt64();
277+
proc_min_address = new IntPtr(proc_min_address_l);
278+
if (mem_basic_info.BaseAddress == 0 && mem_basic_info.RegionSize == 0)
279+
throw new InvalidOperationException("Process invalid.");
280+
}
281+
282+
return IntPtr.Zero;
283+
}
284+
285+
private static int SearchPatternWithWildcards(byte[] src, byte[] pattern)
286+
{
287+
int c = src.Length - pattern.Length + 1;
288+
int j;
289+
for (int i = 0; i < c; i++)
290+
{
291+
if (pattern[0] != 0x00 && src[i] != pattern[0])
292+
continue;
293+
for (j = pattern.Length - 1; j >= 1; j--)
294+
{
295+
if (pattern[j] != 0x00 && src[i + j] != pattern[j])
296+
break;
297+
}
298+
if (j == 0)
299+
return i;
300+
}
301+
return -1;
302+
}
303+
219304
public IntPtr GetAddressForPatternInModuleWithWildcards(string moduleName, string pattern, long maxBufferSize = -1, long offsetAddress = 0)
220305
{
221306
byte[] convertedByteArray = ConvertPattern(pattern);

0 commit comments

Comments
 (0)