[+] 完成基于特征码的防撤回查找替换功能

This commit is contained in:
huiyadanli
2020-01-01 18:32:54 +08:00
parent 604f84b0f6
commit 88f6ae7417
7 changed files with 182 additions and 19 deletions
+41 -7
View File
@@ -1,4 +1,5 @@
using RevokeMsgPatcher.Model;
using RevokeMsgPatcher.Model.Enum;
using System;
using System.Collections.Generic;
using System.Drawing;
@@ -166,6 +167,30 @@ namespace RevokeMsgPatcher.Modifier
return false;
}
/// <summary>
/// 文件修改器是否已经有对应的特征码修改替换信息
/// </summary>
/// <returns></returns>
public bool EditorsHasCommonModifyInfos()
{
int i = 0;
for (i = 0; i < editors.Count; i++) // 多种文件
{
if (editors[i].FileCommonModifyInfo == null)
{
break;
}
}
if (i == editors.Count)
{
return true;
}
else
{
return false;
}
}
/// <summary>
/// a.初始化修改器
/// </summary>
@@ -235,34 +260,40 @@ namespace RevokeMsgPatcher.Modifier
// 补丁后SHA1匹配上,肯定已经打过补丁
if (matchingSHA1After != null)
{
throw new BusinessException("installed", $"你已经安装过此补丁,文件路径:{editor.FilePath}");
throw new BusinessException("installed", $"你已经安装过此补丁");
}
// 全部不匹配,说明不支持
if (matchingSHA1Before == null && matchingSHA1After == null && matchingVersion == null)
{
throw new BusinessException("not_support", $"不支持此版本:{editor.FileVersion},文件路径:{editor.FilePath}");
throw new BusinessException("not_support", $"不支持此版本:{editor.FileVersion}");
}
// SHA1不匹配,版本匹配,可能dll已经被其他补丁程序修改过
if ((matchingSHA1Before == null && matchingSHA1After == null) && matchingVersion != null)
{
throw new BusinessException("maybe_modified", $"程序支持此版本:{editor.FileVersion}。但是文件校验不通过,请确认是否使用过其他补丁程序。文件路径:{editor.FilePath}");
throw new BusinessException("maybe_modified", $"程序支持此版本:{editor.FileVersion}。但是文件校验不通过,请确认是否使用过其他补丁程序");
}
}
}
/// <summary>
/// c.根据补丁信息,安装补丁
/// 两种打补丁的方式:精准(指定位置替换)、通用(特征码替换)
/// </summary>
/// <param name="type">两种打补丁的方式:精准(指定位置替换)、通用(特征码替换)</param>
/// <returns></returns>
public bool Patch()
public bool Patch(PatchType type = PatchType.Accurate)
{
// 首先验证文件修改器是否没问题
foreach (FileHexEditor editor in editors)
{
if (editor.FileModifyInfo == null)
if (type == PatchType.Accurate && editor.FileModifyInfo == null)
{
throw new Exception("补丁安装失败,原因:文件修改器初始化失败!");
}
if (type == PatchType.Common && editor.FileCommonModifyInfo == null)
{
throw new Exception("补丁安装失败,原因:特征码修改器初始化失败!");
}
}
// 再备份所有文件
foreach (FileHexEditor editor in editors)
@@ -275,12 +306,15 @@ namespace RevokeMsgPatcher.Modifier
{
foreach (FileHexEditor editor in editors)
{
bool success = editor.Patch();
bool success = editor.Patch(type);
if (!success)
{
editor.Restore();
}
done.Add(editor);
else
{
done.Add(editor);
}
}
}
catch (Exception ex)
+84 -6
View File
@@ -1,4 +1,6 @@
using RevokeMsgPatcher.Model;
using RevokeMsgPatcher.Matcher;
using RevokeMsgPatcher.Model;
using RevokeMsgPatcher.Model.Enum;
using RevokeMsgPatcher.Utils;
using System;
using System.Collections.Generic;
@@ -53,7 +55,7 @@ namespace RevokeMsgPatcher.Modifier
public ModifyInfo FileModifyInfo { get; set; }
/// <summary>
/// 通过比对版本范围得到的通用查找替换的修改信息
/// 通过比对版本范围得到的通用查找替换的修改信息(特征码替换信息)
/// </summary>
public CommonModifyInfo FileCommonModifyInfo { get; set; }
@@ -76,14 +78,90 @@ namespace RevokeMsgPatcher.Modifier
/// <summary>
/// 打补丁
/// 优先使用特定的补丁信息(存在对应SHA1信息)
/// 不存在补丁信息,使用通用版本替换方法
/// </summary>
/// <param name="type">两种打补丁的方式:精准(指定位置替换)、通用(特征码替换)</param>
/// <returns></returns>
public bool Patch()
public bool Patch(PatchType type)
{
if (type == PatchType.Accurate)
{
AccuratePatch();
}
else
{
CommonPatch();
}
return true;
}
/// <summary>
/// 精准(指定位置替换)
/// </summary>
public void AccuratePatch()
{
FileUtil.EditMultiHex(FilePath, FileModifyInfo.Changes);
return true;
}
/// <summary>
/// 通用(特征码替换)
/// </summary>
public void CommonPatch()
{
if (FileCommonModifyInfo == null)
{
throw new Exception("特征码替换:缺失对应特征码信息");
}
// 1. 拷贝一份临时文件
File.Copy(FilePath, fileReplacedPath, true);
// 2. 读取整个临时文件
byte[] fileByteArray = File.ReadAllBytes(fileReplacedPath);
// 3. 循环查找所有未替换的替换点
int needReplaceNum = 0;
List<Change> changes = new List<Change>();
foreach (ReplacePattern pattern in FileCommonModifyInfo.ReplacePatterns)
{
int[] indexs = FuzzyMatcher.MatchNotReplaced(fileByteArray, pattern.Search, pattern.Replace);
if (indexs.Length == 1)
{
needReplaceNum++;
changes.Add(new Change(indexs[0], pattern.Replace));
}
}
// 判断是否可以使用特征码替换的方式
if (needReplaceNum == 0)
{
// 查找所有替换点
int matchNum = 0;
foreach (ReplacePattern pattern in FileCommonModifyInfo.ReplacePatterns)
{
int[] indexs = FuzzyMatcher.MatchAll(fileByteArray, pattern.Search);
if (indexs.Length == 1)
{
matchNum++;
}
}
if (matchNum == FileCommonModifyInfo.ReplacePatterns.Count)
{
throw new Exception("特征码替换:当前应用已经防撤回");
}
else
{
throw new Exception("特征码替换:没有搜索到撤回的相关特征");
}
}
else if (needReplaceNum == FileCommonModifyInfo.ReplacePatterns.Count)
{
// 正常情况下每个替换点都能找到
// 3. 替换所有未替换的替换点
FileUtil.EditMultiHex(fileReplacedPath, changes);
// 4. 覆盖特征码替换后的文件
File.Copy(fileReplacedPath, FilePath, true);
}
else
{
throw new Exception("特征码替换:可替换的特征数不正确");
}
}
/// <summary>