.NET 中的代码安全






4.07/5 (34投票s)
关于代码逆向工程的漏洞,以及修复它们的最佳步骤(包括 DotFuscator)。
引言
安全是 IT 领域每个人的首要关注点之一。当我们谈论安全时,我们通常会想到数据安全。数据是每个公司最重要的部分。我们保护数据,以便不道德的人无法突破安全屏障并获取有价值的信息。在 IT 领域,安全地存储信息是很常见的。因此,我们使用数据库而不是文件来存储数据,以加强数据的安全性。要连接到数据库,我们需要连接字符串 (ConnectionStrings),它们安全地连接数据库并获取数据。这些连接字符串存储在配置文件中,为了额外的安全性,我们使用加密算法来加密我们的数据,这样任何人都无法理解我们的数据。
为了实现安全性,.NET 提供了一些高级类。System.Security
命名空间中的类提供了高质量的库,可以增强任何应用程序的安全性。
但是,我们从未想到的一件事是代码的安全性。代码安全通常比数据安全更重要。通常,当我们处理 .NET 程序集时,我们会将所有安全技术写入其中,从代码中使用我们的安全类,甚至将加密密钥写入业务逻辑中。
众所周知,.NET 是一个生成 **程序集** 的框架,这些程序集类似于 CLR (JIT) 理解的汇编语言代码。因此,汇编代码在运行时编译。因此,任何程序集编辑器都可以通过这个“大门”,轻松发现您的业务逻辑。
背景
对于传统的机器语言,它们很难理解,因为它们是用二进制编写的。但 .NET 程序集并非如此。任何优秀的程序员,甚至新手,都可以从提供的程序集中获取您的业务逻辑。
这将使程序员能够对程序集进行逆向工程,并从中获取实际代码。因此,您为应用程序编写的任何业务逻辑都可能很容易公开。即使您使用了高质量的安全措施来加密所有数据访问,通过对代码进行逆向工程也很容易获取这些信息。
有一些现成的代码生成器,几乎可以生成用于生成程序集的精确代码。例如,我们可以使用 Reflector,它是免费下载的,可以从我们的程序集生成 C#、VB.NET、C++ 或 DELPHI 代码。
在下面的演示中,我将使用 Lutz Roeder's Reflector
项目来反汇编一个类库,稍后,我们将解释如何避免这个问题。从这里获取 Lutz Roeder 的 Reflector。如果找不到,请尝试此链接:下载 Lutz Roeder 的 Reflector - 1.04 MB。
.NET 程序集的问题
让我们开始构建一个简单的类库。让程序集的代码如下所示
using System;
using System.Collections.Generic;
using System.Text;
namespace MyFixedLibrary
{
public class LibraryClass
{
/// <summary>
/// MethodFromFixedLibrary Comments
/// </summary>
public void MethodFromMyFixedLibrary()
{
int myidentifier = 10;
string myString = "This is a String";
for(int i=0;i<myidentifier;i++)
Console.Write(myString);
}
}
}
这是一个简单的代码,介绍了 MyFixedLibrary
命名空间,其中包含一个名为 LibraryClass
的类。LibraryClass
有一个名为 MethodFromFixedLibrary
的方法。
现在,仔细看看标识符的名称。第一个标识符是 myIdentifier
,第二个是 myString
。通常,我们以一种清晰地理解标识符在当前上下文中将做什么的方式来创建标识符。
构建类库后,它会生成一个 DLL。在 Lutz 的 Reflector 中加载 DLL 后,它会通过其逆向工程逻辑生成精确的代码。请看下图
这确实对开发团队构成威胁。反汇编器提供了一些插件,可以生成构成 DLL 的精确解决方案。因此,必须清楚反汇编器如何用于从 .NET 程序集中获取您宝贵的代码。
自己试试看。
如何解决这个问题?
要解决这个问题,我们需要做两个步骤
- 安装软件后,您可以使用 NGen 运行,它将生成本地机器代码并强制 DLL 转换为二进制。
- 使用 Visual Studio .NET 附带的 DotFuscator 和混淆工具。
1. NGEN
要使用 NGEN,您必须编写一个特殊的代码,将您的代码优化为机器语言并将其添加为安装后代码。您还必须随应用程序一起发布 ngen.exe。如果您的应用程序很大,优化代码将需要太长时间才能将 DLL 转换为机器特定代码。这会让用户感到厌烦。
注意:您还可以添加已经本机生成的 DLL。但是,这会导致 DLL 只能在您的平台上运行。这意味着,如果您在 Win XP 中优化了 DLL,它可能会在 Vista 或其他操作系统中引起问题。因此,始终从安装应用程序创建机器代码是一个好习惯。
要了解有关 NGEN 的更多信息,请访问 MSDN。
2. DotFuscator
我们还可以借助混淆工具来编译 DLL,以便使逻辑难以理解。在本节中,我将演示如何使用 DotFuscator 来实现您的目标。步骤如下:
- 首先,在您创建库之后,需要打开 DotFuscator。转到“开始”-“程序”->“Visual Studio .NET”->“Visual Studio Tools”->“Dotfuscator Community Edition”。
- 打开程序集后,您需要对其进行配置,以便可以混淆程序集。在下图中,选择“设置”选项卡用于设置。Configdir 是输出 DLL 的保存位置。
注意:这是社区版,随 Visual Studio .NET 免费提供。您可以轻松购买高级版并获得所有功能。
- 在下一个“选项”选项卡中,对于社区版,只有一个选项是只读的。如果“禁用重命名”设置为“否”,则意味着变量和私有函数将以一种难以理解逻辑的方式重命名。
- 在“输入”选项卡中,选择“库”以使程序集成为库项目。您还可以选择“遵守混淆属性”或“剥离混淆属性”。这些是可选的。
- 在“重命名”选项卡中,您必须选择 Map.xml,它提供 DLL 映射。如果需要额外的 DLL,您可以将信息存储到 XML 文件中。
- “构建”选项卡将帮助您设置输出目录。
注意:关于其他选项卡,社区版不提供。它们仅在高级版中提供。
因此,混淆后,代码将如下所示
using System;
using System.Collections.Generic;
using System.Text;
namespace MyFixedLibrary
{
public class LibraryClass
{
/// <summary>
/// MethodFromFixedLibrary Comments
/// </summary>
public void MethodFromMyFixedLibrary()
{
int num= 10;
string str = "This is a String";
for(int i=0;i<num;i++)
Console.Write(str);
}
}
}
方法名保持不变,但所有私有变量都已重命名。您可以看到 num
已映射到 myidentifier
,str
已映射到 mystring
。
因此,如果您的程序集非常大,更改变量会使反汇编器难以操作。
另外,社区版提供的功能不多。在 DotFuscator 的完整版中,混淆将是广泛的。它可以重命名您的命名空间,甚至字符串。
附加信息(将 DotFuscator 作为生成后事件)
您还可以将混淆添加为项目的生成后自定义事件。为此,您需要创建一个项目文件,这是一个 XML 文档,如下面的示例所示
<?xml version="1.0" encoding="utf-8" standalone="no"?>
<!DOCTYPE dotfuscator SYSTEM
"http://www.preemptive.com/dotfuscator/dtd/dotfuscator_v2.1.dtd">
<dotfuscator version="2.1">
<!--This is application generated code. Do not edit manually.-->
<global />
<input>
<asmlist>
<inputassembly>
<option>library</option>
<file dir="C:\MyFixedLibrary\bin\Debug" name="MyFixedLibrary.dll" />
</inputassembly>
</asmlist>
</input>
<output>
<file dir="C:\ObfuscatedDlls" />
</output>
<tempdir>
<file dir="C:\tempdir" />
</tempdir>
<renaming>
<mapping>
<mapoutput overwrite="false">
<file dir="C:\Mapdir" name="map.xml" />
</mapoutput>
</mapping>
</renaming>
</dotfuscator>
只要您在 DotFuscator 中创建项目,就会自动生成此 XML 文件。在这里,InputAssembly
将保存输入文件程序集,它应该是您的项目目录,Bin/Debug 或 bin/Release,构建的输出将存储在那里。输出目录是混淆后生成的最终 DLL 可用的地方。MapDir 中的 Map.xml 文件是另一个将自动创建并用于记录 DotFuscator 对您的 DLL 所做的一切的 XML 文件。从该文件中,您将获得有关此过程所做的所有函数和变量名称更改的信息。
现在,要包含该事件:转到“项目”->“属性”->“生成事件”,并将这些行添加到生成后事件中
C:\Program Files\PreEmptive Solutions\Dotfuscator
Community Edition 1.1\dotfuscator.exe" /q c:\dproj\demo.xml
请更改 Dotfuscator 文件路径和您创建项目时的项目路径。
历史
这是本文的第一个版本。希望您会喜欢我的文章。