目录
- 1 前言
- 1.1 可能带来的问题
- 2 ConfuserEx
- 2.1 简介
- 2.2 功能特点
- 2.3 基本使用方法
- 2.4 集成到MSBuild
- 2.5 深入设置
- 2.5.1 保护机制
- 2.5.1.1 ConfuserEx Protection
- 2.5.2 精细的代码保护
- 主要特性
- 1. `decl-type(string)`
- 2.`full-name(string)`
- 3. `is-public()`
- 4. `match(string)`
- 5. `match-name(string)`
- 6.`match-type-name(string)`
- 7. `member-type(string)`
- 8. `module(string)`
- 9. `name(string)`
- 10. `namespace(string)`
- 11. `inherits(string)`
- 12. `is-type(string)`
- 2.6 使用建议
1 前言
代码混淆是一种通过故意模糊代码逻辑、隐藏其本意的技术,旨在提高逆向工程的难度,从而实现以下目标:
- 延缓破解与篡改速度:通过复杂化代码结构,增加攻击者分析和修改代码的时间成本。
- 保护知识产权:防止敏感算法或商业逻辑被轻易窃取或复制。
常见的混淆技术包括:
- 名称混淆:缩短变量、函数名称,使其失去语义性。
- 字符串加密:对字符串内容进行加密,避免明文暴露关键信息。
- 控制流混淆:引入冗余逻辑或虚假分支,扰乱程序执行路径。
- 控制流扁平化:将线性逻辑转化为复杂的状态机结构。
- 不透明谓词:插入看似有意义但实际上不影响功能的条件判断。
- 指令替换:用等价但更复杂的指令替代原有操作。
代码混淆不仅能有效保护程序逻辑,还能通过移除冗余信息、缩短标识符等方式减小编译后程序体积,提升分发效率。其核心价值在于平衡功能等价性与可读性之间的矛盾,为软件安全提供基础保障。
1.1 可能带来的问题
- 调试和维护困难:混淆后的代码难以理解,调试和修复问题时通常需要依赖未混淆的原始代码,否则可能难以定位问题。
- 反射冲突:代码混淆可能与反射机制产生冲突,尤其在未正确配置保留规则时,可能导致运行时错误。
- 安全性限制:代码混淆无法完全阻止反向工程,仅能提高其门槛。对于高安全性需求的场景,建议结合加密、完整性校验等多重保护措施。
2 ConfuserEx
2.1 简介
ConfuserEx 是一个开源的 .NET 应用程序保护工具,用于防止反编译和篡改。它支持多种混淆技术,包括控制流混淆、字符串加密、资源加密等。其灵活的配置选项可以根据不同的需求进行定制,为开发者提供了强大的保护机制。
官网:https://mkaring.github.io/ConfuserEx/
文档:git clone https://github.com/mkaring/ConfuserEx.wiki.git
2.2 功能特点
- 代码混淆:通过重命名、控制流混淆等技术,使反编译后的代码难以理解。
- 字符串加密:对字符串进行加密,防止攻击者轻易获取敏感信息。
- 完整性校验:确保应用程序在运行过程中没有被篡改。
- 反反编译:防止反编译工具对应用程序进行反编译。
- 插件系统:允许开发者根据自己的需求编写自定义混淆规则,增强工具的灵活性和扩展性。
2.3 基本使用方法
-
下载安装 ConfuserExGUI
https://github.com/mkaring/ConfuserEx/releases
-
ConfuserExGUI界面
-
将待混淆的 .dll 或 .exe 文件拖拽进中间方框区域。
他会自动带出基本路径和输出路径
4. 设置 .NET 运行时.NET Core, .NET Standard, .NET 5 Support · Issue #302 · mkaring/ConfuserEx
ConfuserExGUI默认支支持.NET FrameWork,如果需要使用.NET Core版本,需要手动设置运行时。
-
点击【⚙️】选择对应版本的运行时。
-
点击【+】选择运行时文件夹
-
-
选择 Settings 项,添加混淆规则。
-
点击【Protect!】按钮开始混淆。
-
点击【Save Project】保存混淆项目
这将保存一个crproj文件。内容示例,可以看到其包含输出路径,基本路径,模块以及模块对应的规则。
<project outputDir="E:\File\WorkFile\ConfuserExTest\ConfuserDemo\ConfuserDemo\bin\Debug\net5.0-windows\Confused" baseDir="E:\File\WorkFile\ConfuserExTest\ConfuserDemo\ConfuserDemo\bin\Debug\net5.0-windows" xmlns="http://confuser.codeplex.com"> <module path="ConfuserDllDemo.dll"> inherit="false"> <protection id="rename"> <argument name="mode" value="reversible" /> <argument name="generatePassword" value="true" /> protection> </rule> </module> <module path="ConfuserDemo.dll" /> <module path="ConfuserDllDemo2.dll"> inherit="false"> <protection id="constants" /> <protection id="ctrl flow" /> <protection id="rename"> <argument name="mode" value="reversible" /> <argument name="generatePassword" value="true" /> protection> </rule> </module> <probePath>C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App\5.0.17</probePath> <probePath>C:\Program Files\dotnet\shared\Microsoft.NETCore.App\5.0.17</probePath> <probePath>C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App\5.0.17</probePath> </project>
2.4 集成到MSBuild
ConfuserEx提供了ConfuserEx.CIL.exe工具,可以运行ConfuserEx.CIL.exe执行代码混淆。所以可以通过csproj配置MSBuild事件或者通过bat脚本执行ConfuserEx.CIL.exe工具等方法实现xxxxx执行混淆。
其基本命令为:
Confuser.CLI.exe <path to project file>
以下是两种方式的示例:
-
方式一:通过bat脚本执行ConfuserEx.CIL.exe工具
..\release\tool\ConfuserEx.CIL.exe Your_ConfuderExProjectPath.crproj
-
方式二:通过csproj配置MSBuild事件
-
csproj配置如下:
<Project Sdk="Microsoft.NET.Sdk"> <PropertyGroup> <OutputType>WinExe</OutputType> <TargetFramework>net5.0-windows</TargetFramework> <UseWPF>true</UseWPF> <ConfuserExPath>$(SolutionDir)tools\ConfuserEx\Confuser.CLI.exe</ConfuserExPath> <ConfuserConfig>$(SolutionDir)tools\ConfuserEx\ConfuserDemoConfuder.crproj</ConfuserConfig> </PropertyGroup> <ItemGroup> <ProjectReference Include="..\ConfuserDllDemo2\ConfuserDllDemo2.csproj" /> <ProjectReference Include="..\ConfuserDllDemo\ConfuserDllDemo.csproj" /> </ItemGroup> <Target Name="Obfuscate" AfterTargets="Build"> <!-- 执行混淆命令 --> <Exec Command=""$(ConfuserExPath)" "$(ConfuserConfig)"" /> </Target> </Project>
-
配置解析
-
定义 ConfuserEx 路径
<PropertyGroup> <ConfuserExPath>$(SolutionDir)tools\ConfuserEx\Confuser.CLI.exe</ConfuserExPath> <ConfuserConfig>$(SolutionDir)tools\ConfuserEx\ConfuserDemoConfuder.crproj</ConfuserConfig> </PropertyGroup>
ConfuserExPath
:指定 ConfuserEx 的可执行文件路径。$(SolutionDir)
是 MSBuild 的内置变量,表示解决方案的根目录。但是注意只有通过解决f- 确保路径中使用的是反斜杠
\
,而不是正斜杠/
。
ConfuserConfig
:指定 ConfuserEx 的配置文件路径。- 配置文件
.crproj
包含了混淆规则和保护选项。
- 配置文件
-
定义构建后目标
<Target Name="Obfuscate" AfterTargets="Build"> <!-- 执行混淆命令 --> <Exec Command=""$(ConfuserExPath)" "$(ConfuserConfig)"" /> </Target>
Target
:定义一个名为Obfuscate
的目标。AfterTargets="Build"
:表示该目标会在Build
目标完成后执行。
Exec
:执行命令行指令。Command
属性中使用了"
来转义双引号,确保路径中包含空格时命令能正确执行。
-
-
2.5 深入设置
2.5.1 保护机制
ConfuserEx 提供了四种混淆预设:Minimum,Normal,Aggressive,Maximum,每种预设,设定了不同的混淆模式,也可以选择不设置预设,自行选择混淆模式。其对应关系如下:
**Protection保护项** / **preset**预设 | Minimum | Normal | Aggressive | Maximum |
---|---|---|---|---|
Name | ✅ | ✅ | ✅ | ✅ |
Hardening | ✅ | ✅ | ✅ | ✅ |
Anti Debug | ✅ | ✅ | ✅ | ✅ |
Anti IL Dasm | ✅ | ✅ | ✅ | ✅ |
Watermark | ✅ | ✅ | ✅ | ✅ |
Constants | ✅ | ✅ | ✅ | |
Reference Proxy | ✅ | ✅ | ✅ | |
Resources | ✅ | ✅ | ✅ | |
Anti Dump | ✅ | |||
Anti Tamper | ✅ | |||
Invalid Metadata | ✅ | |||
Type Scramble |
2.5.1.1 ConfuserEx Protection
标题 | 简要说明 | 缺点 | 备注 |
---|---|---|---|
Hardening 代码硬化保护 | 合并调用指令,隐藏敏感方法,对性能影响小 | 适用范围小,只针对全局静态构造函数 | 可能对方法有要求。实践没起效 |
Reference Proxy 中间代理保护 | 添加中间方法作为代理,隐藏对类型、方法和字段的引用 | 可能对方法有要求。实践没起效 | |
Anti Debug 反调试保护 | 保护代码会维护一个专用线程来监控调试器。 | 只适用于应用程序的主程序集,对性能有影响,能够被dnspy移除 | |
Watermark | 增加一个被ConfuserEx 保护的特性,也没有实质性的保护,默认启用 | ||
Anti IL Dasm | 给代码添加一个SuppressIldasmAttribute自定义属性 | 没有任何实质性的混淆保护,只是增加礼貌的提示。 | |
Invalid Metadata | 向模块中添加无效的元数据,阻止反汇编器或反编译器正常打开目标程序。 | 实践没起效,不明原因 | |
Anti Dump防转储保护 | 不推荐,我们需要能够捕捉Dump以进行分析 | ||
Rename 重命名保护 | 高效,推荐,支持多种重命名方式 | 可能会影响反射 | 推荐 |
Anti Tamper反篡改保护 | 确保应用程序的完整性。 | ||
Type Scramble | 类型混淆保护 | 不明副作用,不推荐使用。使用最好对特定类型启用 | |
Constants | 使用算法对程序中的常量进行压缩,推荐使用 | 推荐 | |
Resources 资源保护 | 通过算法对资源进行编码和压缩 |
2.5.2 精细的代码保护
声明式混淆和表达式函数是ConfuserEx中非常重要的功能,它们共同为开发者提供了灵活、精确的代码保护机制。声明式混淆通过ObfuscationAttribute
特性直接在代码中指定混淆规则,而表达式函数通过规则模式筛选代码元素,实现更精细的代码保护。
-
声明式混淆
使用System.Reflection.ObfuscationAttribute 特性指导ConcuserEx混淆。
声明式混淆是通过.NET框架提供的
System.Reflection.ObfuscationAttribute
特性来指导混淆工具(如ConfuserEx)对代码进行混淆的一种方式。
主要特性
- Exclude:布尔值,表示是否将当前代码元素排除在混淆之外。
Exclude = true
:当前代码元素不会被混淆。Exclude = false
:当前代码元素会被混淆。
- Feature:字符串值,用于指定混淆工具的特定功能。
- 例如:
Feature = "generate debug symbol: true"
表示生成调试符号。 - 也可以组合多个功能,如
Feature = "preset(minimum);+ctrl flow;-anti debug;+rename(mode=letters,flatten=false)"
。
- 例如:
- ApplyToMembers:布尔值,表示是否将当前类型的混淆规则应用到其成员。
- 默认值为
true
,表示混淆规则会应用到类型的所有成员。
- 默认值为
[assembly: Obfuscation(Exclude = false, Feature = "generate debug symbol: true")]
[assembly: Obfuscation(Exclude = false, Feature = "random seed: Hello!")]
[assembly: Obfuscation(Exclude = false, Feature = "strong name key:C:\\key.pfx")]
[assembly: Obfuscation(Exclude = false, Feature = "strong name key password:hunter2")]
[assembly: Obfuscation(Exclude = false, Feature = "packer:compressor(key=dynamic)")]
[assembly: Obfuscation(Exclude = false, Feature = "preset(minimum);+ctrl flow;-anti debug;+rename(mode=letters,flatten=false);")]
[assembly: Obfuscation(Exclude = false, Feature = "namespace('Test'):-rename")]
[assembly: Obfuscation(Exclude = false, Feature = "namespace('LibraryA.Test'):+rename")]
[assembly: Obfuscation(Exclude = false, Feature = "external module:LibraryB.dll")]
namespace Test {
[Obfuscation(Exclude = false, Feature = "constants")]
class Program {
public static void Main() {
Console.WriteLine("Hi");
}
}
}
-
表达式函数
在设置规则时,可以看到一个Pattern,其默认值为true。这里支持设置表达式函数筛选模块中哪些成员进行混淆。通过组合这些函数和运算符,可以灵活地指定规则的适用范围,从而实现更精细的代码保护。
-
规则模式的构成
规则模式由以下部分组成:
- 文字表达(Literal Expressions):
- 布尔文字:
true
和false
,用于表示逻辑值。 - 字符串文字:用单引号(
'
)或双引号("
)括起来的字符串,支持用反斜杠(\
)转义特殊字符。例如:'NS1.MyClass'
。
- 布尔文字:
- 运算符:
and
:逻辑与。or
:逻辑或。not
:逻辑非。
- 表达函数(Expression Functions):
- 这些函数用于检查代码元素的属性,返回布尔值(
true
或false
)。 - 如果返回
true
,则表示该规则适用于当前评估的代码元素。
- 这些函数用于检查代码元素的属性,返回布尔值(
- 文字表达(Literal Expressions):
-
支持的函数
1.
decl-type(string)
- 功能:检查当前评估的类型(或类型成员的声明类型)是否具有指定的签名。
- 示例:
decl-type("System.Object")
返回true
,如果当前类型是System.Object
。
2.
full-name(string)
- 功能:检查当前评估的项目是否具有指定的签名(全名)。
- 示例:
full-name("MyNamespace.MyClass")
返回true
,如果当前项目的全名是MyNamespace.MyClass
。
3.
is-public()
- 功能:检查当前评估的项目是否在程序集外部可见(即是否为公共成员)。
- 示例:
is-public()
返回true
,如果当前项目是公共的。
4.
match(string)
- 功能:检查当前评估的项目的签名是否与指定的正则表达式匹配。
- 示例:
match(".*MyClass.*")
返回true
,如果当前项目的签名包含MyClass
。
5.
match-name(string)
- 功能:检查当前评估的项目的名称是否与指定的正则表达式匹配。
- 示例:
match-name("MyClass")
返回true
,如果当前项目的名称是MyClass
。
6.
match-type-name(string)
- 功能:检查当前评估的类型的名称(或类型成员的声明类型的名称)是否与指定的正则表达式匹配。
- 示例:
match-type-name("MyClass")
返回true
,如果当前类型的名称是MyClass
。
7.
member-type(string)
- 功能:检查当前评估的项目是否具有指定的类型。
- 支持的类型:
type
、method
、field
、property
、event
和module
。 - 示例:
member-type("method")
返回true
,如果当前项目是一个方法。
8.
module(string)
- 功能:检查当前评估的项目的模块是否具有指定的名称。
- 示例:
module("MyModule.dll")
返回true
,如果当前项目的模块名称是MyModule.dll
。
9.
name(string)
- 功能:检查当前评估的项目的名称是否与指定的名称匹配。
- 示例:
name("MyMethod")
返回true
,如果当前项目的名称是MyMethod
。
10.
namespace(string)
- 功能:检查当前评估的类型(或类型成员的声明类型)是否具有指定的命名空间。
- 示例:
namespace("MyNamespace")
返回true
,如果当前类型的命名空间是MyNamespace
。
11.
inherits(string)
- 功能:检查当前评估的类型是否继承自指定的类型。
- 示例:
inherits("System.Exception")
返回true
,如果当前类型继承自System.Exception
。
12.
is-type(string)
- 功能:检查当前评估的类型是否属于指定的特殊类型。
- 示例:
is-type("delegate")
返回true
,如果当前类型是一个委托。
-
实践
例如:要匹配程序集
ConfuserDllDemo2
中CalculateExpressionFunctions
类的Calculate
方法,可以使用 ConfuserEx 的规则模式。member-type('method') and name('Calculate') and decl-type('ConfuserDllDemo2.CalculateExpressionFunctions')
-
- 配置示例
<project outputDir="E:\File\WorkFile\ConfuserExTest\ConfuserDemo\ConfuserDemo\bin\Debug\net5.0-windows\Confused" baseDir="E:\File\WorkFile\ConfuserExTest\ConfuserDemo\ConfuserDemo\bin\Debug\net5.0-windows" xmlns="http://confuser.codeplex.com"> <module path="ConfuserDemo.dll"> inherit="false"> <protection id="constants" /> </rule> </module> <module path="ConfuserDllDemo.dll"> inherit="false"> <protection id="rename"> <argument name="mode" value="reversible" /> <argument name="generatePassword" value="true" /> protection> <protection id="harden" /> <protection id="constants" /> <protection id="ref proxy" /> <protection id="invalid metadata" /> </rule> </module> <module path="ConfuserDllDemo2.dll"> inherit="false"> <protection id="ctrl flow" /> <protection id="constants" /> <protection id="rename"> <argument name="mode" value="reversible" /> <argument name="generatePassword" value="true" /> protection> </rule> </module> <probePath>C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App\5.0.17</probePath> <probePath>C:\Program Files\dotnet\shared\Microsoft.NETCore.App\5.0.17</probePath> <probePath>C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App\5.0.17</probePath> </project>
2.6 使用建议
-
建议启用重命名保护、常量保护
高效,对性能影响小
<protection id="constants" /> <protection id="rename"> <argument name="mode" value="reversible" /> <argument name="generatePassword" value="true" /> protection>
-
结合使用声明式混淆和表达式函数和对核心或敏感代码进行混淆
-
注意避免重命名可能会进行反射的方法