本文来安利大家 Obfuscar 这个好用的基于 MIT 协议开源的混淆工具。这是一个非常老牌的混淆工具,从 2014 年就对外分发,如今已有累计 495.5K 的 nuget 下载量。而且此工具也在不断持续迭代更新,完全支持 dotnet 6 版本,对 WPF 和 WinForms 等等的支持也是非常好,支持多个不同混淆方式和等级的配置,支持混淆之后生成符号文件。本文将来告诉大家如何使用此混淆工具,以及此工具能达成的效果和此工具混淆的原理

开源

此工具是由 Lex Li 主导开发的,在 GitHub 上使用 MIT 最友好协议开源,开源地址是 https://github.com/obfuscar/obfuscar

使用方法

此工具的使用方式有多个不同的方式,比较推荐的是采用 dotnet tool 的方式进行使用。因为使用 dotnet tool 可以非常方便接入自己已有的 CI CD 上,而且也可以实现非常方便的更新逻辑

按照约定,使用 dotnet tool 的第一步是进行安装,安装的方法就是在命令行输入以下代码

dotnet tool install --global Obfuscar.GlobalTool

如此即可完成安装。安装完成之后的使用方法是调用 obfuscar.console 命令,传入混淆配置 Obfuscar.xml 文件即可,如下面命令行例子

obfuscar.console Obfuscar.xml

也就是说最关键的只有两点,第一个就是命令行的工作路径,另一个就是混淆配置 Obfuscar.xml 文件

假定我有一个项目是 HeenerholiCeleehano 项目,此项目我需要对他进行混淆。此项目输出的是 HeenerholiCeleehano.dll 文件,放在 C:\lindexi\Code\lindexi\HeenerholiCeleehano\HeenerholiCeleehano\bin\Release\net6.0-windows\ 文件夹下

那么在混淆之前,请设置好命令行的工作路径,如使用 cd 命令进入到输出文件夹,如以下命令

cd C\lindexi\Code\lindexi\HeenerholiCeleehano\HeenerholiCeleehano\bin\Release\net6.0-windows\

接下来是要在 C:\lindexi\Code\lindexi\HeenerholiCeleehano\HeenerholiCeleehano\bin\Release\net6.0-windows\ 文件夹下放一个混淆配置 Obfuscar.xml 文件,文件内容可以是如下

<?xml version='1.0'?>
<Obfuscator>
<Var name="InPath" value="." />
<Var name="OutPath" value=".\Obfuscar" />
<Var name="KeepPublicApi" value="true" />
<Var name="HidePrivateApi" value="true" />
<Var name="HideStrings" value="false" />
<Var name="UseUnicodeNames" value="true" />
<Var name="ReuseNames" value="true" />
<Var name="RenameFields" value="true" />
<Var name="RegenerateDebugInfo" value="true" />
<Module file="$(InPath)\HeenerholiCeleehano.dll" /> <AssemblySearchPath path="C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App\6.0.1\" />
<AssemblySearchPath path="C:\Program Files\dotnet\shared\Microsoft.NETCore.App\6.0.1\" />
</Obfuscator>

以上配置文件的含义如下,我一一带上注释标识

<?xml version='1.0'?>
<Obfuscator>
<!-- 输入的工作路径,采用如约定的 Windows 下的路径表示法,如以下表示当前工作路径 -->
<!-- 推荐使用当前工作路径,因为 DLL 的混淆过程,需要找到 DLL 的所有依赖。刚好当前工作路径下,基本都能满足条件 -->
<Var name="InPath" value="." />
<!-- 混淆之后的输出路径,如下面代码,设置为当前工作路径下的 Obfuscar 文件夹 -->
<!-- 混淆完成之后的新 DLL 将会存放在此文件夹里 -->
<Var name="OutPath" value=".\Obfuscar" />
<!-- 以下的都是细节的配置,配置如何进行混淆 --> <!-- 使用 KeepPublicApi 配置是否保持公开的 API 不进行混淆签名,如公开的类型公开的方法等等,就不进行混淆签名了 -->
<!-- 语法的写法就是 name 表示某个开关,而 value 表示值 -->
<!-- 对于大部分的库来说,设置公开的 API 不进行混淆是符合预期的 -->
<Var name="KeepPublicApi" value="true" />
<!-- 设置 HidePrivateApi 为 true 表示,对于私有的 API 进行隐藏,隐藏也就是混淆的意思 -->
<!-- 可以通过后续的配置,设置混淆的方式,例如使用 ABC 字符替换,或者使用不可见的 Unicode 代替 -->
<Var name="HidePrivateApi" value="true" />
<!-- 设置 HideStrings 为 true 可以设置是否将使用的字符串进行二次编码 -->
<!-- 由于进行二次编码,将会稍微伤一点点性能,二次编码需要在运行的时候,调用 Encoding 进行转换为字符串 -->
<Var name="HideStrings" value="false" />
<!-- 设置 UseUnicodeNames 为 true 表示使用不可见的 Unicode 字符代替原有的命名,通过此配置,可以让反编译看到的类和命名空间和成员等内容都是不可见的字符 -->
<Var name="UseUnicodeNames" value="true" />
<!-- 是否复用命名,设置为 true 的时候,将会复用命名,如在不同的类型里面,对字段进行混淆,那么不同的类型的字段可以是重名的 -->
<!-- 设置为 false 的时候,全局将不会有重复的命名 -->
<Var name="ReuseNames" value="true" />
<!-- 配置是否需要重命名字段,默认配置了 HidePrivateApi 为 true 将都会打开重命名字段,因此这个配置的存在只是用来配置为 false 表示不要重命名字段 -->
<Var name="RenameFields" value="true" />
<!-- 是否需要重新生成调试信息,生成 PDB 符号文件 -->
<Var name="RegenerateDebugInfo" value="true" /> <!-- 需要进行混淆的程序集,可以传入很多个,如传入一排排 -->
<!-- <Module file="$(InPath)\Lib1.dll" /> -->
<!-- <Module file="$(InPath)\Lib2.dll" /> -->
<Module file="$(InPath)\HeenerholiCeleehano.dll" /> <!-- 程序集的引用加载路径,对于 dotnet 6 应用,特别是 WPF 或 WinForms 项目,是需要特别指定引用加载路径的 -->
<!-- 这里有一个小的需要敲黑板的知识点,应该让 Microsoft.WindowsDesktop.App 放在 Microsoft.NETCore.App 之前 -->
<!-- 对于部分项目,如果没有找到如下顺序,将会在混淆过程中,将某些程序集解析为旧版本,从而失败 -->
<AssemblySearchPath path="C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App\6.0.1\" />
<AssemblySearchPath path="C:\Program Files\dotnet\shared\Microsoft.NETCore.App\6.0.1\" />
</Obfuscator>

详细的配置,还请参阅官方文档

执行如上的命令行进行混淆,即可实现命名混淆效果

使用 dotPeek 反编译可以看到字段被混淆为如下内容

    private readonly int \u00A0;
private readonly short \u00A0;

这里需要复习一下 IL 的知识,在 IL 里面,是允许不同的字段重名的,只要字段的类型不相同即可。因为使用的时候,是用类型名加字段名的方式使用的。这也能让代码更加混淆

以上就是我推荐的使用 dotnet tool 的方式

除了使用 dotnet tool 的方式之外,还可以自己将混淆过程嵌入到构建过程里面,如此可以实现在开发阶段对混淆的结果进行调试。也就是开发时调试的 DLL 就是混淆过后的

使用构建过程的方式需要编辑一下 csproj 项目文件,先在项目文件使用下面代码安装 Obfuscar 库,代码如下

  <ItemGroup>
<PackageReference Include="Obfuscar" Version="2.2.33">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
</ItemGroup>

在需要写构建过程下,预计实际需求都是千奇百怪的,很难有统一的方式,本文只是提供一个简单的例子

完成安装之后,在项目上放一个混淆配置 Obfuscar.xml 文件,设置此文件如果较新则输出

  <ItemGroup>
<None Update="Obfuscar.xml">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>

最后编写一个 Target 用来在构建完成之后调用命令行进行混淆,代码如下

  <Target Name="ObfuscarTask" AfterTargets="AfterBuild">
<PropertyGroup>
<ObfuscateCommand>$(Obfuscar) "Obfuscar.xml"</ObfuscateCommand>
</PropertyGroup>
<Exec WorkingDirectory="$(OutputPath)" Command="$(ObfuscateCommand)" />
</Target>

如此即可实现在构建完成之后,自动调用

以上的代码放在 githubgitee 欢迎访问

可以通过如下方式获取本文的源代码,先创建一个空文件夹,接着使用命令行 cd 命令进入此空文件夹,在命令行里面输入以下代码,即可获取到本文的代码

git init
git remote add origin https://gitee.com/lindexi/lindexi_gd.git
git pull origin b0b402abe4f32008d383d984bff677ac45cccde8

以上使用的是 gitee 的源,如果 gitee 不能访问,请替换为 github 的源

git remote remove origin
git remote add origin https://github.com/lindexi/lindexi_gd.git

获取代码之后,进入 HeenerholiCeleehano 文件夹

以上代码的混淆配置 Obfuscar.xml 文件里使用的程序集引用路径写的是 C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App\6.0.1\ 路径,这是因为代码是之前写的,博客是鸽子很久才写的,还请大家自行更新

混淆原理

此混淆工具底层使用 Mono.Cecil 进行程序集的读取和编织,使用 Mono.Cecil 可以读取出程序集的信息,从读取到的信息进行更改,更改也就是混淆的核心逻辑,更改完成之后,再通过 Mono.Cecil 生成新的程序集文件,如此即可完成混淆

此工具在 GitHub 上完全开源,请看 https://github.com/obfuscar/obfuscar

更多细节逻辑还请自己去阅读源代码

更多阅读

其他的混淆工具还有非常多,可以从 https://github.com/NotPrab/.NET-Obfuscator 找到更多的混淆工具列表

当然,有混淆工具,也就有反混淆工具。可以从 https://github.com/NotPrab/.NET-Deobfuscator 找到更多反混淆列表

dotnet 6 使用 Obfuscar 进行代码混淆的更多相关文章

  1. 【Dotnet 工具箱】JIEJIE.NET - 强大的 .NET 代码混淆工具

    你好,这里是 Dotnet 工具箱,定期分享 Dotnet 有趣,实用的工具和组件,希望对您有用! JIEJIE.NET - 强大的 .NET 代码混淆工具 JIEJIE.NET JIEJIE.NET ...

  2. 【Android】Android Studio 进行代码混淆,打包release APK

    整了一天,感觉坑挺多. 1. 选择如图中的选项Android Studio进行签名打包: 2. 填写APP对应的信息:(最好用个文本记下来放在项目中同步给Team) - Key store path: ...

  3. ProGuard代码混淆技术详解

    前言     受<APP研发录>启发,里面讲到一名Android程序员,在工作一段时间后,会感觉到迷茫,想进阶的话接下去是看Android系统源码呢,还是每天继续做应用,毕竟每天都是画UI ...

  4. Android Studio代码混淆插件

    之前给公司的App添加代码混淆,在代码的混淆过程也遇到了不少的问题,再加上最近学习了一下Android Studio插件的开发,所以就开发一个代码混淆插件方便项目的代码混淆. 截图 第三方库列表清单 ...

  5. 77.Android之代码混淆

    转载:http://www.jianshu.com/p/7436a1a32891 简介 作为Android开发者,如果你不想开源你的应用,那么在应用发布前,就需要对代码进行混淆处理,从而让我们代码即使 ...

  6. Android 代码混淆、第三方平台加固加密、渠道分发 完整教程(图文)

    第一步:代码混淆(注意引入的第三方jar) 在新版本的ADT创建项目时,混码的文件不再是proguard.cfg,而是project.properties和proguard-project.txt. ...

  7. 推荐一个C#代码混淆器 .NET Reactor【转】

    C#的代码辛苦写出来之后,一个反射工具,就可以完全显露出来. 当然,在做项目时,这个功能还不错.因为我就曾在一个项目上使用C#,没有进行任何混淆.结果在项目二年多之后,需要做一些调整,自己保存的源代码 ...

  8. Android代码混淆官方实现方法

    首先查看一下 “project.properties” 这个文件: # This file is automatically generated by Android Tools.# Do not m ...

  9. android 常用第三方包的代码混淆

    首先在:project.properties 文件下,启动代码混淆 proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:pro ...

  10. Android 代码混淆 防止反编译

    为了防止代码被反编译,因此需要加入混淆.混淆也可以通过第三方进行apk混淆,也可以用android中的proguard进行混淆. 混淆步骤: 1.配置混淆文件,名字可以随意,在这里使用proguard ...

随机推荐

  1. 初学STM32 CAN通信(三)

    1. stm32 CAN通信标准库函数 //CAN通信初始化函数 uint8_t CAN_Init(CAN_TypeDef* CANx, CAN_InitTypeDef* CAN_InitStruct ...

  2. sql分页遍历出现重复数据原因与解决方案

    1. 问题描述 有同时反馈,直接通过如下的sql进行分页查询,分页会出现重复数据,于是乎我专门查了相关了资料,整理了一下. -- 根据sort字段对dbname进行排序,每五百条数据一页 SELECT ...

  3. AndroidStudio--app是如何运行的

    #实用快捷键# Ctrl+alt+F 快速自动把类方法内部的变量声明为类属性变量,以方便全局使用! Ctrl+O  快速显示所有类方法以及field属性结构 今天发现了一个非常好的博主----litt ...

  4. 5W1H聊开源之What——开源协议有哪些?

    开源许可协议是指开源社区为了维护作者和贡献者的合法权利,保证软件不被一些商业机构或个人窃取,影响软件的发展而开发的协议.开源协议规定了用户在使用开源软件时的权利和责任,虽然不一定具备法律效力,但是当涉 ...

  5. el-table边框颜色修改—骨灰级

    一.前言说明 1. 网上很多都是通过上下左右边框方式,如: .el-table { border-bottom: 1px solid black; border-right: 1px solid bl ...

  6. [一本通1700]PFS集合

    题目描述 有一种特殊的集合叫做PFS(Prefix Free Set)集合. 一个PFS集合由若干字符串构成,且不存在一个字符串是另一个字符串的前缀.空集也被看作是PFS集合. 例如 {\(" ...

  7. HarmonyOS跨进程通信—IPC与RPC通信开发指导

      一.IPC与RPC通信概述 基本概念 IPC(Inter-Process Communication)与RPC(Remote Procedure Call)用于实现跨进程通信,不同的是前者使用Bi ...

  8. signalr 应用于微信小程序(二)

    前言 本节基于一,为2017年写的脚本库. 正文 我们连接的是websocket那么我们需要看的是ws: 这里看到需要的参数其实只要connecttoken我们是没有的,那么如果得到的呢? 是网络请求 ...

  9. 重新整理数据结构与算法(c#)—— 算法套路分治算法[二十五]

    前言 有一个汉罗塔的游戏如下: 汉诺塔:汉诺塔(又称河内塔)问题是源于印度一个古老传说的益智玩具. 大梵天创造世界的时候做了三根金刚石柱子,在一根柱子上从下往上按照大小顺序摞着64片黄金圆盘. 大梵天 ...

  10. vue登录3D效果

    实现的效果 登录动态效果很炫酷,话不多说直接上代码: 组件template <template> <div class="entrance"> <di ...