前言

Harmony是适用于.NET和Mono的通用非破坏性破解程序库。

Harmony使用简单,文档齐全,兼容性强,实为破解注入外挂之首选。

官网:https://harmony.pardeike.net/

GitHub:https://github.com/pardeike/Harmony

1,快速开始

用visual studio新建一个console项目,Nuget安装Lib.Harmony,代码如下:

namespace _01_玩一玩Harmony
{
class Program
{
//Harmony 是适用于 .NET 和 Mono 模块的通用的非破坏性破解程序库
//Nuget安装Lib.Harmony
static void Main(string[] args)
{
int result = 0; //Patch前-----
SomeGameClass someGameClass = new SomeGameClass();
result = someGameClass.DoSomething(); //DoSomething 0
result = someGameClass.DoSomething(); //DoSomething 0 //Patch后-----
MyPatcher.DoPatching();
result = someGameClass.DoSomething(); //DoSomething 10
Console.WriteLine($"result {result}"); //result 20
result = someGameClass.DoSomething(); //DoSomething 20
Console.WriteLine($"result {result}"); //result 40
result = someGameClass.DoSomething(); //DoSomething 30
Console.WriteLine($"result {result}"); //result 60
result = someGameClass.DoSomething(); //不执行
Console.WriteLine($"result {result}"); //result 0
Console.ReadKey();
}
} //原始代码
public class SomeGameClass
{
private bool isRunning;
private int counter; public int DoSomething()
{
if (isRunning)
{
counter++;
}
Console.WriteLine($"DoSomething {counter * 10}");
return counter * 10;
}
} public class MyPatcher
{
// 调用DoPatching方法Patch才会生效
public static void DoPatching()
{
var harmony = new Harmony("com.example.patch");
harmony.PatchAll();
}
} [HarmonyPatch(typeof(SomeGameClass))] //类
[HarmonyPatch("DoSomething")] //方法,防止写错尽量用nameof()
class Patch01
{
//获取类型成员
static FieldRef<SomeGameClass, bool> isRunningRef = FieldRefAccess<SomeGameClass, bool>("isRunning"); //Prefix返回一个bool,如果false,则不执行后续Prefix,不执行原始方法
[HarmonyPrefix]
static bool Prefix(SomeGameClass __instance, ref int ___counter)
{
isRunningRef(__instance) = true; //给成员变量isRunning赋值
if (___counter >= 3)
{
return false;
}
return true;
} //Postfix永远执行
[HarmonyPostfix]
static void Postfix(ref int __result) //__result表示DoSomething方法的返回值
{
__result *= 2;
}
}
}

1.1 SomeGameClass类

即将被Patch的代码,注意观察Patch前和Patch后执行DoSomething方法的变化。

1.2 Patch01类

指明了具体需要Patch的类,方法和具体行为。[HarmonyPatch(typeof(SomeGameClass))][HarmonyPatch("DoSomething")]表示要修改SomeGameClass类的DoSomething方法,isRunningRef用于访问SomeGameClass类的isRunning变量,[HarmonyPrefix]表示在执行DoSomething方法之前要执行的代码,[HarmonyPostfix]表示执行DoSomething方法之后要执行的代码。

1.3 MyPatcher类

仅仅用于启动Patch,即调用harmony.PatchAll(),使Patch01类生效,或者说使带[HarmonyPatchAttribute]的类都生效。

1.4 跑起来

执行和结果都写在Main方法里了,很直白。

2,破解

此处的破解指的是改变第三方dll的行为,典型场景是你做开发时引用第一个第三方dll,这个库会先给试用,之后就需要激活码或授权文件才能继续使用。判断是否激活的方法一般都存在于第三方dll中,只需要用Harmony修改激活方法就算破解了。

一般流程是先使用第三方dll,观察dll报需要激活时的信息,然后反编译dll找出与激活相关的代码,最后用Harmony改变这些代码行为。(部分情况下dll会做混淆加壳防止破解,混淆的话通过观察也基本能确定对应的代码,费点眼神就是了。加壳的话,要专门学习脱壳技术,我也不太会)

创建一个需要激活才能使用的类库项目。

创建一个调用此类库的winform项目。

2.1 类库项目

namespace ClassLibrary1
{
public class Class1
{
bool 已激活 = false;
MD5 md5 = MD5.Create();
public void 激活(string code)
{
if (!已激活)
{
if (Convert.ToBase64String(md5.ComputeHash(Encoding.UTF8.GetBytes(code))) == "ICy5YqxZB1uWSwcVLSNLcA==")
{
已激活 = true;
Console.WriteLine("激活成功!");
}
else
{
Console.WriteLine("激活失败!");
}
}
}
public void DomeSomething()
{
if (已激活)
{
Console.WriteLine("调用成功!");
}
else
{
Console.WriteLine("需要激活!");
}
}
}
}

很简单,需要调用激活方法,给对激活码才能成功调用。MD5保证了有密文也反推不了明文。

2.2 winform项目

namespace WindowsFormsApp1
{
//Nuget安装Lib.Harmony
public partial class Form1 : Form
{
Harmony harmony = new Harmony("com.example.patch");
Class1 class1 = new Class1();
public Form1()
{
InitializeComponent();
} private void 破解_Click(object sender, EventArgs e)
{
harmony.PatchAll();
class1.激活("任意字符");
} private void 调用_Click(object sender, EventArgs e)
{
class1.DomeSomething();
}
} [HarmonyPatch("ClassLibrary1.Class1", "激活")] //类,方法
class Patch01
{
//获取类型成员
static FieldRef<Class1, bool> 已激活Ref = FieldRefAccess<Class1, bool>("已激活"); //Prefix返回一个bool,如果false,则不执行后续Prefix,不执行原始方法
[HarmonyPrefix]
static bool Prefix(Class1 __instance)
{
已激活Ref(__instance) = true; //给成员变量已激活赋值
return false; //跳过原始方法
}
}
}

winform项目引用ClassLibrary1.dll,直接点击调用按钮会输出需要激活!,点击破解按钮之后,再点击调用按钮会输出调用成功!

3,注入

此处的注入指的是改变正在运行的应用程序的行为,典型场景就是使用C#写的工具或游戏,用着用着就要激活码,要收费。这种相较于破解要稍微麻烦一点,因为目标已经独立运行起来了,需要用到dll注入工具FastWin32。

一般流程是先使用应用程序,观察应用程序报需要激活时的信息,然后反编译应用程序找出与激活相关的代码,然后写一个类库项目用Harmony改变这些代码行为编译成dll,最后用FastWin32将dll注入给应用程序。

创建一个winform项目叫02_目标winform,即需要改变行为的应用程序。

创建一个类库项目02_注入用dll,使用Harmony改变应用程序的行为。

创建一个winform项目叫02_注入工具FastWin32,使用FastWin32将dll注入给应用程序。

3.1 目标winform

namespace _02_目标winform
{
public partial class 目标Form : Form
{
public 目标Form()
{
InitializeComponent();
} private void button1_Click(object sender, EventArgs e)
{
textBox1.Text = MakeMessage();
} private string MakeMessage()
{
return "我是Form1";
}
}
}

Form很简单就两个控件,一个TextBox,一个Button,MakeMessage方法就是我们要改变的目标。

3.2 注入用dll

namespace _02_注入用dll
{ public class MyPatcher
{
//注意!!FastWin32要求函数签名必须是static int MethodName(string)
public static int DoPatching(string msg)
{
var harmony = new Harmony("com.example.patch");
harmony.PatchAll();
return 1;
}
} [HarmonyPatch("_02_目标winform.目标Form", "MakeMessage")] //类,方法
class Patch01
{
//Prefix返回一个bool,如果false,则不执行后续Prefix,不执行原始方法
[HarmonyPrefix]
static bool Prefix(ref string __result) //__result表示MakeMessage方法的返回值
{
__result = "我是Harmony的Prefix";
return false;
} //Postfix永远执行
[HarmonyPostfix]
static void Postfix(ref string __result) //__result表示MakeMessage方法的返回值
{
__result = $"{__result} 我是Harmony的Postfix";
}
}
}

DoPatching方法有参数和返回值,只是为了满足FastWin32对函数的签名要求,没别的意义。其余部分一路看下来的应该很直白明了。

3.3 注入工具FastWin32

namespace _02_注入工具FastWin32
{
public partial class 注入工具Form : Form
{
public 注入工具Form()
{
InitializeComponent();
} private void button1_Click(object sender, EventArgs e)
{
//Nuget安装FastWin32
OpenFileDialog dialog = new OpenFileDialog();
dialog.InitialDirectory = AppDomain.CurrentDomain.BaseDirectory;
if (dialog.ShowDialog() == DialogResult.OK) //手动选择02_HarmonyTest\02_注入用dll\bin\Debug\02_注入用dll.dll
{
uint id = Convert.ToUInt32(textBox1.Text); //在任务管理器看02_目标winform.exe的PID,手动填上
Injector.InjectManaged(id, dialog.FileName, "_02_注入用dll.MyPatcher", "DoPatching", "", out int returnValue);
MessageBox.Show($"returnValue:{returnValue}");
}
}
}
}

Form很简单就两个控件,一个TextBox,一个Button,这块逻辑写的略微粗糙,先打开任务管理器,找到02_目标winform.exe的PID,填在TextBox里,然后点击按钮,选择3.2节中生成的02_注入用dll.dllInjector.InjectManaged方法就会在02_目标winform.exe的程序域中执行DoPatching方法,就搞定了。

3.4 跑起来

先运行02_目标winform.exe



然后在任务管理器找到PID。



然后运行02_注入工具FastWin32.exe,填上PID,选择好02_注入用dll.dll



再回到02_目标winform.exe,点击按钮,就会发生变化。

4,絮叨

使用Harmony的同期也尝试过别的方法,比如DotNetDetour,比如打开unsafe直接替换函数指针,但是效果都不好,远远不如Harmony。这才能说Harmony实为破解注入外挂之首选。

作者:tossorrow

出处:C#应用 - 破解注入外挂必备神器Harmony

转载:欢迎转载,请保留此段声明,请在文章中给出原文链接;

C#应用 - 破解注入外挂必备神器Harmony的更多相关文章

  1. sublime text3 --前端工程师必备神器

    sublime text3 --前端工程师必备神器 导读目录: 下载与Emmet插件安装 sublime text3 中cssrem安装与使用 sublime Text 3的中文文件名显示为方框的问题 ...

  2. 工欲善其事,必先利其器 软件工具开发关键词 protractor自动化测试工具 RegexBuddy正则 CodeSmith,LightSwitch:代码生成 CheatEngine:玩游戏修改内存值必备神器 ApkIDE:Android反编译工具 Reflector:反编译dll动态链接库

    工欲善其事,必先利其器 本文版权归翟士丹(Stan Zhai)和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文链接,否则保留追究法律责任的权利. 原文地址:http ...

  3. 考试必备神器-真题园手机客户端Android版1.1正式上线啦,欢迎大家下载使用!

    真题园-考试必备神器,爱学习,找真题! 真题园-考试必备神器,爱学习,找真题!1.真题园android客户端1.1版全新发布上线.2.最新教育资讯实时更新,了解行业动态新闻.3.最新最全的真题大全,最 ...

  4. Unity3D开发必备神器(Visual Studio Tools for Unity)

    Unity3D开发必备神器(Visual Studio Tools for Unity) 开发Unity3D程序你用的什么IDE呢? 1.MonoDevelop 2.VS 可能你的回答是这样的,我用的 ...

  5. 剑指Offer——求职必备神器

    剑指Offer--求职必备神器 前言   不管是公司网申.银行招聘.面试等等,"谈谈你的职业规划"."以往工作中遇到了哪些棘手问题?你是如何解决的?".&quo ...

  6. 2019,UI设计师必备神器

      2019年将会是你全新起航的一年,相信你已经制定了很多规划,正在开启第一步的推动. 作为对UI设计师更大程度的支持,今天特意为你分享一款释放你双手的设计神器.让你可以把时间和精力投入到设计本身,这 ...

  7. Sublime Text 2 - 性感无比的代码编辑器!程序员必备神器!

    Sublime Text 2 - 性感无比的代码编辑器!程序员必备神器! http://www.iplaysoft.com/sublimetext.html 代码编辑器或者文本编辑器,对于程序员来说, ...

  8. UML架构设计师必备神器

    UML-架构设计师必备神器 做过Java开发的一定都听过UML,也都能感觉到它的重要性.由其是在网上搜索一些高级技术介绍,写的好的.阅读量高的.让初.中级程序员容易看懂的.思路清晰的文章一定有UML类 ...

  9. 程序员必备神器(FastStoneCapture)

    工欲善其事,必先利其器. 作为程序员,如果我们不知道如何制作动态图或者快捷录屏.录视频等,会给人一种身怀不技的感觉:好!屁话少说,接下来我会废话连篇的介绍一款神器--------那就是FastSton ...

  10. 被女朋友三番五次拉黑后,我用 Python 写了个“舔狗”必备神器

    在一个阳光明媚的周日,我打开窗户呼吸了一口新鲜空气.阳光灿烂,岁月静好,又是一个约女朋友出去爬山吃饭看电影的好日子. 想到女朋友的大眼睛,我脸上不禁洋溢起了幸福的微笑.打开微信,给女朋友发出去一个美好 ...

随机推荐

  1. 含税168元起!四核A53+NPU+PCIe+USB3.0,瑞芯微RK3562性价比真高!

     

  2. NXP i.MX 8M Plus工业开发板规格书(四核ARM Cortex-A53 + 单核ARM Cortex-M7,主频1.6GHz)

      1 评估板简介 创龙科技TLIMX8MP-EVM是一款基于NXP i.MX 8M Plus的四核ARM Cortex-A53 + 单核ARM Cortex-M7异构多核处理器设计的高性能工业评估板 ...

  3. Win10 下安装使用easyocr图片识别工具

    [前言] 最近在做图像识别相关的工作,找到了一个名为EasyOCR的pythoh 库. 使用过程中出现了一些问题,现做简单记录. [正文] 1. 安装EasyOCR 我用了最简单的方法:pip3 in ...

  4. Docker的使用和常用命令

    部署项目前基础服务准备 第一步:安装Docker环境 第二步:开启Docker远程带证书访问(可选) 第三步:拉取mysql,redis,nginx等等所需镜像 第四步:运行(创建)容器 # 本地远程 ...

  5. 9. 嵌套的 CMake

    9. 嵌套的 CMake 如果项目很大,或者项目中有很多的源码目录,在通过 CMake 管理项目的时候如果只使用一个 CMakeLists.txt ,那么这个文件相对会比较复杂,有一种化繁为简的方式就 ...

  6. 内部网关协议OSPF

    开放最短路径优先OSPF,开放表明OSPF不受某一厂商控制,最短路径优先是因为使用了最短路径算法SPF. OSPF最主要的特征是使用链路状态协议,而不是RIP的距离向量路由协议.其余特点: ⑴使用洪泛 ...

  7. Apache Kyuubi 在小米大数据平台的应用实践

    导读:今天分享的主题是<Kyuubi 在小米大数据平台的应用实践>,主要分为四部分内容: Kyuubi 在小米的落地过程 打造易用和高可用的 Kyuubi 服务 基于 kyuubi 的改进 ...

  8. 解决php提示Maximum execution time of 30 seconds exceeded错误

    如何解决错误? 基本上,有3种方法可以处理此错误: 修改php配置文件php.ini文件 使用 ini_set() 函数 使用set_time_limit()函数 1)修改php配置文件php.ini ...

  9. MViTv2:Facebook出品,进一步优化的多尺度ViT | CVPR 2022

    论文将Multiscale Vision Transformers (MViTv2) 作为图像和视频分类以及对象检测的统一架构进行研究,结合分解的相对位置编码和残差池化连接提出了MViT的改进版本 来 ...

  10. Windows/Linux 安装NVM及npm配置

    nvm安装及npm配置 nvm nvm下载 Windows: Releases · coreybutler/nvm-windows (github.com) Windows直接下载相应版本的nvm-s ...