资源预览内容
第1页 / 共9页
第2页 / 共9页
第3页 / 共9页
第4页 / 共9页
第5页 / 共9页
第6页 / 共9页
第7页 / 共9页
第8页 / 共9页
第9页 / 共9页
亲,该文档总共9页全部预览完了,如果喜欢就下载吧!
资源描述
阻止 Visual Basic .NET 或 C# 代码的反向工程 发布日期: 09/02/2004 | 更新日期: 09/02/2004 Gabriel Torok 和 Bill Leach 本文假设您熟悉 .NET 和 C# 摘要 .NET 体系结构的一个优势是:利用它构建的程序集包含了可以使用 ILDASM 进行 恢复的很多有用的信息以及中间语言反汇编程序。尽管存在一个负面影响,即可以访问您 的二进制文件的人可以恢复与原始源代码非常接近的代码。此处作者提供的程序模糊处理 作为一种阻止反向工程的方法。此外,他们还讨论了可用的不同类型的模糊处理技术,并 说明了包含在 Visual Studio .NET 2003 中的新的模糊处理工具。 到目前为止,您可能已经熟悉了元数据丰富的 Microsoft.NET Framework 体系结构为表 格带来的所有好处,从减轻部署和版本控制的负担到由自说明的二进制文件所启用的丰富 的 IDE 功能。您可能不知道所有元数据的简单可用性已经引入了一个问题,直到目前为 止尚未被大多数开发人员所关注。为通用语言运行时 (CLR) 编写应用程序对于反向工程 来说越来越简单了。在 .NET Framework 中不允许出现任何错误,它仅仅是现成的中间编 译语言(Java 语言应用程序表现出相同的特性) 。Java 和 .NET Framework 都使用嵌入到 可执行代码内部的丰富元数据:在 Java 中为字节代码,在 .NET 中为 Microsoft 中间语 言 (MSIL)。比二进制机器码高级很多的可执行文件包含有可以被轻松破译的信息。 利用像 ILDASM(.NET Framework SDK 附带的 MSIL 反汇编程序)这样的工具或诸如 Anakrino 和 Reflector for .NET 这样的反编译程序,任何人都可以轻松地研究您的程序集 并利用反向工程将它们转换为可读的源代码。黑客可以搜索可利用的安全漏洞、盗取独特 的思想,甚至破解程序。这足以让您犹豫一阵。 但是,请不要担心。有一个解决方案,即模糊处理,它将帮助您防止反向工程。模糊处理 是一种提供程序集中无缝重命名的符号以及阻止反编译程序的其他技巧的技术。正确应用 该技术后,模糊处理可以极大地增加免遭反编译的保护,而使应用程序不受任何损害。模 糊处理通常用于 Java 环境中,很多年来一直用于公司保护基于 Java 的产品的知识产权。 很多第三方根据需要创建了适用于 .NET 代码的模糊处理程序。Microsoft 在与我们公司 PreEmptive Solutions 的合作中将 Dotfuscator Community Edition 包括在 Visual Studio. NET 2003 中,我们的公司提供了多种模糊处理程序包。 使用 Dotfuscator Community Edition,本文将教您有关模糊处理的所有知识(以及一些有关 反编译的知识) 、通常可用的模糊处理类型以及当使用模糊处理程序时您需要注意的一些问题。 要说明反编译和模糊处理,我们将使用一个经典 Vexed 游戏的开放源代码实现。 Vexed.NET 是由 Roey Ben-amotz 编写的,位于 http:/vexeddotnet.benamotz.com。这是一 个智力游戏,您的目标是将相似的块移动到一起,之后它们就会消失。下面就是来自 Vexed.NET 源代码的简单方法: public void undo() if (numOfMoves0) numOfMoves-;if (_UserMoves.Length=2)_UserMoves = _UserMoves.Substring(0, _UserMoves.Length02);this.loadBoard(this.moveHistorynumOfMmoves -(numOfMoves/50) * 50);this.drawBoard(this.gr); 反汇编 .NET Framework SDK 提供的名为 ILDASM 的反汇编实用工具,允许您将 .NET Framework 程序集反编译为 IL 程序集语言语句。为了启动 ILDASM ,您必须确保已安装 了 .NET Framework SDK,并在命令行上键入 ILDASM ,后跟要进行反编译的程序名。在 我们的例子中,将键入“ILDASM vexed.net.exe” 。这将会启动 ILDASM UI ,可以用来浏 览任意基于 .NET Framework 的应用程序的结构。图 1 显示了反汇编的 undo 方法。 返回页首 反编译 如果您现在认为只有那些真正了解 IL 汇编语言的少数人会查看和可以理解您的源代码, 那么请记住反编译并非止步于此。我们可以使用反编译程序重新创建实际的源代码。这些 实用工具可以将 .NET 程序集直接反编译回高级语言,例如 C# 、Visual Basic.NET 或 C+。让我们看一下由 Anakrino 反编译程序生成的 undo 方法: public void undo() if (this.numOfMoves 0) this.numOfMoves = this.numOfMoves - 1;if (this._UserMoves.Length = 2)this._UserMoves = this._UserMoves.Substring(0, this._UserMoves.Length - 2);this.loadBoard(this.moveHistorythis.numOfMoves -this.numOfMoves / 50 * 50); this.drawBoard(this.gr); 正如您所看到的那样,结果几乎与原来的代码相同。稍后,我们将重新回到该示例以查看 在使用模糊处理后的结果。 返回页首 深入模糊处理 模糊处理是使用一套相关的技术完成的。它的目标就是隐藏程序的意图,而不更改其运行 时行为。它并不是加密,但在 .NET 代码的上下文中,它可能会更好。您可以加密 .NET 程序集以使它们完全不可读。但是,这种方法会面临进退两难的局面 因为运行库必须 执行未加密过的代码,而加密密钥必须保存在已加密的程序中。因此,可以创建一个自动 的实用工具来恢复密钥、解密代码,然后将 IL 以其原始的格式写入磁盘。只要发生这种 情况,程序就完全暴露于反编译。 作一个比喻,加密就像将六道菜锁入了一个带锁的盒子中。只有希望进餐的人(在这个例 子中是 CLR )才有钥匙,我们并不想让其他任何人知道他或她想吃什么东西。遗憾的是, 就餐时食物将会被所有旁观者一览无余。模糊处理工作就像是将六道菜放入了搅拌器,然 后将其放入塑料袋送给进餐者。当然,每个人都可以看到传递中的食物,但是除了幸运的 豌豆或者某些牛肉色的糊状物之外,他们并不知道原来的菜到底是什么。进餐者仍然获得 了想要的菜肴,并且菜肴仍然提供了与以前相同的营养价值(幸好,CLR 并不过分挑剔味 道如何) 。模糊处理程序的诀窍就是使观察者糊涂,同时仍然为 CLR 提供相同的产品。 当然,模糊处理(或者加密)并不是百分之百的安全。即使编译的 C+ 也可以被反汇编。 如果黑客足够有耐力,她可以重新生成您的代码。 图 2 模糊处理过程 模糊处理是应用到已编译的 .NET 程序集而不是应用到源代码的过程。模糊处理程序不会 读取或更改您的源代码。图 2 显示了模糊处理过程的流程。模糊处理程序的输出是另外一 套程序集,在功能上与输入的程序集相同,只是改变了阻止反向工程的方式。现在,我们 将考虑 Dotfuscator Community Edition 所使用的两个基本技术来达到该目标:重命名和删 除不必要的元数据。 返回页首 重命名元数据模糊处理的第一道纺线就是使用无意义的名称重命名有意义的名称。正如您所知道的那样, 经过慎重选择的名称有非常大的价值。它们有助于您的代码进行自我说明,并可以作为有 价值的线索来揭示它们所表示项目的目的。CLR 并不介意名称的说明性如何,因此模糊处 理程序可以毫无限制地对它们进行更该,通常将其更改为一个字符的名称,如“a” 。 很明显,对于模糊处理程序可以在某个特殊应用程序上执行重命名的数量,还会有许多限 制。一般而言有三种通用的重命名方案。 如果您的应用程序由一个或多个独立的程序集组成(即,不会有未模糊处理的代码依赖于 任何程序集) ,那么模糊处理程序可以无限制地重命名程序集,无需顾及名称的视觉效果, 只要它们的名称和引用在程序集集合中保持一致即可。WindowsForm 应用程序就是一个 很好的示例。在相反的极端,如果您的应用程序设计为由未模糊处理的代码使用,那么模 糊处理程序无法更改类型的名称或者对那些客户端可见的成员。该类型应用程序的示例是 共享的类库、可重用的组件及其他。在某些位置中间是要插入到现有未模糊处理框架中的 应用程序。在这个例子中,模糊处理程序可以重命名不被模糊处理特定环境(该模糊处理 程序在其中运行)所访问的任意内容,无需考虑可视性。ASP.NET 应用程序是这种类型应 用程序的典型示例。 Dotfuscator Community Edition 使用名为“重载归纳”的专利重命名技术,该技术向重命名 中添加了转换。在彻底的作用域分析后,方法标识符会最大限度的过载。不再使用新的名 称替换每个旧的名称,重载归纳技术使用尽可能多的方法重命名为相同的名称,进而迷惑 试图要理解反编译代码的任何人。 此外,还有一个很好的附带作用,应用程序的大小会由于包含在程序集中字符串堆的减小 而相应的减小。例如,如果您有一个长为 20 个字符的名称,将其重命名为“a”会节省 19 个字符。此外,连续地重用名称会由于保存字符串堆项而节省空间。将所有名称重命名 为“a”意味着“a”仅存储一次,而且重命名为“a”的每个方法或字段都可以指向它。重 载归纳增强了这个效果,因为最短的标识符可以连续地重复使用。通常情况下,一个重载 归纳的项目可以将最多 35 的方法重命名为“a” 。 要查看重命名对反编译代码的影响,请在重命名过程后研究一下 undo 方法: public void c() if (this.p 0) this.p = this.p - 1;if (this.r.Length = 2)this.r = this.r.Substring(0, this.r.Length - 2);this.a(this.qthis.p - this.p / 50 * 50); this.a(this.e); 您可以发现如果没有任何其他种类的模糊处理,这种方法已经非常不容易理解。 返回页首 删除不必要的元数据 并不是在已编译的基于 .NET 的应用程序中的所有元数据都由运行库使用。其中一些由诸 如设计程序、IDE 和调试程序的其他工具使用。例如,如果您在 C# 中的某个类型上定义 了名为“Size”的属性,则编译器会忽略属性名为“Size”的元数据,并且将该名称与实现 get 和 set 操作(分别为“get_Size”和“set_Size” )的方法相关联。当您编写设置 Size 属性的代码时,编译器将始终生成一个对方法“set_Size”本身的调用,并且不会通过其名 称引用该属性。实际上,此处的属性名称用于 IDE 和那些使用您的代码的开发人员;它 不会由 CLR 访问。 如果您的应用程序希望只由运行库使用而不被其他工具使用,则模糊处理程序删除这种类 型的元数据是安全的。除了属性名外,事件名和方法参数名也属于这个类别。当 Dotfuscator Community Edition 认为将所有这些类型的元数据删除安全时,它就会这么做。 返回页首 其他技术 Dotfuscator Community
网站客服QQ:2055934822
金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号