Repository navigation
Expand file tree
/
Copy pathPatternScanner.cs
More file actions
122 lines (110 loc) · 4.33 KB
/
Copy pathPatternScanner.cs
File metadata and controls
122 lines (110 loc) · 4.33 KB
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
using System;
using System.Collections.Concurrent;
using System.Linq;
using ProcessNET.Memory;
using ProcessNET.Modules;
using ProcessNET.Utilities;
namespace ProcessNET.Patterns
{
public class PatternScanner : IPatternScanner
{
private class CachedPatternScanResult
{
public int Offset { get; set; }
public string ModuleName { get; set; }
}
static ConcurrentDictionary<string, CachedPatternScanResult> cache = null;
private readonly IProcessModule _module;
private readonly IProcess _process;
public byte[] Data { get; }
public PatternScanner(IProcess process, IProcessModule module)
{
this._process = process;
_module = module;
Data = module.Read(0, _module.Size);
}
static PatternScanner()
{
cache = new ConcurrentDictionary<string, CachedPatternScanResult>();
}
public PatternScanResult Find(IMemoryPattern pattern, bool useCache = true)
{
if(useCache && cache.TryGetValue(GetPatternCacheKey(pattern), out CachedPatternScanResult cachedResult))
{
return new PatternScanResult()
{
BaseAddress = _module.BaseAddress + cachedResult.Offset,
ReadAddress = _module.BaseAddress + cachedResult.Offset,
Offset = cachedResult.Offset,
Found = true,
};
}
return pattern.PatternType == MemoryPatternType.Function
? FindFunctionPattern(pattern)
: FindDataPattern(pattern);
}
private int GetOffset(IMemoryPattern pattern)
{
switch (pattern.Algorithm)
{
case PatternScannerAlgorithm.Naive:
return StringSearching.Naive.GetIndexOf(pattern, Data, _module, pattern.SearchStartOffset);
case PatternScannerAlgorithm.BoyerMooreHorspool:
return StringSearching.BoyerMooreHorspool.IndexOf(Data, pattern.GetBytes().ToArray(), pattern.SearchStartOffset);
default:
throw new NotImplementedException($"Unknown search algorithm, please implement it, {pattern.Algorithm}.");
}
}
private PatternScanResult FindFunctionPattern(IMemoryPattern pattern)
{
int offset = GetOffset(pattern);
if (offset < 0)
return PatternScanResult.NotFound;
PatternScanResult result = new PatternScanResult
{
BaseAddress = _module.BaseAddress + offset,
ReadAddress = _module.BaseAddress + offset,
Offset = offset,
Found = true
};
CachePatternScanResult(pattern, result);
return result;
}
private PatternScanResult FindDataPattern(IMemoryPattern pattern)
{
int offset = GetOffset(pattern);
if (offset < 0)
return PatternScanResult.NotFound;
var result = new PatternScanResult();
// If this area is reached, the pattern has been found.
result.Found = true;
result.ReadAddress = _module.Read<IntPtr>(offset);
result.BaseAddress = new IntPtr(result.ReadAddress.ToInt64() - _module.BaseAddress.ToInt64());
result.Offset = offset;
CachePatternScanResult(pattern, result);
return result;
}
private string GetPatternCacheKey(IMemoryPattern pattern)
{
return $"{pattern.ToString()}_{_module.Name}_{_module.Path}_{pattern.SearchStartOffset}";
}
private void CachePatternScanResult(IMemoryPattern pattern, PatternScanResult result)
{
if (!result.Found)
return;
string key = GetPatternCacheKey(pattern);
CachedPatternScanResult cachedPatternScanResult = new CachedPatternScanResult()
{
ModuleName = _module.Name,
Offset = result.Offset,
};
cache.AddOrUpdate(key, oldKey =>
{
return cachedPatternScanResult;
}, (oldKey, oldValue) =>
{
return cachedPatternScanResult;
});
}
}
}