mirror of
https://github.com/huiyadanli/RevokeMsgPatcher.git
synced 2025-07-08 16:49:03 +08:00
[+] 完成核心代码的编写
This commit is contained in:
parent
92594da959
commit
4ec0fb4f85
|
@ -1,4 +1,5 @@
|
||||||
using RevokeMsgPatcher.Utils;
|
using RevokeMsgPatcher.Modifier;
|
||||||
|
using RevokeMsgPatcher.Utils;
|
||||||
using System;
|
using System;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
|
@ -9,18 +10,12 @@ namespace RevokeMsgPatcher
|
||||||
{
|
{
|
||||||
public partial class FormMain : Form
|
public partial class FormMain : Form
|
||||||
{
|
{
|
||||||
Patcher patcher = null;
|
WechatModifier wechatModifier = new WechatModifier();
|
||||||
|
|
||||||
public FormMain()
|
public FormMain()
|
||||||
{
|
{
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
patcher = new Patcher();
|
|
||||||
txtPath.Text = Util.AutoFindInstallPath();
|
|
||||||
if (!string.IsNullOrEmpty(txtPath.Text))
|
|
||||||
{
|
|
||||||
patcher.IntallPath = txtPath.Text;
|
|
||||||
btnRestore.Enabled = File.Exists(patcher.BakPath);
|
|
||||||
}
|
|
||||||
// 标题加上版本号
|
// 标题加上版本号
|
||||||
string currentVersion = System.Reflection.Assembly.GetExecutingAssembly().GetName().Version.ToString();
|
string currentVersion = System.Reflection.Assembly.GetExecutingAssembly().GetName().Version.ToString();
|
||||||
if (currentVersion.Length > 3)
|
if (currentVersion.Length > 3)
|
||||||
|
@ -28,44 +23,41 @@ namespace RevokeMsgPatcher
|
||||||
currentVersion = " v" + currentVersion.Substring(0, 3);
|
currentVersion = " v" + currentVersion.Substring(0, 3);
|
||||||
}
|
}
|
||||||
this.Text += currentVersion;
|
this.Text += currentVersion;
|
||||||
|
|
||||||
|
// 自动获取应用安装路径
|
||||||
|
txtPath.Text = wechatModifier.FindInstallPath();
|
||||||
|
// 显示是否能够备份还原
|
||||||
|
if (!string.IsNullOrEmpty(txtPath.Text))
|
||||||
|
{
|
||||||
|
wechatModifier.InitEditors(txtPath.Text);
|
||||||
|
btnRestore.Enabled = wechatModifier.BackupExists();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void btnPatch_Click(object sender, EventArgs e)
|
private void btnPatch_Click(object sender, EventArgs e)
|
||||||
{
|
{
|
||||||
if (string.IsNullOrEmpty(txtPath.Text) || !Util.IsWechatInstallPath(txtPath.Text))
|
if (string.IsNullOrEmpty(txtPath.Text) || !wechatModifier.IsAllFilesExist(txtPath.Text))
|
||||||
{
|
{
|
||||||
MessageBox.Show("请选择微信安装路径!");
|
MessageBox.Show("请选择微信安装路径!");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
patcher.IntallPath = txtPath.Text;
|
// a.重新初始化编辑器
|
||||||
|
wechatModifier.InitEditors(txtPath.Text);
|
||||||
|
btnPatch.Enabled = false;
|
||||||
|
// b.计算SHA1,验证文件完整性,寻找对应的补丁信息
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
btnPatch.Enabled = false;
|
wechatModifier.ValidateAndFindModifyInfo();
|
||||||
string version = patcher.JudgeVersion();
|
}
|
||||||
if (!string.IsNullOrEmpty(version))
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
if (version == "done")
|
MessageBox.Show(ex.Message);
|
||||||
{
|
}
|
||||||
MessageBox.Show("已经安装过防撤回补丁了");
|
// c.打补丁
|
||||||
btnPatch.Enabled = true;
|
try
|
||||||
return;
|
{
|
||||||
}
|
wechatModifier.Patch();
|
||||||
|
|
||||||
if (patcher.Patch())
|
|
||||||
{
|
|
||||||
MessageBox.Show("成功安装防撤回补丁!原 WeChatWin.dll 文件已经备份到 " + patcher.BakPath + " ,如果有问题可以手动覆盖恢复");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
MessageBox.Show("防撤回补丁安装失败!");
|
|
||||||
}
|
|
||||||
btnRestore.Enabled = File.Exists(patcher.BakPath);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
MessageBox.Show("当前微信版本不被支持:" + Util.GetFileVersion(patcher.DllPath));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
|
@ -79,8 +71,8 @@ namespace RevokeMsgPatcher
|
||||||
{
|
{
|
||||||
if (!string.IsNullOrEmpty(txtPath.Text))
|
if (!string.IsNullOrEmpty(txtPath.Text))
|
||||||
{
|
{
|
||||||
patcher.IntallPath = txtPath.Text;
|
wechatModifier.InitEditors(txtPath.Text);
|
||||||
btnRestore.Enabled = File.Exists(patcher.BakPath);
|
btnRestore.Enabled = wechatModifier.BackupExists();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -90,7 +82,7 @@ namespace RevokeMsgPatcher
|
||||||
dialog.Description = "请选择微信安装路径";
|
dialog.Description = "请选择微信安装路径";
|
||||||
if (dialog.ShowDialog() == DialogResult.OK)
|
if (dialog.ShowDialog() == DialogResult.OK)
|
||||||
{
|
{
|
||||||
if (string.IsNullOrEmpty(dialog.SelectedPath) || !Util.IsWechatInstallPath(dialog.SelectedPath))
|
if (string.IsNullOrEmpty(dialog.SelectedPath) || !wechatModifier.IsAllFilesExist(dialog.SelectedPath))
|
||||||
{
|
{
|
||||||
MessageBox.Show("无法找到微信关键文件,请选择正确的微信安装路径!");
|
MessageBox.Show("无法找到微信关键文件,请选择正确的微信安装路径!");
|
||||||
}
|
}
|
||||||
|
@ -106,22 +98,14 @@ namespace RevokeMsgPatcher
|
||||||
btnRestore.Enabled = false;
|
btnRestore.Enabled = false;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (File.Exists(patcher.BakPath))
|
wechatModifier.Restore();
|
||||||
{
|
|
||||||
File.Copy(patcher.BakPath, patcher.DllPath, true);
|
|
||||||
MessageBox.Show("还原成功");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
MessageBox.Show("备份文件不存在");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Console.WriteLine(ex.Message);
|
Console.WriteLine(ex.Message);
|
||||||
MessageBox.Show(ex.Message);
|
MessageBox.Show(ex.Message);
|
||||||
}
|
}
|
||||||
btnRestore.Enabled = File.Exists(patcher.BakPath);
|
btnRestore.Enabled = wechatModifier.BackupExists();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void linkLabel1_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
|
private void linkLabel1_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
|
||||||
|
@ -144,7 +128,7 @@ namespace RevokeMsgPatcher
|
||||||
|
|
||||||
} else
|
} else
|
||||||
{
|
{
|
||||||
patcher.SetNewPatchJson(json);
|
//patcher.SetNewPatchJson(json);
|
||||||
lblUpdatePachJson.Text = "获取成功";
|
lblUpdatePachJson.Text = "获取成功";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -153,10 +137,10 @@ namespace RevokeMsgPatcher
|
||||||
private void lblUpdatePachJson_Click(object sender, EventArgs e)
|
private void lblUpdatePachJson_Click(object sender, EventArgs e)
|
||||||
{
|
{
|
||||||
string versions = "";
|
string versions = "";
|
||||||
patcher.TargetFiles.ForEach(t =>
|
//patcher.TargetFiles.ForEach(t =>
|
||||||
{
|
//{
|
||||||
versions += t.Version + Environment.NewLine;
|
// versions += t.Version + Environment.NewLine;
|
||||||
});
|
//});
|
||||||
MessageBox.Show("当前所支持的微信版本:" + Environment.NewLine + versions);
|
MessageBox.Show("当前所支持的微信版本:" + Environment.NewLine + versions);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -10,8 +10,8 @@ namespace RevokeMsgPatcher.Model
|
||||||
{
|
{
|
||||||
public string Name { get; set; }
|
public string Name { get; set; }
|
||||||
|
|
||||||
public string[] ModifyFilePaths { get; set; }
|
public Dictionary<string, TargetInfo> FileTargetInfos { get; set; }
|
||||||
|
|
||||||
public List<BinaryFile> ModifyFileInfos { get; set; }
|
public Dictionary<string, List<ModifyInfo>> FileModifyInfos { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,24 +0,0 @@
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.IO;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace RevokeMsgPatcher.Model
|
|
||||||
{
|
|
||||||
public class BinaryFile
|
|
||||||
{
|
|
||||||
//public string Name { get {return Path.GetFileName(RelativePath); } }
|
|
||||||
|
|
||||||
public string RelativePath { get; set; }
|
|
||||||
|
|
||||||
public string Version { get; set; }
|
|
||||||
|
|
||||||
public string SHA1Before { get; set; }
|
|
||||||
|
|
||||||
public string SHA1After { get; set; }
|
|
||||||
|
|
||||||
public List<Change> Changes { get; set; }
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -10,6 +10,14 @@ namespace RevokeMsgPatcher.Model
|
||||||
{
|
{
|
||||||
public long Position { get; set; }
|
public long Position { get; set; }
|
||||||
|
|
||||||
public byte Content { get; set; }
|
public byte[] Content { get; set; }
|
||||||
|
|
||||||
|
public Change Clone()
|
||||||
|
{
|
||||||
|
Change o = new Change();
|
||||||
|
o.Position = Position;
|
||||||
|
o.Content = Content;
|
||||||
|
return o;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
40
RevokeMsgPatcher/Model/ModifyInfo.cs
Normal file
40
RevokeMsgPatcher/Model/ModifyInfo.cs
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace RevokeMsgPatcher.Model
|
||||||
|
{
|
||||||
|
public class ModifyInfo
|
||||||
|
{
|
||||||
|
public string Name { get; set; }
|
||||||
|
|
||||||
|
//public string RelativePath { get; set; }
|
||||||
|
|
||||||
|
public string Version { get; set; }
|
||||||
|
|
||||||
|
public string SHA1Before { get; set; }
|
||||||
|
|
||||||
|
public string SHA1After { get; set; }
|
||||||
|
|
||||||
|
public List<Change> Changes { get; set; }
|
||||||
|
|
||||||
|
public ModifyInfo Clone()
|
||||||
|
{
|
||||||
|
ModifyInfo o = new ModifyInfo();
|
||||||
|
o.Name = Name;
|
||||||
|
o.Version = Version;
|
||||||
|
o.SHA1Before = SHA1Before;
|
||||||
|
o.SHA1After = SHA1After;
|
||||||
|
List<Change> cs = new List<Change>();
|
||||||
|
foreach(Change c in Changes)
|
||||||
|
{
|
||||||
|
cs.Add(c.Clone());
|
||||||
|
}
|
||||||
|
o.Changes = cs;
|
||||||
|
return o;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
26
RevokeMsgPatcher/Model/TargetInfo.cs
Normal file
26
RevokeMsgPatcher/Model/TargetInfo.cs
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace RevokeMsgPatcher.Model
|
||||||
|
{
|
||||||
|
public class TargetInfo
|
||||||
|
{
|
||||||
|
public string Name { get; set; }
|
||||||
|
|
||||||
|
public string RelativePath { get; set; }
|
||||||
|
|
||||||
|
public string Memo { get; set; }
|
||||||
|
|
||||||
|
public TargetInfo Clone()
|
||||||
|
{
|
||||||
|
TargetInfo o = new TargetInfo();
|
||||||
|
o.Name = Name;
|
||||||
|
o.RelativePath = RelativePath;
|
||||||
|
o.Memo = Memo;
|
||||||
|
return o;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -10,6 +10,6 @@ namespace RevokeMsgPatcher.Model
|
||||||
{
|
{
|
||||||
public string AppVersion { get; set; }
|
public string AppVersion { get; set; }
|
||||||
|
|
||||||
public List<BinaryFile> Files { get; set; }
|
public List<ModifyInfo> Files { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,41 +8,52 @@ using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace RevokeMsgPatcher.Modifier
|
namespace RevokeMsgPatcher.Modifier
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 1. 自动获取安装目录(已验证) 或者手动填写安装目录
|
||||||
|
/// 2. 验证安装目录 验证要修改的 dll 是否存在
|
||||||
|
/// 3. 判断所有 dll 是否符合防撤回要求
|
||||||
|
/// 4. 备份所有 dll // *.h.bak
|
||||||
|
/// 5. 根据每个 dll 匹配的 修改信息 循环修改
|
||||||
|
/// </summary>
|
||||||
public abstract class AppModifier
|
public abstract class AppModifier
|
||||||
{
|
{
|
||||||
private App config;
|
protected App config;
|
||||||
|
|
||||||
private List<FileHexEditor> editors;
|
protected List<FileHexEditor> editors;
|
||||||
|
|
||||||
// 1. 获取安装目录
|
public string InstallPath { get; set; }
|
||||||
// 2. 验证安装目录 通过 BinaryFiles
|
|
||||||
// 3. 判断所有 BinaryFiles 是否符合防撤回要求
|
|
||||||
// 4. 备份所有 BinaryFiles // *.h.bak
|
|
||||||
// 5. 对每个 BinaryFile 中的 Changes 循环修改(修改前要测试它的读写性质,是否被程序占用等)
|
|
||||||
|
|
||||||
// 获取版本号
|
|
||||||
// 通过SHA1判断是否可以进行16进制编辑 先判断版本号 再判断SHA1 根据不同结果返回不同的提示
|
|
||||||
|
|
||||||
// ?多文件的备份回退 // 暂定有一个备份文件就点亮按钮
|
|
||||||
|
|
||||||
public abstract string FindInstallPath();
|
public abstract string FindInstallPath();
|
||||||
|
|
||||||
//public abstract bool ValidateInstallPath();
|
//public abstract bool ValidateAndInitialize(string installPath);
|
||||||
|
|
||||||
public abstract bool GetVersion();
|
/// <summary>
|
||||||
|
/// 获取版本号
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
public abstract string GetVersion();
|
||||||
|
|
||||||
public bool IsAllBinaryFilesExist(string installPath)
|
/// <summary>
|
||||||
|
/// 判断APP安装路径内是否都存在要修改的文件
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="installPath">APP安装路径</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public bool IsAllFilesExist(string installPath)
|
||||||
{
|
{
|
||||||
int success = 0;
|
if(string.IsNullOrEmpty(installPath))
|
||||||
foreach(string relativePath in config.ModifyFilePaths)
|
|
||||||
{
|
{
|
||||||
string filePath = Path.Combine(installPath, relativePath);
|
return false;
|
||||||
if(File.Exists(filePath))
|
}
|
||||||
|
int success = 0;
|
||||||
|
foreach (TargetInfo info in config.FileTargetInfos.Values)
|
||||||
|
{
|
||||||
|
string filePath = Path.Combine(installPath, info.RelativePath);
|
||||||
|
if (File.Exists(filePath))
|
||||||
{
|
{
|
||||||
success++;
|
success++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(success == config.ModifyFilePaths.Length)
|
if (success == config.FileTargetInfos.Count)
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -52,5 +63,132 @@ namespace RevokeMsgPatcher.Modifier
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// a.初始化修改器
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="installPath">APP安装路径</param>
|
||||||
|
public void InitEditors(string installPath)
|
||||||
|
{
|
||||||
|
// 初始化文件修改器
|
||||||
|
editors = new List<FileHexEditor>();
|
||||||
|
foreach (TargetInfo info in config.FileTargetInfos.Values)
|
||||||
|
{
|
||||||
|
FileHexEditor editor = new FileHexEditor(installPath, info);
|
||||||
|
editors.Add(editor);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// b.验证文件完整性,寻找对应的补丁信息
|
||||||
|
/// </summary>
|
||||||
|
public void ValidateAndFindModifyInfo()
|
||||||
|
{
|
||||||
|
// 寻找对应文件版本与SHA1的修改信息
|
||||||
|
foreach (FileHexEditor editor in editors) // 多种文件
|
||||||
|
{
|
||||||
|
// 通过SHA1和文件版本判断是否可以打补丁 根据不同结果返回不同的提示
|
||||||
|
ModifyInfo matchingSHA1Before = null, matchingSHA1After = null, matchingVersion = null;
|
||||||
|
foreach (ModifyInfo modifyInfo in config.FileModifyInfos[editor.FileName]) // 多个版本信息
|
||||||
|
{
|
||||||
|
if (modifyInfo.Name == editor.FileName) // 保险用的无用判断
|
||||||
|
{
|
||||||
|
if (editor.FileSHA1 == modifyInfo.SHA1After)
|
||||||
|
{
|
||||||
|
matchingSHA1After = modifyInfo;
|
||||||
|
}
|
||||||
|
else if (editor.FileSHA1 == modifyInfo.SHA1Before)
|
||||||
|
{
|
||||||
|
matchingSHA1Before = modifyInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (editor.FileVersion == modifyInfo.Version)
|
||||||
|
{
|
||||||
|
matchingVersion = modifyInfo;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 补丁前SHA1匹配上,肯定是正确的dll
|
||||||
|
if (matchingSHA1Before != null)
|
||||||
|
{
|
||||||
|
editor.FileModifyInfo = modifyInfo.Clone();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// 补丁后SHA1匹配上,肯定已经打过补丁
|
||||||
|
if (matchingSHA1After != null)
|
||||||
|
{
|
||||||
|
throw new Exception($"你已经安装过此补丁,文件路径:{editor.FilePath}");
|
||||||
|
}
|
||||||
|
// 全部不匹配,说明不支持
|
||||||
|
if (matchingSHA1Before == null && matchingSHA1After == null && matchingVersion == null)
|
||||||
|
{
|
||||||
|
throw new Exception($"不支持此版本:{editor.FileVersion},文件路径:{editor.FilePath}");
|
||||||
|
}
|
||||||
|
// SHA1不匹配,版本匹配,可能dll已经被其他补丁程序修改过
|
||||||
|
if ((matchingSHA1Before == null && matchingSHA1After == null) && matchingVersion != null)
|
||||||
|
{
|
||||||
|
throw new Exception($"程序支持此版本:{editor.FileVersion}。但是文件校验不通过,请确认是否使用过其他补丁程序。文件路径:{editor.FilePath}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// c.根据补丁信息,安装补丁
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
public bool Patch()
|
||||||
|
{
|
||||||
|
// 首先验证文件修改器是否没问题
|
||||||
|
foreach (FileHexEditor editor in editors)
|
||||||
|
{
|
||||||
|
if (editor.FileModifyInfo == null)
|
||||||
|
{
|
||||||
|
throw new Exception("补丁安装失败,原因:文件修改器初始化失败!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 再备份所有文件
|
||||||
|
foreach (FileHexEditor editor in editors)
|
||||||
|
{
|
||||||
|
editor.Backup();
|
||||||
|
}
|
||||||
|
// 打补丁!
|
||||||
|
foreach (FileHexEditor editor in editors)
|
||||||
|
{
|
||||||
|
bool success = editor.Patch();
|
||||||
|
if (!success)
|
||||||
|
{
|
||||||
|
editor.Restore();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool BackupExists()
|
||||||
|
{
|
||||||
|
foreach (FileHexEditor editor in editors)
|
||||||
|
{
|
||||||
|
if(!File.Exists(editor.FileBakPath))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Restore()
|
||||||
|
{
|
||||||
|
if (BackupExists())
|
||||||
|
{
|
||||||
|
foreach (FileHexEditor editor in editors)
|
||||||
|
{
|
||||||
|
editor.Restore();
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw new Exception("备份文件不存在,还原失败!");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,8 @@
|
||||||
using System;
|
using RevokeMsgPatcher.Model;
|
||||||
|
using RevokeMsgPatcher.Utils;
|
||||||
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
@ -8,5 +11,63 @@ namespace RevokeMsgPatcher.Modifier
|
||||||
{
|
{
|
||||||
public class FileHexEditor
|
public class FileHexEditor
|
||||||
{
|
{
|
||||||
|
public string FileName { get; set; }
|
||||||
|
|
||||||
|
public string FilePath { get; set; }
|
||||||
|
|
||||||
|
public string FileBakPath { get; set; }
|
||||||
|
|
||||||
|
private string version;
|
||||||
|
public string FileVersion
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (version == null)
|
||||||
|
{
|
||||||
|
version = FileUtil.GetFileVersion(FilePath);
|
||||||
|
}
|
||||||
|
return version;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public string sha1;
|
||||||
|
public string FileSHA1
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (sha1 == null)
|
||||||
|
{
|
||||||
|
sha1 = FileUtil.ComputeFileSHA1(FilePath);
|
||||||
|
}
|
||||||
|
return sha1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public TargetInfo FileTargetInfo { get; set; }
|
||||||
|
|
||||||
|
public ModifyInfo FileModifyInfo { get; set; }
|
||||||
|
|
||||||
|
public FileHexEditor(string installPath, TargetInfo target)
|
||||||
|
{
|
||||||
|
FileTargetInfo = target.Clone();
|
||||||
|
FileName = FileTargetInfo.Name;
|
||||||
|
FilePath = Path.Combine(installPath, FileTargetInfo.RelativePath);
|
||||||
|
FileBakPath = FilePath + ".h.bak";
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Backup()
|
||||||
|
{
|
||||||
|
File.Copy(FilePath, FileBakPath, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Patch()
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Restore()
|
||||||
|
{
|
||||||
|
File.Copy(FileBakPath, FilePath, true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,14 +9,18 @@ namespace RevokeMsgPatcher.Modifier
|
||||||
{
|
{
|
||||||
class WechatModifier : AppModifier
|
class WechatModifier : AppModifier
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 自动寻找获取微信安装路径
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
public override string FindInstallPath()
|
public override string FindInstallPath()
|
||||||
{
|
{
|
||||||
string installPath = PathUtil.FindInstallPathFromRegistry("Wecaht");
|
string installPath = PathUtil.FindInstallPathFromRegistry("Wechat");
|
||||||
if(!IsAllBinaryFilesExist(installPath))
|
if (!IsAllFilesExist(installPath))
|
||||||
{
|
{
|
||||||
foreach(string defaultPath in PathUtil.GetDefaultInstallPaths(@"Tencent\Wechat"))
|
foreach (string defaultPath in PathUtil.GetDefaultInstallPaths(@"Tencent\Wechat"))
|
||||||
{
|
{
|
||||||
if(IsAllBinaryFilesExist(defaultPath))
|
if (IsAllFilesExist(defaultPath))
|
||||||
{
|
{
|
||||||
return defaultPath;
|
return defaultPath;
|
||||||
}
|
}
|
||||||
|
@ -29,9 +33,38 @@ namespace RevokeMsgPatcher.Modifier
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override bool GetVersion()
|
/// <summary>
|
||||||
|
/// 获取整个APP的当前版本
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
public override string GetVersion()
|
||||||
{
|
{
|
||||||
throw new NotImplementedException();
|
if (editors != null && editors.Count > 0)
|
||||||
|
{
|
||||||
|
foreach (FileHexEditor editor in editors)
|
||||||
|
{
|
||||||
|
if (editor.FileName == "WeChatWin.dll")
|
||||||
|
{
|
||||||
|
return editor.FileVersion;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//public override bool ValidateAndInitialize(string installPath)
|
||||||
|
//{
|
||||||
|
// // 判断是否是安装路径
|
||||||
|
// if (!IsAllBinaryFilesExist(installPath))
|
||||||
|
// {
|
||||||
|
// return false;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// // 初始化十六进制文件编辑器
|
||||||
|
// // 并寻找与之配对的版本修改信息
|
||||||
|
// InitEditors(installPath);
|
||||||
|
|
||||||
|
// return true;
|
||||||
|
//}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,14 +14,18 @@ namespace RevokeMsgPatcher
|
||||||
[STAThread]
|
[STAThread]
|
||||||
static void Main()
|
static void Main()
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
||||||
|
#if DEBUG
|
||||||
|
Application.EnableVisualStyles();
|
||||||
|
Application.SetCompatibleTextRenderingDefault(false);
|
||||||
|
Application.Run(new FormMain());
|
||||||
|
#else
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
Application.EnableVisualStyles();
|
Application.EnableVisualStyles();
|
||||||
Application.SetCompatibleTextRenderingDefault(false);
|
Application.SetCompatibleTextRenderingDefault(false);
|
||||||
|
|
||||||
#if DEBUG
|
|
||||||
Application.Run(new FormMain());
|
|
||||||
#else
|
|
||||||
//当前用户是管理员的时候,直接启动应用程序
|
//当前用户是管理员的时候,直接启动应用程序
|
||||||
//如果不是管理员,则使用启动对象启动程序,以确保使用管理员身份运行
|
//如果不是管理员,则使用启动对象启动程序,以确保使用管理员身份运行
|
||||||
//获得当前登录的Windows用户标示
|
//获得当前登录的Windows用户标示
|
||||||
|
@ -53,12 +57,13 @@ namespace RevokeMsgPatcher
|
||||||
//退出
|
//退出
|
||||||
Application.Exit();
|
Application.Exit();
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
MessageBox.Show(ex.Message, "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
|
MessageBox.Show(ex.Message, "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -57,8 +57,9 @@
|
||||||
</Compile>
|
</Compile>
|
||||||
<Compile Include="Model\App.cs" />
|
<Compile Include="Model\App.cs" />
|
||||||
<Compile Include="Model\Change.cs" />
|
<Compile Include="Model\Change.cs" />
|
||||||
<Compile Include="Model\BinaryFile.cs" />
|
<Compile Include="Model\ModifyInfo.cs" />
|
||||||
<Compile Include="Model\TargetFile.cs" />
|
<Compile Include="Model\TargetFile.cs" />
|
||||||
|
<Compile Include="Model\TargetInfo.cs" />
|
||||||
<Compile Include="Model\Version.cs" />
|
<Compile Include="Model\Version.cs" />
|
||||||
<Compile Include="Modifier\AppModifier.cs" />
|
<Compile Include="Modifier\AppModifier.cs" />
|
||||||
<Compile Include="Modifier\FileHexEditor.cs" />
|
<Compile Include="Modifier\FileHexEditor.cs" />
|
||||||
|
@ -66,6 +67,7 @@
|
||||||
<Compile Include="Modifier\TIMModifier.cs" />
|
<Compile Include="Modifier\TIMModifier.cs" />
|
||||||
<Compile Include="Modifier\WechatModifier.cs" />
|
<Compile Include="Modifier\WechatModifier.cs" />
|
||||||
<Compile Include="Patcher.cs" />
|
<Compile Include="Patcher.cs" />
|
||||||
|
<Compile Include="Utils\FileUtil.cs" />
|
||||||
<Compile Include="Utils\PathUtil.cs" />
|
<Compile Include="Utils\PathUtil.cs" />
|
||||||
<Compile Include="Program.cs" />
|
<Compile Include="Program.cs" />
|
||||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||||
|
|
59
RevokeMsgPatcher/Utils/FileUtil.cs
Normal file
59
RevokeMsgPatcher/Utils/FileUtil.cs
Normal file
|
@ -0,0 +1,59 @@
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.IO;
|
||||||
|
using System.Security.Cryptography;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace RevokeMsgPatcher.Utils
|
||||||
|
{
|
||||||
|
public class FileUtil
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 获取文件版本
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="path"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static string GetFileVersion(string path)
|
||||||
|
{
|
||||||
|
FileVersionInfo fileVersionInfo = FileVersionInfo.GetVersionInfo(path);
|
||||||
|
return fileVersionInfo.FileVersion;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 计算文件SHA1
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="s">文件路径</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static string ComputeFileSHA1(string s)
|
||||||
|
{
|
||||||
|
FileStream file = new FileStream(s, FileMode.Open);
|
||||||
|
SHA1 sha1 = new SHA1CryptoServiceProvider();
|
||||||
|
byte[] retval = sha1.ComputeHash(file);
|
||||||
|
file.Close();
|
||||||
|
|
||||||
|
StringBuilder sc = new StringBuilder();
|
||||||
|
for (int i = 0; i < retval.Length; i++)
|
||||||
|
{
|
||||||
|
sc.Append(retval[i].ToString("x2"));
|
||||||
|
}
|
||||||
|
return sc.ToString();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 修改文件指定位置的字节
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="path">WeChatWin.dll 的路径</param>
|
||||||
|
/// <param name="position">偏移位置</param>
|
||||||
|
/// <param name="after">修改后的值</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static bool EditHex(string path, long position, byte after)
|
||||||
|
{
|
||||||
|
using (var stream = new FileStream(path, FileMode.Open, FileAccess.ReadWrite))
|
||||||
|
{
|
||||||
|
stream.Position = position;
|
||||||
|
stream.WriteByte(after);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user