Dotfuscator 不支持 Unity3d?
Dotfuscator doesn't support Unity3d?
我用一些用 C# 编写的 DLL 测试了 Dotfuscator。
它似乎在 .NET 环境中运行良好,所以这次我用 Unity3D 尝试了它们。这些简单的 DLL 仅使用简单的标准 C# classes 和方法进行编码,没有反射,没有 LINQ,没有其他自定义或第三方 API,包括 Unity 的。但未能使它们在我的 Unity3d 项目中工作,而未混淆的原始纯 DLL 工作正常。
挣扎了几个小时后,我决定用新的简单项目进行测试。以下是我在 C# 中得到的所有内容,没有其他代码,根本没有其他参考。
[System.Reflection.Obfuscation(Feature = "renaming", Exclude = true)]
public class Class1
{
[System.Reflection.Obfuscation(Feature = "renaming", Exclude = true)]
public static int Get()
{
return 123;
}
}
编译成DLL后,我把它放在Unity3D Editor上的一个EMPTY工程里玩,效果不错。但是,当我在使用 Dotfuscator 混淆 DLL 后再次尝试时,它不再说“InvalidProgramException:Class1:Get () 中的无效 IL 代码:IL_000c:pop”。
正如你在上面看到的,我添加了防止代码被重命名的属性,当然,我可以在 Reflector 中看到,class 和方法的名称实际上并没有被重命名。
昨天在PreEmptive网站上新注册并下载了最新的Dotfuscator Professional Edition 4.21.0评估版。我在 Visual Studio 2008 年和 2015 年都使用 .NET 3.5 进行了编译,还尝试了所有不同的解决方案平台。 Unity的版本是5.3.4f1.
我现在的猜测是 Dotfuscator 仅适用于 MSIL,不适用于 Unity3D 内部使用的 Mono 2.X。
我说的对吗?有没有人把 Dotfuscator 和 Unity3D 或 Mono 一起用的好?
[编辑]
我使用 ILDasm 检查了 IL 代码,不明白发生了什么,但有趣的是看到一堆代码被修改了。
应用 Dotfuscator 之前
.method public hidebysig static int32 Get() cil managed
{
.custom instance void [mscorlib]System.Reflection.ObfuscationAttribute::.ctor() = ( 01 00 02 00 54 0E 07 46 65 61 74 75 72 65 08 72 // ....T..Feature.r
65 6E 61 6D 69 6E 67 54 02 07 45 78 63 6C 75 64 // enamingT..Exclud
65 01 ) // e.
// Code Size 6 (0x6)
.maxstack 8
IL_0000: ldc.i4 0x75bcd15
IL_0005: ret
} // end of method Class1::Get
应用 Dotfuscator 后
.method public hidebysig static int32 Get() cil managed
{
// Code Size 127 (0x7f)
.maxstack 2
.locals init (int32 V_0)
IL_0000: ldc.i4 0x993
IL_0005: stloc V_0
IL_0009: ldloca V_0
IL_000d: ldind.i4
IL_000e: ldc.i4 0x993
IL_0013: stloc V_0
IL_0017: ldloca V_0
IL_001b: ldind.i4
IL_001c: ceq
IL_001e: switch (
IL_002f,
IL_004c,
IL_002f)
IL_002f: br.s IL_003e
IL_0031: ldc.i4.0
IL_0032: stloc V_0
IL_0036: ldloca V_0
IL_003a: ldind.i4
IL_003b: pop
IL_003c: br.s IL_004a
IL_003e: ldc.i4.0
IL_003f: stloc V_0
IL_0043: ldloca V_0
IL_0047: ldind.i4
IL_0048: br.s IL_003b
IL_004a: nop
IL_004b: nop
IL_004c: ldc.i4 0x1
IL_0051: stloc V_0
IL_0055: ldloca V_0
IL_0059: ldind.i4
IL_005a: br.s IL_0068
IL_005c: ldc.i4.0
IL_005d: stloc V_0
IL_0061: ldloca V_0
IL_0065: ldind.i4
IL_0066: br.s IL_0068
IL_0068: brfalse.s IL_006a
IL_006a: ldc.i4.0
IL_006b: stloc V_0
IL_006f: ldloca V_0
IL_0073: ldind.i4
IL_0074: brfalse IL_0079
IL_0079: ldc.i4 0x75bcd15
IL_007e: ret
} // end of method Class1::Get
更新:从版本 6.0 开始,Dotfuscator Professional 不再支持 Unity。 (参见 changelog for 6.0.0-beta)。它继续支持 Mono。原答案如下。
是的,Dotfuscator Professional Edition 支持 Mono 和 Unity。您在 IL 中看到差异的原因是专业版提供的 Control Flow 混淆。这与您已从中排除标识符的 重命名 功能不同。
默认情况下,Dotfuscator 在 .NET Framework(即 Microsoft 的实现)上尽可能多地使用控制流转换。 但是,其中一些转换与 Mono 不兼容。 Dotfuscator 提供了一个选项来禁用此类转换。
在 GUI 中加载 Dotfuscator 项目后,可以在 "Advanced" 下的“设置”选项卡上找到此选项,名称为 "Use only Mono-compatible transforms"。将此选项设置为 "Yes",然后保存并重建项目。
如果这仍然给您带来问题,您可以完全禁用控制流以查看是否可以解决问题。这也位于 "Features"、"Disable Control Flow" 下的“设置”选项卡上。将此选项设置为 "Yes",然后保存并重建项目。
完全披露:我在 PreEmptive Solutions 的 Dotfuscator 团队工作。如果您有更多问题,请记住像您这样的评估用户也可以完全访问 PreEmptive 支持。
我用一些用 C# 编写的 DLL 测试了 Dotfuscator。 它似乎在 .NET 环境中运行良好,所以这次我用 Unity3D 尝试了它们。这些简单的 DLL 仅使用简单的标准 C# classes 和方法进行编码,没有反射,没有 LINQ,没有其他自定义或第三方 API,包括 Unity 的。但未能使它们在我的 Unity3d 项目中工作,而未混淆的原始纯 DLL 工作正常。 挣扎了几个小时后,我决定用新的简单项目进行测试。以下是我在 C# 中得到的所有内容,没有其他代码,根本没有其他参考。
[System.Reflection.Obfuscation(Feature = "renaming", Exclude = true)]
public class Class1
{
[System.Reflection.Obfuscation(Feature = "renaming", Exclude = true)]
public static int Get()
{
return 123;
}
}
编译成DLL后,我把它放在Unity3D Editor上的一个EMPTY工程里玩,效果不错。但是,当我在使用 Dotfuscator 混淆 DLL 后再次尝试时,它不再说“InvalidProgramException:Class1:Get () 中的无效 IL 代码:IL_000c:pop”。
正如你在上面看到的,我添加了防止代码被重命名的属性,当然,我可以在 Reflector 中看到,class 和方法的名称实际上并没有被重命名。
昨天在PreEmptive网站上新注册并下载了最新的Dotfuscator Professional Edition 4.21.0评估版。我在 Visual Studio 2008 年和 2015 年都使用 .NET 3.5 进行了编译,还尝试了所有不同的解决方案平台。 Unity的版本是5.3.4f1.
我现在的猜测是 Dotfuscator 仅适用于 MSIL,不适用于 Unity3D 内部使用的 Mono 2.X。
我说的对吗?有没有人把 Dotfuscator 和 Unity3D 或 Mono 一起用的好?
[编辑] 我使用 ILDasm 检查了 IL 代码,不明白发生了什么,但有趣的是看到一堆代码被修改了。
应用 Dotfuscator 之前
.method public hidebysig static int32 Get() cil managed
{
.custom instance void [mscorlib]System.Reflection.ObfuscationAttribute::.ctor() = ( 01 00 02 00 54 0E 07 46 65 61 74 75 72 65 08 72 // ....T..Feature.r
65 6E 61 6D 69 6E 67 54 02 07 45 78 63 6C 75 64 // enamingT..Exclud
65 01 ) // e.
// Code Size 6 (0x6)
.maxstack 8
IL_0000: ldc.i4 0x75bcd15
IL_0005: ret
} // end of method Class1::Get
应用 Dotfuscator 后
.method public hidebysig static int32 Get() cil managed
{
// Code Size 127 (0x7f)
.maxstack 2
.locals init (int32 V_0)
IL_0000: ldc.i4 0x993
IL_0005: stloc V_0
IL_0009: ldloca V_0
IL_000d: ldind.i4
IL_000e: ldc.i4 0x993
IL_0013: stloc V_0
IL_0017: ldloca V_0
IL_001b: ldind.i4
IL_001c: ceq
IL_001e: switch (
IL_002f,
IL_004c,
IL_002f)
IL_002f: br.s IL_003e
IL_0031: ldc.i4.0
IL_0032: stloc V_0
IL_0036: ldloca V_0
IL_003a: ldind.i4
IL_003b: pop
IL_003c: br.s IL_004a
IL_003e: ldc.i4.0
IL_003f: stloc V_0
IL_0043: ldloca V_0
IL_0047: ldind.i4
IL_0048: br.s IL_003b
IL_004a: nop
IL_004b: nop
IL_004c: ldc.i4 0x1
IL_0051: stloc V_0
IL_0055: ldloca V_0
IL_0059: ldind.i4
IL_005a: br.s IL_0068
IL_005c: ldc.i4.0
IL_005d: stloc V_0
IL_0061: ldloca V_0
IL_0065: ldind.i4
IL_0066: br.s IL_0068
IL_0068: brfalse.s IL_006a
IL_006a: ldc.i4.0
IL_006b: stloc V_0
IL_006f: ldloca V_0
IL_0073: ldind.i4
IL_0074: brfalse IL_0079
IL_0079: ldc.i4 0x75bcd15
IL_007e: ret
} // end of method Class1::Get
更新:从版本 6.0 开始,Dotfuscator Professional 不再支持 Unity。 (参见 changelog for 6.0.0-beta)。它继续支持 Mono。原答案如下。
是的,Dotfuscator Professional Edition 支持 Mono 和 Unity。您在 IL 中看到差异的原因是专业版提供的 Control Flow 混淆。这与您已从中排除标识符的 重命名 功能不同。
默认情况下,Dotfuscator 在 .NET Framework(即 Microsoft 的实现)上尽可能多地使用控制流转换。 但是,其中一些转换与 Mono 不兼容。 Dotfuscator 提供了一个选项来禁用此类转换。
在 GUI 中加载 Dotfuscator 项目后,可以在 "Advanced" 下的“设置”选项卡上找到此选项,名称为 "Use only Mono-compatible transforms"。将此选项设置为 "Yes",然后保存并重建项目。
如果这仍然给您带来问题,您可以完全禁用控制流以查看是否可以解决问题。这也位于 "Features"、"Disable Control Flow" 下的“设置”选项卡上。将此选项设置为 "Yes",然后保存并重建项目。
完全披露:我在 PreEmptive Solutions 的 Dotfuscator 团队工作。如果您有更多问题,请记住像您这样的评估用户也可以完全访问 PreEmptive 支持。