Skip to content

Simple good performance byte pattern/PE signature scanner, allowing upwards of 5000MB/s per core (30000+MB/s with AVX) on modern hardware.

License

Notifications You must be signed in to change notification settings

Reloaded-Project/Reloaded.Memory.SigScan

Repository files navigation

Project Reloaded: Signature Scanning



It's fast enough. I think...

Coverage NuGet Build Status

Introduction

Reloaded.Memory.SigScan, is a pattern matching library for scanning byte signatures.

Signature scanning is often used in malware analysis (AV Software) and game hacking.
Usually both of those are the domain of native C/C++ code and at the time of writing this library, there existed very little on the managed .NET front that focuses on performance.

Reloaded.Memory.SigScan is biased towards ease of use and most importantly speed, achieving a staggering > 5GB/s on a in non-vectorised searches and over 30GB/s on vectorised searches on a single thread.

Usage

Patterns are specified as hex values, without prefix and delimited by spaces.
?? represents a wildcard, i.e. any byte can be present in the place of the wildcard.

Search the code of the current process:

// `FindPattern` will automatically use the most 
// efficient scanning method available on the current machine.  
var thisProcess = Process.GetCurrentProcess();
var scanner     = new Scanner(thisProcess, thisProcess.MainModule);
int offset      = scanner.FindPattern("04 25 12 ?? ?? E5 E3");

Search an offset in a byte array:

var scanner     = new Scanner(data);
int offset      = scanner.FindPattern("02 11 25 AB");

Scan for multiple signatures (multithreaded)

var scanner = new Scanner(data);
var multiplePatterns = new string[]
{
    "7A BB",
    "9F AB",
    "7A BB"
};

// Note: Use FindPatternsCached if your list of 
// patterns might contain duplicates.
var results = scanner.FindPatterns(multiplePatterns);

Reference Benchmarks

All benchmarks were performed on a machine running:

  • Core i7 4790k (4.4GHz OC)
  • DDR3 1866MHz RAM (CL9 timings)
  • .NET 5 Runtime

The provided "Speed" column is an effective measure of pattern matching speed in MB/s.

  • NumItems: Number of signatures scanned.
  • ST: Single Threaded. (baseline reference)
  • MT: Multi Threaded.
  • LB: Load Balancing On.
  • Compiled: Non-Vectorized implementation.

Implementation Comparison

Scanning a small data (3MiB) with known signature at end of data.

|   Method |       Mean |    Error |   StdDev | Ratio | RatioSD | Speed (MB/s) |
|--------- |-----------:|---------:|---------:|------:|--------:|------------- |
|      Avx |   232.4 us |  2.76 us |  2.58 us |  0.32 |    0.00 |     13535.33 |
|      Sse |   284.7 us |  2.17 us |  2.03 us |  0.40 |    0.00 |     11049.62 |
| Compiled |   715.7 us |  5.68 us |  5.03 us |  1.00 |    0.00 |      4395.52 |
|   Simple | 3,098.3 us | 36.51 us | 34.15 us |  4.33 |    0.05 |      1015.31 |

Small Data

Scanning a small data (3MiB) with random pre-selected 12 byte signatures.

|         Method | NumItems | Speed (MB/s) |
|--------------- |--------- |------------- |
|      Random_ST |        1 |     13618.03 |
| Random_MT_NoLB |        4 |     26394.96 |
|   Random_MT_LB |        4 |     26326.17 |
|   Random_MT_LB |       16 |     46032.68 |
| Random_MT_NoLB |       16 |     50459.84 |
|   Random_MT_LB |       64 |     56748.39 |
| Random_MT_NoLB |       64 |     57970.04 |
|   Random_MT_LB |      256 |     63418.04 |
| Random_MT_NoLB |      256 |     63746.84 |

Big Data

Scanning a random big data (200MiB) with random pre-selected 12 byte signatures.

|             Method | NumItems | Speed (MB/s) |
|------------------- |--------- |------------- |
| Random_ST_Compiled |        1 |     10308.65 |
|          Random_ST |        1 |     30025.36 |
|     Random_MT_NoLB |        4 |     44669.77 |
|       Random_MT_LB |        4 |     44572.28 |
|       Random_MT_LB |       16 |     60354.57 |
|     Random_MT_NoLB |       16 |     64928.73 |
|       Random_MT_LB |       64 |     59824.99 |
|     Random_MT_NoLB |       64 |     60502.48 |
|     Random_MT_NoLB |      256 |     55931.01 |
|       Random_MT_LB |      256 |     56763.69 |

Speed loss in cases of >16 items suggests increased cache misses.
Might be worth investigating in a future version.

Other Benchmarks

For other benchmarks, please see the Reloaded.Memory.Sigscan.Benchmark project in this repository.

To run the benchmarks yourself, simply run Reloaded.Memory.Sigscan.Benchmark after compiling in Release mode.

Reloaded.Memory.Sigscan.Benchmark is powered by BenchmarkDotNet.

Reloaded-II Shared Library

See Reloaded-II SigScan Shared Library.

Acknowledgements

Vectorised implementations of Reloaded.Memory.Sigscan are based off of a modified version of LazySIMD by uberhalit.