是一个.NET的Obfuscator。它提供企业级的应用程序保护,大大降低了盗版、知识产权盗窃和篡改的风险。Dotfuscator的分层混淆、加密、水印、自动失效、防调试、防篡改、报警和防御技术,为世界各地成千上万的应用程序提供保护。
Dotfuscator提供了一种应用程序保护的多层方法。这些层中的每一层都提供了一个重要的整体保护策略。如果一层受到损害,其他层继续提供有效保护,使攻击者更难以实现其目标。并且不仅有多个层,而且每个层都具有比其他混淆产品使用的简单技术更强大的高级功能。
从本文开始我们一起了解Dotfuscator如何对应用程序进行多层保护,层层递进,大致可分为:
- 第一层保护——Obfuscation转换:它对编译的代码进行操作,使逆向工程变得困难或不可能。
- 第二层保护——保护程序运行时发生的检查:当程序检测到攻击者试图篡改或反向工程时,它可以使用自定义逻辑进行自我防御。
- 其余加强保护——包括切除和水印。
- Dotfuscator提供某些功能帮您构建、部署和调试混淆的程序集。
>>
第一层保护:Obfuscation转换
重命名
Dotfuscator能够将所有类、方法和字段重命名为短名称。这使得反编译输出更加难以理解,并且使得生成的可执行文件的大小更小。
大多数商业混淆器使用一种重命名技术,该技术应用的普通标识符可以短至单个字符。当obfuscator处理代码时,它选择下一个可用的平凡标识符进行替换。这个看似简单的重命名方案有一个关键属性:它是不可逆转的。在保留程序逻辑的同时,这些名称变得毫无意义,阻碍了所有理解代码的尝试。
▲过载感应
Dotfuscator使用了一种更深层次的混淆技术,它是为Dotfuscator开发的,并通过先发制人的解决方案获得了专利,称为过载感应™。重载归纳不是为每个旧名称替换一个新名称,而是将尽可能多的方法重命名为相同的名称。下面的简单例子说明了过载感应技术的威力:
混淆之前的原始源代码:
private void CalcPayroll(SpecialList employeeGroup) { while (employeeGroup.HasMore()) { employee = employeeGroup.GetNext(true); employee.UpdateSalary(); DistributeCheck(employee); }}复制代码
重载感应混淆后的反向工程源代码:
private void a(a b) { while (b.a()) { a = b.a(true); a.a(); a(a); }}复制代码
实例表明,代码被混淆和压缩,这是重命名的一个积极的副作用。通过保存字符串堆条目,重命名还可以节省空间。这种方法有着明显的优点在于:
- 重命名使反编译输出难以理解。在目标源语言中重命名不可打印字符或非法名称是无效的,因为反编译器可以重命名这些标识符。考虑到重载诱导可能使三个方法名中的一个成为“a()”,理解反编译输出是困难的。
- 除了存在于所有重命名系统中的限制外,超载诱导没有其他限制。
- 由于过载诱导往往更频繁地使用相同的字母,所以它进入较长名称的速度更慢(例如aa、aaa等),这也节省了空间。
Overload-Induction的专利算法确定所有可能的重命名冲突,只有在安全的情况下才会引发方法重载。这个过程可以证明是不可逆的。换句话说,重构原始方法名称关系是不可能的(即使再次运行重载诱导)。
▲增强的过载感应
Dotfuscator还通过允许将方法的返回类型或字段的类型用作确定方法或字段唯一性的标准,从而增强了超载诱导™。该特性允许在方法和字段重命名中最多增加15%的冗余。此外,由于在源语言(包括c#和Visual Basic)中通常不允许重载方法返回类型或字段类型,这进一步阻碍了反编译器。
▲限制
通常不会对包含任何XAML代码的程序集执行过载诱导,因为运行时确定XAML和代码如何链接的方式不同。因此,Use Enhanced Overload Induction选项不会更改此类程序集的任何内容。当使用任何类型的反射(包括XAML)、指定入口点的配置文件、其他应用程序调用的库等时,重命名可能会出现问题。在重命名后对应用程序进行全面测试,以确保不存在此类问题,这一点非常重要。
▲具体排除
假定库模式已关闭,Dotfuscator将尝试重命名它所能重命名的所有内容。反射的某些使用可能导致Dotfuscator在重命名时不更新对特定实体的所有引用。在下面的例子中,我们排除了四个类及其字段:
我们的应用程序通过反射查找这些类型和成员的名称来引用它们。如果要重命名它们,应用程序将无法在运行时找到它们。因此,我们将它们排除在通过这些复选框重命名之外。
▲自定义排除规则
有时候,您可能需要为特定的编码约定做出许多特定的排除。即使这样,当开发人员添加更多遵循该约定的代码时,他们也必须记住对新代码进行另一个特定的排除。
对此的解决方案是自定义排除规则。使用前面的示例,假设我们计算出所有名称以“Dungeon”结尾的类型,以及这些类型中的特定字段类型,都需要排除在重命名之外。与其创建一堆特定的排除,我们可以制定一个自定义规则:
我们使用Add Type按钮添加了规则的根节点,并将其命名为.*Dungeon,并将正则表达式(regex)选项设置为true,以指示应该将该名称视为正则表达式。因此,节点将匹配名称以“Dungeon”结尾的类型。因为我们将Exclude类型(excludetype)设置为true,所以任何匹配此名称的类型都将被排除在重命名之外。如果我们将该选项设置为false,那么匹配的类型将不会被排除在重命名之外——只包含由其子节点指定的成员。
然后,通过右键单击根节点并选择Add字段,我们添加了一个子节点。我们将这个节点命名为.*,并再次指出应该将其视为正则表达式。我们将规则限制为只覆盖具有公共访问修饰符的字段(通过设置+public),以及签名为string[]的字段,因为在我们的场景中这两个字段都是必需的。
配置好规则后,您可以选择一个节点并单击Preview按钮,Dotfuscator将在左侧的树视图中突出显示与定制规则匹配的条目。在我们的示例中,我们预览子节点,因此突出显示匹配条件的字段。
▲内置规则
内置规则是自定义的排除规则,非常普遍有用;我们默认包含它们,这样用户就不必重新实现它们。
例如,System.Web方法。服务属性转换为以下自定义规则:
Exclude all methods that are decorated with attributes from the System.Web.services namespace.复制代码
▲选项
options选项卡上有许多重命名选项,包括应该使用什么重命名方案、是否引入显式覆盖以及其他许多选项。
— 持续更新中 —
如果你有任何问题或意见,可在下方评论区留言,点击查看更多教程资源~