From 88f6ae74171dca9e0f377111ee9f89bc2fcf850a Mon Sep 17 00:00:00 2001 From: huiyadanli Date: Wed, 1 Jan 2020 18:32:54 +0800 Subject: [PATCH] =?UTF-8?q?[+]=20=E5=AE=8C=E6=88=90=E5=9F=BA=E4=BA=8E?= =?UTF-8?q?=E7=89=B9=E5=BE=81=E7=A0=81=E7=9A=84=E9=98=B2=E6=92=A4=E5=9B=9E?= =?UTF-8?q?=E6=9F=A5=E6=89=BE=E6=9B=BF=E6=8D=A2=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- RevokeMsgPatcher.Assistant/FormAssisant.cs | 2 +- RevokeMsgPatcher/FormMain.cs | 31 ++++++-- RevokeMsgPatcher/Model/Change.cs | 11 +++ RevokeMsgPatcher/Model/Enum/PatchType.cs | 18 +++++ RevokeMsgPatcher/Modifier/AppModifier.cs | 48 ++++++++++-- RevokeMsgPatcher/Modifier/FileHexEditor.cs | 90 ++++++++++++++++++++-- RevokeMsgPatcher/RevokeMsgPatcher.csproj | 1 + 7 files changed, 182 insertions(+), 19 deletions(-) create mode 100644 RevokeMsgPatcher/Model/Enum/PatchType.cs diff --git a/RevokeMsgPatcher.Assistant/FormAssisant.cs b/RevokeMsgPatcher.Assistant/FormAssisant.cs index 1500aa1..238be3f 100644 --- a/RevokeMsgPatcher.Assistant/FormAssisant.cs +++ b/RevokeMsgPatcher.Assistant/FormAssisant.cs @@ -93,7 +93,7 @@ namespace RevokeMsgPatcher.Assistant if (changeOffsets.Count == 0) { - throw new Exception("查询串与替换串完全相同!请联系作者确认远端补丁信息的正确性。"); + throw new Exception("查询串与替换串完全相同!请确认补丁信息的正确性。"); } List changes = new List(); diff --git a/RevokeMsgPatcher/FormMain.cs b/RevokeMsgPatcher/FormMain.cs index 7e1aefe..f73a988 100644 --- a/RevokeMsgPatcher/FormMain.cs +++ b/RevokeMsgPatcher/FormMain.cs @@ -1,4 +1,5 @@ using RevokeMsgPatcher.Model; +using RevokeMsgPatcher.Model.Enum; using RevokeMsgPatcher.Modifier; using RevokeMsgPatcher.Utils; using System; @@ -95,18 +96,38 @@ namespace RevokeMsgPatcher ga.RequestPageView($"{enName}/{version}/patch", "点击防撤回"); EnableAllButton(false); + PatchType type = PatchType.Accurate; // 两种打补丁的方式:精准(指定位置替换)、通用(特征码替换) // a.重新初始化编辑器 modifier.InitEditors(txtPath.Text); - // b.计算SHA1,验证文件完整性,寻找对应的补丁信息 + // b.计算SHA1,验证文件完整性,寻找对应的补丁信息(精确版本、通用特征码两种补丁信息) try { modifier.ValidateAndFindModifyInfo(); } catch (BusinessException ex) { - ga.RequestPageView($"{enName}/{version}/patch/sha1/ex/{ex.ErrorCode}", ex.Message); - MessageBox.Show(ex.Message); - return; + if ((ex.ErrorCode == "not_support" || ex.ErrorCode == "maybe_modified") && modifier.EditorsHasCommonModifyInfos()) + { + // 存在特征码修改替换信息的情况下,发起一次询问 + DialogResult useCommonPatch = + MessageBox.Show("尝试使用精准匹配补丁程序时发生错误:【" + + ex.Message + "】,不过该版本支持使用特征码替换补丁程序,当前建议继续尝试防撤回!是否继续尝试防撤回?", + "是否使用特征码补丁", MessageBoxButtons.OKCancel, MessageBoxIcon.Question); + if (useCommonPatch == DialogResult.OK) + { + type = PatchType.Common; + } + else + { + return; + } + } + else + { + ga.RequestPageView($"{enName}/{version}/patch/sha1/ex/{ex.ErrorCode}", ex.Message); + MessageBox.Show(ex.Message); + return; + } } catch (IOException ex) { @@ -128,7 +149,7 @@ namespace RevokeMsgPatcher // c.打补丁 try { - modifier.Patch(); + modifier.Patch(type); ga.RequestPageView($"{enName}/{version}/patch/succ", "防撤回成功"); MessageBox.Show("补丁安装成功!"); } diff --git a/RevokeMsgPatcher/Model/Change.cs b/RevokeMsgPatcher/Model/Change.cs index df3c99f..369e3ec 100644 --- a/RevokeMsgPatcher/Model/Change.cs +++ b/RevokeMsgPatcher/Model/Change.cs @@ -12,6 +12,17 @@ namespace RevokeMsgPatcher.Model public byte[] Content { get; set; } + public Change() + { + + } + + public Change(long position, byte[] content) + { + Position = position; + Content = content; + } + public Change Clone() { Change o = new Change(); diff --git a/RevokeMsgPatcher/Model/Enum/PatchType.cs b/RevokeMsgPatcher/Model/Enum/PatchType.cs new file mode 100644 index 0000000..4b9a211 --- /dev/null +++ b/RevokeMsgPatcher/Model/Enum/PatchType.cs @@ -0,0 +1,18 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace RevokeMsgPatcher.Model.Enum +{ + /// + /// 两种打补丁的方式 + /// 精准(指定位置替换)、通用(特征码替换) + /// + public enum PatchType + { + Accurate, // 精准(指定位置替换) + Common // 通用(特征码替换) + } +} diff --git a/RevokeMsgPatcher/Modifier/AppModifier.cs b/RevokeMsgPatcher/Modifier/AppModifier.cs index f84126b..0ed9f1b 100644 --- a/RevokeMsgPatcher/Modifier/AppModifier.cs +++ b/RevokeMsgPatcher/Modifier/AppModifier.cs @@ -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; } + /// + /// 文件修改器是否已经有对应的特征码修改替换信息 + /// + /// + 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; + } + } + /// /// a.初始化修改器 /// @@ -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}。但是文件校验不通过,请确认是否使用过其他补丁程序!"); } } } /// /// c.根据补丁信息,安装补丁 + /// 两种打补丁的方式:精准(指定位置替换)、通用(特征码替换) /// + /// 两种打补丁的方式:精准(指定位置替换)、通用(特征码替换) /// - 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) diff --git a/RevokeMsgPatcher/Modifier/FileHexEditor.cs b/RevokeMsgPatcher/Modifier/FileHexEditor.cs index 6973970..ad8a857 100644 --- a/RevokeMsgPatcher/Modifier/FileHexEditor.cs +++ b/RevokeMsgPatcher/Modifier/FileHexEditor.cs @@ -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; } /// - /// 通过比对版本范围得到的通用查找替换的修改信息 + /// 通过比对版本范围得到的通用查找替换的修改信息(特征码替换信息) /// public CommonModifyInfo FileCommonModifyInfo { get; set; } @@ -76,14 +78,90 @@ namespace RevokeMsgPatcher.Modifier /// /// 打补丁 - /// 优先使用特定的补丁信息(存在对应SHA1信息) - /// 不存在补丁信息,使用通用版本替换方法 /// + /// 两种打补丁的方式:精准(指定位置替换)、通用(特征码替换) /// - public bool Patch() + public bool Patch(PatchType type) + { + if (type == PatchType.Accurate) + { + AccuratePatch(); + + } + else + { + CommonPatch(); + } + return true; + } + + /// + /// 精准(指定位置替换) + /// + public void AccuratePatch() { FileUtil.EditMultiHex(FilePath, FileModifyInfo.Changes); - return true; + } + + /// + /// 通用(特征码替换) + /// + 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 changes = new List(); + 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("特征码替换:可替换的特征数不正确"); + } } /// diff --git a/RevokeMsgPatcher/RevokeMsgPatcher.csproj b/RevokeMsgPatcher/RevokeMsgPatcher.csproj index 078272a..e8b911c 100644 --- a/RevokeMsgPatcher/RevokeMsgPatcher.csproj +++ b/RevokeMsgPatcher/RevokeMsgPatcher.csproj @@ -63,6 +63,7 @@ +