[+] 添加特征码识别替换的版本范围判定

This commit is contained in:
huiyadanli
2020-01-01 15:20:55 +08:00
parent 000dfa969e
commit 8630dc83df
6 changed files with 73 additions and 9 deletions

File diff suppressed because one or more lines are too long

View File

@@ -1,216 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace RevokeMsgPatcher.Assistant.Matcher
{
public class BoyerMooreMatcher
{
private static int AlphabetSize = 256;
private static int Max(int a, int b) { return (a > b) ? a : b; }
static int[] PreprocessToBuildBadCharactorHeuristic(byte[] pattern)
{
int m = pattern.Length;
int[] badCharactorShifts = new int[AlphabetSize];
for (int i = 0; i < AlphabetSize; i++)
{
//badCharactorShifts[i] = -1;
badCharactorShifts[i] = m;
}
// fill the actual value of last occurrence of a character
for (int i = 0; i < m; i++)
{
//badCharactorShifts[(int)pattern[i]] = i;
badCharactorShifts[(int)pattern[i]] = m - 1 - i;
}
return badCharactorShifts;
}
static int[] PreprocessToBuildGoodSuffixHeuristic(byte[] pattern)
{
int m = pattern.Length;
int[] goodSuffixShifts = new int[m];
int[] suffixLengthArray = GetSuffixLengthArray(pattern);
for (int i = 0; i < m; ++i)
{
goodSuffixShifts[i] = m;
}
int j = 0;
for (int i = m - 1; i >= -1; --i)
{
if (i == -1 || suffixLengthArray[i] == i + 1)
{
for (; j < m - 1 - i; ++j)
{
if (goodSuffixShifts[j] == m)
{
goodSuffixShifts[j] = m - 1 - i;
}
}
}
}
for (int i = 0; i < m - 1; ++i)
{
goodSuffixShifts[m - 1 - suffixLengthArray[i]] = m - 1 - i;
}
return goodSuffixShifts;
}
static int[] GetSuffixLengthArray(byte[] pattern)
{
int m = pattern.Length;
int[] suffixLengthArray = new int[m];
int f = 0, g = 0, i = 0;
suffixLengthArray[m - 1] = m;
g = m - 1;
for (i = m - 2; i >= 0; --i)
{
if (i > g && suffixLengthArray[i + m - 1 - f] < i - g)
{
suffixLengthArray[i] = suffixLengthArray[i + m - 1 - f];
}
else
{
if (i < g)
{
g = i;
}
f = i;
// find different preceded character suffix
while (g >= 0 && pattern[g] == pattern[g + m - 1 - f])
{
--g;
}
suffixLengthArray[i] = f - g;
}
}
return suffixLengthArray;
}
public static bool TryMatch(byte[] text, byte[] pattern, out int firstShift)
{
firstShift = -1;
int n = text.Length;
int m = pattern.Length;
int s = 0; // s is shift of the pattern with respect to text
int j = 0;
// fill the bad character and good suffix array by preprocessing
int[] badCharShifts = PreprocessToBuildBadCharactorHeuristic(pattern);
int[] goodSuffixShifts = PreprocessToBuildGoodSuffixHeuristic(pattern);
while (s <= (n - m))
{
// starts matching from the last character of the pattern
j = m - 1;
// keep reducing index j of pattern while characters of
// pattern and text are matching at this shift s
while (j >= 0 && pattern[j] == text[s + j])
{
j--;
}
// if the pattern is present at current shift, then index j
// will become -1 after the above loop
if (j < 0)
{
firstShift = s;
return true;
}
else
{
// shift the pattern so that the bad character in text
// aligns with the last occurrence of it in pattern. the
// max function is used to make sure that we get a positive
// shift. We may get a negative shift if the last occurrence
// of bad character in pattern is on the right side of the
// current character.
//s += Max(1, j - badCharShifts[(int)text[s + j]]);
// now, compare bad char shift and good suffix shift to find best
s += Max(goodSuffixShifts[j], badCharShifts[(int)text[s + j]] - (m - 1) + j);
}
}
return false;
}
public static int[] MatchAll(byte[] text, byte[] pattern)
{
int n = text.Length;
int m = pattern.Length;
int s = 0; // s is shift of the pattern with respect to text
int j = 0;
int[] shiftIndexes = new int[n - m + 1];
int c = 0;
// fill the bad character and good suffix array by preprocessing
int[] badCharShifts = PreprocessToBuildBadCharactorHeuristic(pattern);
int[] goodSuffixShifts = PreprocessToBuildGoodSuffixHeuristic(pattern);
while (s <= (n - m))
{
// starts matching from the last character of the pattern
j = m - 1;
// keep reducing index j of pattern while characters of
// pattern and text are matching at this shift s
while (j >= 0 && pattern[j] == text[s + j])
{
j--;
}
// if the pattern is present at current shift, then index j
// will become -1 after the above loop
if (j < 0)
{
shiftIndexes[c] = s;
c++;
// shift the pattern so that the next character in text
// aligns with the last occurrence of it in pattern.
// the condition s+m < n is necessary for the case when
// pattern occurs at the end of text
//s += (s + m < n) ? m - badCharShifts[(int)text[s + m]] : 1;
s += goodSuffixShifts[0];
}
else
{
// shift the pattern so that the bad character in text
// aligns with the last occurrence of it in pattern. the
// max function is used to make sure that we get a positive
// shift. We may get a negative shift if the last occurrence
// of bad character in pattern is on the right side of the
// current character.
//s += Max(1, j - badCharShifts[(int)text[s + j]]);
// now, compare bad char shift and good suffix shift to find best
s += Max(goodSuffixShifts[j], badCharShifts[(int)text[s + j]] - (m - 1) + j);
}
}
int[] shifts = new int[c];
for (int y = 0; y < c; y++)
{
shifts[y] = shiftIndexes[y];
}
return shifts;
}
}
}

View File

@@ -1,133 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
namespace RevokeMsgPatcher.Assistant.Matcher
{
/// <summary>
/// 对16进制数据进行通配符查找
/// </summary>
public class FuzzyMatcher
{
public const byte wildcard = 0x3F; // 通配符
/// <summary>
/// 通配符匹配所有符合查找串的位置
/// </summary>
/// <param name="content">被查找对象</param>
/// <param name="pattern">查找串</param>
/// <returns></returns>
public static int[] MatchAll(byte[] content, byte[] pattern)
{
byte[] head = GetHead(pattern);
int[] indexs = BoyerMooreMatcher.MatchAll(content, head);
// 头串和查找串相同则直接返回,不同则继续判断是否符合查询串
if (head.Length == pattern.Length)
{
return indexs;
}
else
{
List<int> res = new List<int>();
foreach (int index in indexs)
{
if (IsEqual(content, index, pattern))
{
res.Add(index);
}
}
return res.ToArray();
}
}
/// <summary>
/// 通配符匹配所有符合查找串的位置,并排除已经替换的情况
/// </summary>
/// <param name="content">被查找对象</param>
/// <param name="searchBytes">查找串</param>
/// <param name="replaceBytes">替换串</param>
/// <returns></returns>
public static int[] MatchNotReplaced(byte[] content, byte[] searchBytes, byte[] replaceBytes)
{
byte[] head = GetHead(searchBytes);
int[] indexs = BoyerMooreMatcher.MatchAll(content, head);
// 头串和查找串相同则直接返回,不同则继续判断是否符合查询串
List<int> res = new List<int>();
if (head.Length != searchBytes.Length)
{
foreach (int index in indexs)
{
if (IsEqual(content, index, searchBytes))
{
res.Add(index);
}
}
indexs = res.ToArray();
}
// 判断是否与替换串相同
res = new List<int>();
foreach (int index in indexs)
{
if (!IsEqual(content, index, replaceBytes))
{
res.Add(index);
}
}
return res.ToArray();
}
/// <summary>
/// 获取头串
/// </summary>
/// <param name="whole">完整查找串</param>
/// <returns></returns>
private static byte[] GetHead(byte[] whole)
{
int len = whole.Length;
for (int i = 0; i < whole.Length; i++)
{
if (whole[i] == wildcard)
{
len = i;
break;
}
}
if (len == 0)
{
throw new Exception("不正确的通配符位置!");
}
return whole.Take(len).ToArray();
}
/// <summary>
/// 确认整个查找串是否匹配
/// </summary>
/// <param name="content">被查找对象</param>
/// <param name="start">头串匹配位置</param>
/// <param name="whole">完整查找串</param>
/// <returns></returns>
private static bool IsEqual(byte[] content, int start, byte[] whole)
{
int i = 0;
for (i = 0; i < whole.Length; i++)
{
if (whole[i] == wildcard)
{
continue;
}
if (content[start + i] != whole[i])
{
break;
}
}
if (i == whole.Length)
{
return true;
}
else
{
return false;
}
}
}
}