精华内容
下载资源
问答
  • 解决办法:得到你重新签名的组件1的public key token ,然后修改其它引用这个组件反向之后的il文件,把publick key token改成你重新签过名组件1的publick key token。这样问题就解决了。 最后所有问题全部解决,宣告...
    研究Sybase的DataWindow 2.5 在.net上的控件,想把加密点去掉,碰到的几个问题,下面是解决方案。
    第一个问题是就一个组件,解决方法很简单,把public key清掉,或者随即生成SNK签名就可以了

    第二个问题,很多其它.net组件要调用你修改的dll,因为你重新签名后,public key发生了变化,所以其它组件全部不能用了。
    解决办法:得到你重新签名的组件1的public key token ,然后修改其它引用这个组件反向之后的il文件,把publick key token改成你重新签过名组件1的publick key token。这样问题就解决了。


    最后所有问题全部解决,宣告成功!!!
    展开全文
  • 阻止 Visual Basic .NET 或 C# 代码的反向工程- - 摘要 .NET 体系结构的一个优势是:利用它构建的程序集包含了可以使用 ILDASM 进行恢复的很多有用的信息以及中间语言反汇编程序。尽管存在一个负面影响,即...

    阻止 Visual Basic .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 反汇编程序)这样的工具或诸如 AnakrinoReflector 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 (numOfMoves>0) {
        numOfMoves--;
        if (_UserMoves.Length>=2)
            _UserMoves = _UserMoves.Substring(0, _UserMoves.Length02);
        this.loadBoard(this.moveHistory[numOfMmoves -
                          (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.moveHistory[this.numOfMoves -
                   this.numOfMoves / 50 * 50]);
          this.drawBoard(this.gr);
        }
    }
    

    正如您所看到的那样,结果几乎与原来的代码相同。稍后,我们将重新回到该示例以查看在使用模糊处理后的结果。

    深入模糊处理


    模糊处理是使用一套相关的技术完成的。它的目标就是隐藏程序的意图,而不更改其运行时行为。它并不是加密,但在 .NET 代码的上下文中,它可能会更好。您可以加密 .NET 程序集以使它们完全不可读。但是,这种方法会面临进退两难的局面 - 因为运行库必须执行未加密过的代码,而加密密钥必须保存在已加密的程序中。因此,可以创建一个自动的实用工具来恢复密钥、解密代码,然后将 IL 以其原始的格式写入磁盘。只要发生这种情况,程序就完全暴露于反编译。


    作一个比喻,加密就像将六道菜锁入了一个带锁的盒子中。只有希望进餐的人(在这个例子中是 CLR)才有钥匙,我们并不想让其他任何人知道他或她想吃什么东西。遗憾的是,就餐时食物将会被所有旁观者一览无余。模糊处理工作就像是将六道菜放入了搅拌器,然后将其放入塑料袋送给进餐者。当然,每个人都可以看到传递中的食物,但是除了幸运的豌豆或者某些牛肉色的糊状物之外,他们并不知道原来的菜到底是什么。进餐者仍然获得了想要的菜肴,并且菜肴仍然提供了与以前相同的营养价值(幸好,CLR 并不过分挑剔味道如何)。模糊处理程序的诀窍就是使观察者糊涂,同时仍然为 CLR 提供相同的产品。


    当然,模糊处理(或者加密)并不是百分之百的安全。即使编译的 C++ 也可以被反汇编。如果黑客足够有耐力,她可以重新生成您的代码。

    NFissues0311netcodeobfuscationgif02.gif

    模糊处理是应用到已编译的 .NET 程序集而不是应用到源代码的过程。模糊处理程序不会读取或更改您的源代码。图 2显示了模糊处理过程的流程。模糊处理程序的输出是另外一套程序集,在功能上与输入的程序集相同,只是改变了阻止反向工程的方式。现在,我们将考虑 Dotfuscator Community Edition 所使用的两个基本技术来达到该目标:重命名和删除不必要的元数据。

    重命名元数据


     

    模糊处理的第一道纺线就是使用无意义的名称重命名有意义的名称。正如您所知道的那样,经过慎重选择的名称有非常大的价值。它们有助于您的代码进行自我说明,并可以作为有价值的线索来揭示它们所表示项目的目的。CLR 并不介意名称的说明性如何,因此模糊处理程序可以毫无限制地对它们进行更该,通常将其更改为一个字符的名称,如“a”。


     

    很明显,对于模糊处理程序可以在某个特殊应用程序上执行重命名的数量,还会有许多限制。一般而言有三种通用的重命名方案。


     

    如果您的应用程序由一个或多个独立的程序集组成(即,不会有未模糊处理的代码依赖于任何程序集),那么模糊处理程序可以无限制地重命名程序集,无需顾及名称的视觉效果,只要它们的名称和引用在程序集集合中保持一致即可。Windows®Form 应用程序就是一个很好的示例。在相反的极端,如果您的应用程序设计为由未模糊处理的代码使用,那么模糊处理程序无法更改类型的名称或者对那些客户端可见的成员。该类型应用程序的示例是共享的类库、可重用的组件及其他。在某些位置中间是要插入到现有未模糊处理框架中的应用程序。在这个例子中,模糊处理程序可以重命名不被模糊处理特定环境(该模糊处理程序在其中运行)所访问的任意内容,无需考虑可视性。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.q[this.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 Edition 使用我们刚刚介绍的技术提供了很好的模糊处理,但是您应该注意到提供更强保护的其他模糊处理技术,可能会一起阻止反向工程。Dotfuscator Professional Edition 实现了很多其他的技术,包括控制流模糊处理、字符串加密、增量模糊处理和大小减小等。


     

    控制流是一种强大的模糊处理技术,其目标就是隐藏指令结果的目的,而不更改逻辑。更重要的是,它用于删除反编译程序要查找以忠实地重新生成高级源代码语句(例如,if-then-else 语句和循环)的线索。实际上,这种技术趋向于终止反编译程序。


     

    要查看该操作的效果,请在应用重命名和控制流模糊处理后,再次查看反编译的 undo 方法(请参阅图 3)。您可以看到,取代了原来的嵌套 if 语句,反编译程序生成了一个 if 语句、两个嵌套 while 循环,以及将它们全部联系在一起的一些 goto。引用了标签 i1,但它不是由反编译程序生成的(我们认为这是一个反编译程序的错误)。


     

    字符串加密是一项将简单的加密算法应用于嵌入到应用程序中的字符文字的技术。如前所述,在运行时执行的任何加密(或者尤其是解密)本质上就是不安全的。也就是说,聪明的黑客可以最终破解它,但对于应用程序代码中的字符串,这是值得的。让我们面对它,如果黑客要进入您的代码,他们不会盲目地开始搜索重命名的类型。他们可能确实要搜索“Invalid License Key”,这将他们正好引导到执行许可证处理所在的代码。在字符串中进行搜索出乎意料的简单;字符串加密建立起障碍,因为加密的版本只出现在编译后的代码中。


     

    增量模糊处理帮助在模糊处理的局面下发布修补程序以修复客户的问题。修复代码中的错误通常会创建或删除类、方法或字段。更改代码(例如添加或删除方法)可能会引起随后的模糊处理运行重命名事务稍微有所不同。在前面称为“a”的事务现在可能称为“b”。遗憾的是,重命名不同的方式和不同的内容都是一个谜。


     

    增量模糊处理可以解决这个问题。模糊处理程序创建一个映射文件来通知您它是如何执行重命名的。但是,这个相同的映射文件可以在随后的运行中用作模糊处理程序的输入,从而规定以前使用的重命名应该尽可能的再次使用。如果您发布您的产品,然后为一些类推出修补程序,则模糊处理程序可以以这种方式运行以模拟它以前的重命名架构。这样,您可以只为客户发行已修补的类。


     

    大小减小并不严格阻止反向工程,但它值得讨论,因为模糊处理程序几乎始终必须在输入程序集集合上执行依赖性分析。这样该模糊处理程序就能够很好地进行模糊处理,并且一些更好的模糊处理程序将使用其对应用程序的了解来删除程序不使用的代码。将不使用的代码删除看起来有些多余,但它确实能够实现一定目的 - 不是有些人并不使用自己编写的代码吗?好了,这就是我们所有的回答。还有,我们所使用的库和类都是由其他人针对重复使用而编写的。


     

    重复使用的代码表示可以处理许多情况的临时代码;但是,对于任意给定的应用程序,通常情况下您只使用这些情况中的一个或两个。高级的模糊处理程序可以确定这一点,并且可以剥离所有不使用的代码(同样,从编译后的程序集中,而不是从源代码中)。结果是输出精确地包含应用程序所需要的类型和方法 - 一点儿多余的都没有。较小应用程序的好处是节省计算资源和减少加载时间。对于在 .NET Compact Framework 或分布式应用程序上运行的应用程序来说,这可能尤其重要。

    使用 Dotfuscator Community Edition


     

    现在,让我们使用 Dotfuscator Community Edition 来模糊处理 Vexed 应用程序。Dotfuscator Community Edition 使用为特殊应用程序指定模糊处理设置的配置文件。它具有 GUI,可以帮助您简单地创建和维护配置文件以及运行模糊处理程序并检查输出。此外,Dotfuscator Community Edition 的命令行界面使您可以轻松地将模糊处理集成到自动化的构建过程中。您可以从 Visual Studio .NET 2003 的工具菜单中启动 GUI。


     

    要为进行模糊处理配置 Vexed,您需要在 Dotfuscator Community Edition GUI 中指定三个项目:输入程序集、映射文件位置和输出目录。在“Trigger”选项卡上指定输入程序集(模糊处理程序将这些称为“触发程序集”)。您可以在此处添加任意多个,但是对于 Vexed 应用程序,您只需添加一个。


     

    在“Rename | Options”选项卡上指定映射文件位置(请参阅图 4)。映射文件是基本的信息块,包含原始和未模糊处理名称之间明确的名称映射。在模糊处理应用程序后保存该文件是非常重要的,如果没有它,您将无法简单地排解模糊处理应用程序的问题。由于其重要性,在默认情况下,模糊处理程序将不会覆盖现有的映射文件,除非您明确选中“Overwrite Map file”复选框。


     

    最后,“Build”选项卡使您可以指定要放置模糊处理应用程序的目录。完成这个操作后,您就可以开始模糊处理应用程序了。您可以保存您的配置文件以便将来使用,然后按下“Build”选项卡上的“Build”按钮或使用工具栏上的“Play”按钮。在构建过程中,模糊处理程序会在 GUI 的输出窗格中显示进度信息。您可以通过在“Options”选项卡上选择“Quiet”或“Verbose”来控制在此处显示的信息量。


     

    构建完成后,您可以在“Output”选项卡上浏览结果,如图 5 所示。正如您所看到的那样,模糊处理程序显示应用程序的图形视图,类似于对象浏览器。新名称立即出现在视图中原始名称的下面。在该图表中,您可以看到名为“board”的类重命名为“h”,并且带有不同签名(init 和 ToImage)的两个方法都重命名为“a”。

    检查映射文件


     

    Dotfuscator 所产生的映射文件是 XML 格式的文件,除了已经提到的名称映射外,它还包含有关重命名过程效率的一些统计。图 6 总结了模糊处理 Vexed 应用程序后类型和方法的统计。


     

    映射文件也用于执行增量模糊处理。该过程使您可以从以前的运行中导入名称,这会通知模糊处理程序以它以前执行的相同方式进行重命名。如果您为已经模糊处理后的应用程序发布一个修补程序(或者新的插件),您可以使用与原始版本相同的名称集合来模糊处理更新。对于维护多个相互依赖应用程序的企业开发团队来说,这尤其有用。

    模糊处理程序缺陷


     

    在复杂的应用程序中,需要慎重对待模糊处理(尤其是重命名),它对正确的配置非常敏感。如果您不小心,模糊处理程序可能会破坏您的应用程序。在本部分中,我们将讨论当使用模糊处理程序时可能会出现的十分常见的问题。


     

    首先,当应用程序包括强命名的程序集时,您需要做更多的工作。强命名的程序集是经过数字签名的,允许运行库确定在签名后程序集是否已经更改。该签名是一个 SHA1 哈希,该哈希签有 RSA 公钥/私钥对的私钥。签名和公钥都嵌入到程序集的元数据中。由于模糊处理程序修改了程序集,在模糊处理后进行签名很重要。在开发过程中和进行模糊处理之前,应该延迟签名该程序集,然后在模糊处理后完成签名过程。有关延迟签名程序集的更多详细信息,请参阅 .NET Framework 文档,并且记住在测试延迟签名的程序集时关闭强名称验证。


     

    使用 Reflection API 和动态类加载也会使模糊处理过程复杂化。因为这些功能是动态的,所以它们趋向于取代由大多数模糊处理程序使用的静态分析技术。请考虑下面的 C# 代码片段,它按名称获得一个类型并动态对其进行实例化,将类型转换返回到接口:

    public MyInterface GetNewType() {
        Type type = Type.GetType( GetUserInputString(), true );
        object newInstance = Activator.CreateInstance( type );
        return newInstance as MyInterface;
    }
    


     

    类型的名称来自于另一个方法。GetUserInputString 可能会要求用户输入字符串,或者可能从数据库中检索字符串。任意一种方法中,类型名称都没有出现在用于恢复的静态分析的代码中,因此无法知道输入程序集中的哪个类型可能会以这种方式进行实例化。这个例子的解决方案就是防止实现 MyInterface 的所有潜在可加载的类型进行重命名(请注意,仍然可以执行方法和字段重命名)。这就是手动配置和了解进行模糊处理的应用程序扮演重要角色的原因所在。Dotfuscator Community Edition 为您提供了防止重命名选择类型、方法或字段的工具。您可以选择独立的名称;另外,您还可以使用正则表达式和其他标准(例如在作用域上的可视性)来编写排除规则。例如,您可以排除所有公共方法使其避免重命名。


     

    使用模糊处理程序的另一个问题发生在部署已模糊处理的应用程序之后,并试图支持它时。假设您的应用程序引发一个异常(这甚至会发生到我们最优秀的人身上),客户向您发送了如下所示的堆栈转储:

    System.Exception: A serious error has occurred
       at cv.a()
       at cv..ctor(Hashtable A_0)
       at ar.a(di A_0)
       at ae.a(String[] A_0)
    

    很明显,这比从未模糊处理程序中进行堆栈转储所得到的信息要少得多。好消息就是您可以使用在模糊处理过程中生成的映射文件来将堆栈跟踪解码回原始符号。坏消息就是有时在堆栈跟踪中没有足够的信息来明确地从映射文件中检索原始符号。例如,转储中忽略方法返回类型的通知。在利用增强的重载归纳重命名算法模糊处理的应用程序中,只有由返回类型区别的方法可能被重命名为相同的名称。因此,堆栈跟踪是模糊的。在大多数情况下,您可以使可能性变得足够小,这样就会以很高的确定性发现原始名称。为此,Dotfuscator Professional 提供了一个工具来自动将堆栈跟踪转换回原始的有问题的方法。

    小结


     

    您不需要让黑客为了不可告人的目的在您的应用程序中使用手头的 ILDASM 实用工具。您可以使用很好的模糊处理程序来保护您的代码。模糊处理产生了反向工程的障碍。在 Visual Studio .NET 2003 框中,Dotfuscator Community Edition 可以只通过几次单击就能够完成很好的模糊处理。

    相关文章,请参阅:
    Inside Microsoft .NET IL Assembler,作者是 Serge Lidin (Microsoft Press, 2002)
    Dotfuscator FAQ
    有关背景信息,请参阅:
    Ildasm.exeTutorial
    Anakrino
    http://vexeddotnet.benamotz.com
    http://www.preemptive.com

    Gabriel Torok 是 PreEmptive Solutions 的总裁。他是 JavaScript Primer PlusJava Primer Plus 的作者之一,这两本书都是由 Macmillan 出版的。Gabriel 已经在全世界很多软件开发研讨会上做了很多报告并提供了教程。

    Bill Leach 是 PreEmptive Solutions 的首席技术官。他是模糊处理程序产品线的架构师和技术领导。Bill 曾经做过软件开发书籍和文章的技术审查人员。

    摘自 MSDN Magazine2003 年 11 月刊。

    - 作者: Beautifully 2004年09月13日, 星期一 21:14

    转载于:https://www.cnblogs.com/walkingboy/archive/2005/03/28/127016.html

    展开全文
  • 反转 逆向工程tuya固件的工具集 我不了解逆向工程,但是也许这可以帮助知道他们在做什么的人。 image1M.bin来自: : 工作汇编: 用法 使用以下命令克隆代码:git clone --recursive 运行start.sh
  • 高级语言源程序经过 编译 变成可执行文件,反编译就是逆过程。 但是通常不能把可执行文件变成高级语言源代码,只能... 计算机软件反向工程(Reversepengineering)也称为计算机软件还原工程,是指通过对他人..共1次编辑
  • C# 代码进行反向工程 发布日期 : 12/28/2004 | 更新日期 : 12/28/2004 Gabriel Torok和 Bill Leach 本文假设您熟悉 .NET 与 C# 摘要 .NET 体系结构的优势之一在于,利用该体系结构构建的程序集包含很多有用的信息,...

    防止对 Visual Basic .NET 或 C# 代码进行反向工程

    发布日期 : 12/28/2004 | 更新日期 : 12/28/2004

    Gabriel TorokBill Leach

    本文假设您熟悉 .NET 与 C#

    摘要

    .NET 体系结构的优势之一在于,利用该体系结构构建的程序集包含很多有用的信息,使用中间语言反汇编程序 ILDASM 即可恢复这些信息。但是这样会带来另一个问题,就是可以访问您的二进制代码的人能够以非常近似的手段恢复原始源代码。作者将在文中介绍程序模糊处理,该处理可作为一种阻止反相工程的手段。此外,他们还将讨论可用的不同类型的模糊处理技术,并示范 Visual Studio .NET 2003 中包含的新模糊处理工具。

    本页内容

    反汇编反汇编
    反编译反编译
    深入了解模糊处理深入了解模糊处理
    重命名元数据重命名元数据
    删除非基本元数据删除非基本元数据
    其他技术其他技术
    使用 Dotfuscator Community Edition使用 Dotfuscator Community Edition
    检查映射文件检查映射文件
    模糊处理程序的缺陷模糊处理程序的缺陷
    小结小结

    迄今为止,从减轻部署和版本控制的负担,到自描述二进制数据所实现的丰富 IDE 功能,您可能已经熟悉了这些元数据丰富的 Microsoft® .NET Framework 体系结构带来的所有好处。您可能不知道元数据的这种易用性带来的一个目前对于大多数开发人员来说还没有注意到的问题。为公共语言运行库 (CLR) 编写的程序更易于进行反相工程。不管怎么说,这并不是 .NET Framework 设计中的缺陷;它只是一种现代的、中间编译语言(Java 语言应用程序具有同样的特征)的现实状况。Java 和 .NET Framework 都使用内嵌在可执行代码中的丰富元数据:在 Java 中是字节码,在 .NET 中是 Microsoft 中间语言 (MSIL)。由于比二进制机器码要高级很多,可执行文件充满了可以轻松破解的信息。

    借助于诸如 ILDASM 这样的工具(随同 .NET Framework SDK 一同发布的 MSIL 反汇编程序)或者类似于 AnakrinoReflector for .NET 这样的反汇编程序,任何人都可以轻松地查看您的程序集并将其反相工程为可读的源代码。黑客可以搜索安全缺陷,以探究、窃取独特的创意并破译程序。这足以使您犹豫不决。

    尽管如此,请不必担心。有一种模糊处理解决方案可帮助您防止反相工程。模糊处理是为程序集中的符号提供无缝重命名的一项技术,它还提供了其他技巧以阻止反汇编程序。如果运用适当,模糊处理可以大幅度提升应用程序防止反相工程的能力,同时保持应用程序的完整无缺。模糊处理技术通常用于 Java 环境中,多年来已帮助了众多公司保护他们的基于 Java 技术产品的知识产权。

    现在已有多家第三方通过创建 .NET代码的模糊处理程序来予以响应。通过与我们公司 PreEmptive Solutions 合作,Microsoft 在 Visual Studio?.NET 2003 中包含了 Dotfuscator Community Edition,而 PreEmptive Solutions 也推出了多种模糊处理程序软件包。

    通过使用 Dotfuscator Community Edition,本文将向您讲授与模糊处理有关的所有内容(同时简要介绍一下反汇编)、通常可用的模糊处理的类型以及利用模糊处理程序工作时需要解决的一些问题。

    为演示反编译和模糊处理,我们将使用经典的 Vexed 游戏的一个开放源代码实现。Vexed.NET 由 Roey Ben-amotz 编写,可从 http://vexeddotnet.benamotz.com 获得。这是一个益智类游戏,您的目标就是将相似的块移到一起,从而使它们消失。下面是Vexed.NET 源代码中的一个简单方法:

    public void undo() {
      if (numOfMoves>0) {
        numOfMoves--;
        if (_UserMoves.Length>=2)
            _UserMoves = _UserMoves.Substring(0, _UserMoves.Length02);
        this.loadBoard(this.moveHistory[numOfMmoves -
                          (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.moveHistory[this.numOfMoves -
                   this.numOfMoves / 50 * 50]);
          this.drawBoard(this.gr);
        }
    }
    

    您可以看到,结果几乎与原始代码完全相同。稍后,我们将回到这里来查看经过模糊处理后的结果。

    返回页首

    深入了解模糊处理

    模糊处理是使用一组相关技术来实现的。模糊处理的目的是隐藏程序的意图而又不改变其运行时行为。它不是加密,但对于 .NET 代码而言,它比加密可能更胜一筹。您可以加密 .NET 程序集,使它们完全不可读。但是,该方法会造成一个典型的进退两难的局面,这是因为运行库必须执行未加密代码,解密密钥必须与已加密程序保存在一起。因此,可创建一个自动化的实用工具来恢复密钥、解密代码,然后以 IL 的原始形式将其写到磁盘上。一旦发生这种情况,程序就完全暴露在反编译之下了。

    我们可以将加密比作是将包含六道菜的套餐锁到箱子里。只有预定的用餐者(在本例中为 CLR)才有钥匙,而且我们不想让任何其他人知道他或她将要吃什么。遗憾的是,到了用餐时间所有食物将完全处于众目睽睽之下。模糊处理工作更像将包含六道菜的套餐放到一个搅拌机中,然后将它放到一个塑料袋中送给用餐者。当然,每个人都可以看到正在递送的食物,但是除了碰巧可以看到一颗完整的豌豆或一些牛肉色的粘糊东西之外,他们并不知道原来的食物是什么。用餐者仍然获得了他想要的东西,而且这次用餐仍然提供了与以前一样的营养价值(幸运的是,CLR 对口味并不挑剔)。模糊处理程序的窍门就是把窥探者搞糊涂,同时该程序仍然能向 CLR 提交同样的产品。

    当然,模糊处理(或加密)并不是百分之百地坚不可摧。即使编译后的 C++ 也可能被反汇编。如果黑客坚持不懈,他就可以重新产生您的代码。

    图 2 模糊处理过程

    模糊处理是一个应用于编译后的 .NET 程序集而不是源代码的过程。模糊处理程序决不会读取或更改您的源代码。图 2 显示了模糊处理过程的流程。模糊处理程序的输出是另一组程序集,功能上与输入程序集等同,但是该程序以一种阻碍反相工程的方式进行了转换。现在我们将讨论 Dotfuscator Community Edition 用来实现该目标所使用的两项基本技术:重命名和删除非基本元数据。

    返回页首

    重命名元数据

    模糊处理的第一道防线就是将有意义的名称重命名为一个无意义的名称。如您所知,从精心选择的名称中可得出许多有价值的线索。它们有助于使您的代码自我文档化,并充当了揭示它们所表示的项目的有价值的线索。CLR 不关心一个名称的描述性如何,因此模糊处理程序可以自由地修改这些名称,通常是修改为类似于“a”这样的单字符名称。

    显然,模糊处理程序对一个特定程序所能执行的重命名次数是有限制的。通常来说,有三种常见的重命名方案。

    如果您的应用程序由一个或多个独立的程序集组成(即未模糊处理的代码不依赖于任何程序集),那么模糊处理程序可以自由地对程序集进行重命名,而无论名称的可见性如何,只要名称和对名称的引用在程序集组中是一致的。Windows 窗体应用程序就是一个很好的例子。作为一个反面的极端例子,如果您的应用程序设计目的就是供未经过模糊处理的代码使用,那么模糊处理程序将无法更改那些对客户可见的类型或成员的名称。这种类型的应用程序的例子,包括共享类库、可重用组件等诸如此类的东西。位于二者之间的是那些打算插到现有的未做模糊处理的框架中的应用程序。在这种情况下,模糊处理程序可以对它运行时所在的环境不访问的任何东西进行重命名,不管可见性如何。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.q[this.p - this.p / 50 * 50]);
            this.a(this.e);
        }
    }
    

    您可以看出来,在没有经过任何模糊处理,这个方法就已经比较难于理解了。

    返回页首

    删除非基本元数据

    在编译过的、基于 .NET 的应用程序中,并非所有的元数据在运行时都会得到使用。其中的一些数据将由其他工具使用(例如,设计器、IDE和调试器)。例如,如果您在 C# 中的类型上定义了一个名为“Size”的属性,则编译器将省略属性名“Size”的元数据,并将该名称与实现 get 和 set 操作的那些方法关联起来(它们被分别命名为“get_Size”和“set_Size”)。当您开始编写设置 Size 属性的代码时,编译器将始终生成一个对方法“size-Size”本身的调用,并且决不会通过其名称引用该属性。事实上,属性的名称供 IDE 和使用您的代码的开发人员使用;CLR 从不访问它。

    如果只是由运行库而不是其他工具使用您的应用程序,那么模糊处理程序删除这种类型的元数据就是安全的。除了属性名,事件名和方法参数名也在这个范畴之列。Dotfuscator Community Edition 在它认为这样做安全时会删除所有这些类型的元数据。

    返回页首

    其他技术

    Dotfuscator Community Edition 使用我们刚刚介绍的技术来提供良好的模糊处理,但是您应该知道模糊处理技术在提供更为强大的保护的同时,可能还会阻止反相工程的进行。Dotfuscator Professional Edition 实现了很多其他技术,其中包括控制流模糊处理、字符串加密、增量模糊处理和规模降低。

    控制流是一种强大的模糊处理技术,它的目的是隐藏一系列指令的意图而又不会更改逻辑。更为重要的是,它可用来删除反编译程序为了忠实重现高级源代码语句(比如 if-then-else 语句和循环)而寻找的那些线索。事实上,这项技术试图破坏反汇编程序的工作。

    要查看运行效果,在运用重命名和控制流模糊处理后,再次研究反编译后的undo方法(请参见图 3)。您可以看到反汇编程序并没有生成原始的嵌套 if 语句,而是生成了一个 if 语句、两个嵌套 while 循环和一些将其捆绑在一起的 goto。标签 i1 被引用了,但它不是由反编译程序生成的(我们假定它是一个反编译程序错误)。

    字符串加密是一种将简单加密算法应用到嵌入您的应用程序中的字符串的技术。如上所述,在运行时执行的任何加密(或特殊情况下的解密)从根本上讲都是不安全的。也就是说,技术高超的黑客事实上是可以破解它的,但对于应用程序代码中的字符串而言,这样做是值得的。我们所面对的事实是,如果黑客希望进入您的代码,那么他们不会盲目地开始搜索已重命名的类型。他们可能确实会搜索“无效许可证密钥”,这会将他们直接引导到执行许可证处理的代码。对字符串进行搜索非常简单;字符串加密设置有保护,这是因为在编译的密码中只存在加密的版本。

    增量模糊处理有助于发布修补程序来解决客户在面对模糊处理时碰到的问题。修复代码中的错误时经常会创建或删除类、方法或字段。更改代码(例如,添加或删除某个方法)可能会导致随后的模糊处理运行,从而使事物的重命名稍有不同。先前称为“a”的名称现在可能称为“b”。遗憾的是,如何不同地进行重命名和不同地重命名哪些内容却不容易弄清楚。

    增量模糊处理可以解决这一问题。Dotfuscator 将创建一个映射文件以告知您它是如何执行重命名的。但是,这个映射文件在随后的运行中同样可用作对 Dotfuscator 的输入,以指示先前使用的重命名应在任何可能的地方再次使用。如果发布您的产品,然后修补一些类,Dotfuscator 就会以一种模仿其先前重命名方案的方式运行。这样,您就可以只将修补过的类发布给您的客户。

    减小规模不会严格地阻止反相工程,但这里仍值得提一提,因为模糊处理程序几乎始终必须要在输入程序集上执行依赖性分析。因此,模糊处理程序不仅可以很好地进行模糊处理,更好的是,它还可以利用对您的应用程序的了解来删除您的程序没有使用的代码。看起来有点奇怪,实际上,删除未使用的代码非常容易,那么,是谁编写了这些不使用的代码呢?答案是,我们所有的人。此外,我们都使用其他人编写的、可重用的库和类型。

    可重用代码意味着存在一些可处理许多用例的随附代码;但在任何给定的应用程序中,您通常只使用这些众多用例中的一种或两种。高级模糊处理程序可以确定这一点并删除所有未使用的代码(而且,是从已编译的程序集而非源文件中删除)。结果是,输出中所包含的正是您的应用程序不再需要的类型和方法。较小的应用程序具有节省计算资源和缩短加载时间等好处。这些好处对于在 .NET Compact Framework 上运行的应用程序或分布式应用程序尤为重要。

    返回页首

    使用 Dotfuscator Community Edition

    现在让我们使用 Dotfuscator Community Edition 来模糊处理 Vexed 应用程序。Dotfuscator Community Edition 使用一个配置文件来指定特定应用程序的模糊处理设置。它让一个 GUI 来帮助您轻松创建和维护配置文件,以及运行模糊处理程序并检查输出。此外,Dotfuscator Community Edition 的命令行界面允许您将模糊处理轻松集成到您自动生成过程中。您可以从 Visual Studio .NET 2003 的工具菜单直接启动 GUI。

    要配置 Vexed 以进行模糊处理,您需要在 Dotfuscator Community Edition GUI 中指定 3 项:输入程序集、映射文件位置和输出目录。输入程序集(Dotfuscator 称之为“触发器程序集”)在 Trigger 选项卡上指定。您可以在这里根据所需添加任意多的程序集,但对 Vexed 应用程序来说只需要一个。

    在“Rename | Options”选项卡上指定映射文件的位置(请参见图 4)。映射文件中含有原始名称和被模糊处理名称之间的明确名称映射,这些信息至关重要。重要的一点是,对应用程序进行模糊处理后,要保存该文件;如果没有它,您就不能轻松地对模糊处理过的应用程序进行查错。由于其重要性,Dotfuscator 在默认情况下不会改写现有映射文件,除非您显式地选中 "Overwrite Map file" 框。

    最后,“Build”选项卡允许您指定放置经过模糊处理的应用程序的目录。完成上述工作后,就可以对应用程序进行模糊处理了。您可以保存配置文件以备后用,然后可以在“Build”选项卡上按“Build”按钮,或在工具栏上使用“Play”按钮。在构建时,Dotfuscator 会在 GUI 的输出窗格中显示进度信息。在“Options”选项卡上选择 Quiet 或者 Verbose,可以控制在这里显示的信息量。

    一旦完成生成,您就可以在 Output 选项卡上浏览结果,如图 5 所示。如您所见,Dotfuscator 显示了一个与对象浏览器类似的应用程序图形视图。新名称位于视图中原始名称的正下方。在此图中,您会看到名为“board”的类被重命名为“h”,具有不同签名的两个方法(init 和 ToImage)都被重命名为“a”。

    返回页首

    检查映射文件

    Dotfuscator 生成的映射文件是一种 XML 格式的文件,这种文件除包含上述名称映射外,还包含一些统计数据,这些数据指出重命名过程的有效性。图 6 汇总了对 Vexed 应用程序进行模糊处理后类型和方法的统计。

    映射文件还被用于执行增量模糊处理。此过程允许您从以前的运行中导入名称,这样会通知模糊处理程序采用与以前同样的方式来执行重命名。如果为一个经模糊处理的应用程序发布修补程序(或新插件),您可以使用与原始版本相同的名称集对更新程序进行模糊处理。这对维护多个相互依赖的应用程序的企业开发小组特别有用。

    返回页首

    模糊处理程序的缺陷

    有关复杂应用程序的模糊处理(特别是重命名)比较棘手,它对正确配置高度敏感。如果不慎,模糊处理程序就会中断您的应用程序。在本部分中,我们将讨论一些使用模糊处理程序时可能出现的常见问题。

    首先,如果您的应用程序包含强名称程序集,则您需要多做一些工作。强名称程序集是经过数字签名的,允许运行库确定是否已在签名后改变了程序集。签名是一个利用 RSA 公钥/私钥对的私钥签名的 SHA1 哈希值。此签名和公钥都被嵌入到程序集的元数据中。因为模糊处理程序将修改程序,所以在模糊处理后进行签名非常重要。在开发过程中和进行模糊处理之前,您应该对程序集延迟签名,然后完成签名过程。有关延迟签名程序集的详细信息,请参阅 .NET Framework 文档。请记住,在测试延迟签名的程序集时,关闭强名称验证。

    使用 Reflection API 和动态类加载还将增加模糊过程的复杂性。由于这些实用程序是动态的,所以它们优于大多数模糊处理程序使用的静态分析。请考虑下列 C# 代码片段,该代码片段按名称获取类型并动态地将其实例化,然后将类型转换返回给接口:

    public MyInterface GetNewType() {
        Type type = Type.GetType( GetUserInputString(), true );
        object newInstance = Activator.CreateInstance( type );
        return newInstance as MyInterface;
    }
    

    类型的名称来自另一个方法。GetUserInputString 可能要求用户输入一个字符串,也可能从数据库中检索一个字符串。不论采用哪种方式,代码中都不显示静态分析可恢复的类型名称,因此,无法了解输入程序集中的哪些类型可能会采用此方式来进行实例化。在此情况下采用的解决方案是防止对实现 MyInterface 的所有潜在的可加载类型进行重命名(请注意,仍可以执行方法和字段重命名)。因此,手动配置和掌握一些有关要进行模糊处理的应用程序的知识在这里非常重要。Dotfuscator Community Edition 为您提供了多种工具来防止对所选类型、方法或字段进行重命名。您可以挑选和选择独特的名称;或者,您可以使用正则表达式和其他标准(例如作用域的可见性)来编写排除规则。例如,您可以将所有的公共方法排除在重命名之外。

    在您已部署了一个经模糊处理的应用程序并尝试支持它时,使用模糊处理程序会产生另一个问题。假定应用程序将抛出一个异常(对大多数人而言,都会发生该情形)并且客户向您发送如下的堆栈转储:

    System.Exception: A serious error has occurred
       at cv.a()
       at cv..ctor(Hashtable A_0)
       at ar.a(di A_0)
       at ae.a(String[] A_0)
    

    显然,上述堆栈转储所含的信息少于来自未模糊处理的程序所含的信息。好的方面是,您可以使用模糊处理期间生成的映射文件将堆栈跟踪解码回原始代码。坏的方面是,堆栈跟踪中的消息有时不足以明确地从映射文件中检索出原始符号。例如,请注意在转储中省略了方法返回类型。在用增强的重载归纳重命名算法模糊处理的应用程序中,或许只有返回类型不同的方法才会被重命名为相同的名称。因此,堆栈跟踪可能是任意的。在大多数情况下,您可以缩小检索范围,以便更有把握找到原始名称。要获得帮助,Dotfuscator Professional 为您提供了一个工具以自动将堆栈跟踪转换回不招人喜欢的原始方法。

    返回页首

    小结

    您可以防止黑客使用随处可得的 ILDASM 实用程序对您的应用程序进行恶意处理。您可以用模糊处理程序来保护代码。模糊处理可以有效阻止反相工程。使用 Visual Studio .NET 2003 产品中提供的 Dotfuscator Community Edition,只需点击几下鼠标即可进行良好的模糊处理。

    有关文章,请参阅
    Inside Microsoft .NET IL Assembler by Serge Lidin (Microsoft Press, 2002)
    Dotfuscator FAQ
    有关背景信息,请参阅
    Ildasm.exe Tutorial
    Anakrino
    http://vexeddotnet.benamotz.com
    http://www.preemptive.com

    Gabriel Torok 是 PreEmptive Solutions 的总裁。他与别人合著有 JavaScript Primer PlusJava Primer Plus,这两本书均由 Macmillan 出版。Gabriel 在世界各地的开发会议上发表演讲并讲授课程。

    Bill Leach 是 PreEmptive Solutions 的首席技术官。他是 Dotfuscator 产品线的架构师和技术主管。Bill 还担任了软件开发书籍和文章的技术评论。

    转载于:https://www.cnblogs.com/HappyQQ/archive/2008/04/13/1151294.html

    展开全文
  • 摘要 .NET 体系结构的一个优势是:利用它构建的...此处作者提供的程序模糊处理作为一种阻止反向工程的方法。此外,他们还讨论了可用的不同类型的模糊处理技术,并说明了包含在 Visual Studio .NET 2003 中的新的模糊处
    摘要 .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 反汇编程序)这样的工具或诸如 AnakrinoReflector 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 (numOfMoves>0) {
        numOfMoves--;
        if (_UserMoves.Length>=2)
            _UserMoves = _UserMoves.Substring(0, _UserMoves.Length02);
        this.loadBoard(this.moveHistory[numOfMmoves -
                          (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 的应用程序的结构。

     

    反编译


    如果您现在认为只有那些真正了解 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.moveHistory[this.numOfMoves -
                   this.numOfMoves / 50 * 50]);
          this.drawBoard(this.gr);
        }
    }
    

    正如您所看到的那样,结果几乎与原来的代码相同。稍后,我们将重新回到该示例以查看在使用模糊处理后的结果。

     

    深入模糊处理


    模糊处理是使用一套相关的技术完成的。它的目标就是隐藏程序的意图,而不更改其运行时行为。它并不是加密,但在 .NET 代码的上下文中,它可能会更好。您可以加密 .NET 程序集以使它们完全不可读。但是,这种方法会面临进退两难的局面 - 因为运行库必须执行未加密过的代码,而加密密钥必须保存在已加密的程序中。因此,可以创建一个自动的实用工具来恢复密钥、解密代码,然后将 IL 以其原始的格式写入磁盘。只要发生这种情况,程序就完全暴露于反编译。


    作一个比喻,加密就像将六道菜锁入了一个带锁的盒子中。只有希望进餐的人(在这个例子中是 CLR)才有钥匙,我们并不想让其他任何人知道他或她想吃什么东西。遗憾的是,就餐时食物将会被所有旁观者一览无余。模糊处理工作就像是将六道菜放入了搅拌器,然后将其放入塑料袋送给进餐者。当然,每个人都可以看到传递中的食物,但是除了幸运的豌豆或者某些牛肉色的糊状物之外,他们并不知道原来的菜到底是什么。进餐者仍然获得了想要的菜肴,并且菜肴仍然提供了与以前相同的营养价值(幸好,CLR 并不过分挑剔味道如何)。模糊处理程序的诀窍就是使观察者糊涂,同时仍然为 CLR 提供相同的产品。


    当然,模糊处理(或者加密)并不是百分之百的安全。即使编译的 C++ 也可以被反汇编。如果黑客足够有耐力,她可以重新生成您的代码。

    模糊处理是应用到已编译的 .NET 程序集而不是应用到源代码的过程。模糊处理程序不会读取或更改您的源代码。图 2显示了模糊处理过程的流程。模糊处理程序的输出是另外一套程序集,在功能上与输入的程序集相同,只是改变了阻止反向工程的方式。现在,我们将考虑 Dotfuscator Community Edition 所使用的两个基本技术来达到该目标:重命名和删除不必要的元数据。

     

    重命名元数据


     

    模糊处理的第一道纺线就是使用无意义的名称重命名有意义的名称。正如您所知道的那样,经过慎重选择的名称有非常大的价值。它们有助于您的代码进行自我说明,并可以作为有价值的线索来揭示它们所表示项目的目的。CLR 并不介意名称的说明性如何,因此模糊处理程序可以毫无限制地对它们进行更该,通常将其更改为一个字符的名称,如“a”。


     

    很明显,对于模糊处理程序可以在某个特殊应用程序上执行重命名的数量,还会有许多限制。一般而言有三种通用的重命名方案。


     

    如果您的应用程序由一个或多个独立的程序集组成(即,不会有未模糊处理的代码依赖于任何程序集),那么模糊处理程序可以无限制地重命名程序集,无需顾及名称的视觉效果,只要它们的名称和引用在程序集集合中保持一致即可。Windows®Form 应用程序就是一个很好的示例。在相反的极端,如果您的应用程序设计为由未模糊处理的代码使用,那么模糊处理程序无法更改类型的名称或者对那些客户端可见的成员。该类型应用程序的示例是共享的类库、可重用的组件及其他。在某些位置中间是要插入到现有未模糊处理框架中的应用程序。在这个例子中,模糊处理程序可以重命名不被模糊处理特定环境(该模糊处理程序在其中运行)所访问的任意内容,无需考虑可视性。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.q[this.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 Edition 使用我们刚刚介绍的技术提供了很好的模糊处理,但是您应该注意到提供更强保护的其他模糊处理技术,可能会一起阻止反向工程。Dotfuscator Professional Edition 实现了很多其他的技术,包括控制流模糊处理、字符串加密、增量模糊处理和大小减小等。


     

    控制流是一种强大的模糊处理技术,其目标就是隐藏指令结果的目的,而不更改逻辑。更重要的是,它用于删除反编译程序要查找以忠实地重新生成高级源代码语句(例如,if-then-else 语句和循环)的线索。实际上,这种技术趋向于终止反编译程序。


     

    要查看该操作的效果,请在应用重命名和控制流模糊处理后,再次查看反编译的 undo 方法。您可以看到,取代了原来的嵌套 if 语句,反编译程序生成了一个 if 语句、两个嵌套 while 循环,以及将它们全部联系在一起的一些 goto。引用了标签 i1,但它不是由反编译程序生成的(我们认为这是一个反编译程序的错误)。


     

    字符串加密是一项将简单的加密算法应用于嵌入到应用程序中的字符文字的技术。如前所述,在运行时执行的任何加密(或者尤其是解密)本质上就是不安全的。也就是说,聪明的黑客可以最终破解它,但对于应用程序代码中的字符串,这是值得的。让我们面对它,如果黑客要进入您的代码,他们不会盲目地开始搜索重命名的类型。他们可能确实要搜索“Invalid License Key”,这将他们正好引导到执行许可证处理所在的代码。在字符串中进行搜索出乎意料的简单;字符串加密建立起障碍,因为加密的版本只出现在编译后的代码中。


     

    增量模糊处理帮助在模糊处理的局面下发布修补程序以修复客户的问题。修复代码中的错误通常会创建或删除类、方法或字段。更改代码(例如添加或删除方法)可能会引起随后的模糊处理运行重命名事务稍微有所不同。在前面称为“a”的事务现在可能称为“b”。遗憾的是,重命名不同的方式和不同的内容都是一个谜。


     

    增量模糊处理可以解决这个问题。模糊处理程序创建一个映射文件来通知您它是如何执行重命名的。但是,这个相同的映射文件可以在随后的运行中用作模糊处理程序的输入,从而规定以前使用的重命名应该尽可能的再次使用。如果您发布您的产品,然后为一些类推出修补程序,则模糊处理程序可以以这种方式运行以模拟它以前的重命名架构。这样,您可以只为客户发行已修补的类。


     

    大小减小并不严格阻止反向工程,但它值得讨论,因为模糊处理程序几乎始终必须在输入程序集集合上执行依赖性分析。这样该模糊处理程序就能够很好地进行模糊处理,并且一些更好的模糊处理程序将使用其对应用程序的了解来删除程序不使用的代码。将不使用的代码删除看起来有些多余,但它确实能够实现一定目的 - 不是有些人并不使用自己编写的代码吗?好了,这就是我们所有的回答。还有,我们所使用的库和类都是由其他人针对重复使用而编写的。


     

    重复使用的代码表示可以处理许多情况的临时代码;但是,对于任意给定的应用程序,通常情况下您只使用这些情况中的一个或两个。高级的模糊处理程序可以确定这一点,并且可以剥离所有不使用的代码(同样,从编译后的程序集中,而不是从源代码中)。结果是输出精确地包含应用程序所需要的类型和方法 - 一点儿多余的都没有。较小应用程序的好处是节省计算资源和减少加载时间。对于在 .NET Compact Framework 或分布式应用程序上运行的应用程序来说,这可能尤其重要。

     

    使用 Dotfuscator Community Edition


     

    现在,让我们使用 Dotfuscator Community Edition 来模糊处理 Vexed 应用程序。Dotfuscator Community Edition 使用为特殊应用程序指定模糊处理设置的配置文件。它具有 GUI,可以帮助您简单地创建和维护配置文件以及运行模糊处理程序并检查输出。此外,Dotfuscator Community Edition 的命令行界面使您可以轻松地将模糊处理集成到自动化的构建过程中。您可以从 Visual Studio .NET 2003 的工具菜单中启动 GUI。


     

    要为进行模糊处理配置 Vexed,您需要在 Dotfuscator Community Edition GUI 中指定三个项目:输入程序集、映射文件位置和输出目录。在“Trigger”选项卡上指定输入程序集(模糊处理程序将这些称为“触发程序集”)。您可以在此处添加任意多个,但是对于 Vexed 应用程序,您只需添加一个。


     

    在“Rename | Options”选项卡上指定映射文件位置。映射文件是基本的信息块,包含原始和未模糊处理名称之间明确的名称映射。在模糊处理应用程序后保存该文件是非常重要的,如果没有它,您将无法简单地排解模糊处理应用程序的问题。由于其重要性,在默认情况下,模糊处理程序将不会覆盖现有的映射文件,除非您明确选中“Overwrite Map file”复选框。


     

    最后,“Build”选项卡使您可以指定要放置模糊处理应用程序的目录。完成这个操作后,您就可以开始模糊处理应用程序了。您可以保存您的配置文件以便将来使用,然后按下“Build”选项卡上的“Build”按钮或使用工具栏上的“Play”按钮。在构建过程中,模糊处理程序会在 GUI 的输出窗格中显示进度信息。您可以通过在“Options”选项卡上选择“Quiet”或“Verbose”来控制在此处显示的信息量。


     

    构建完成后,您可以在“Output”选项卡上浏览结果。正如您所看到的那样,模糊处理程序显示应用程序的图形视图,类似于对象浏览器。新名称立即出现在视图中原始名称的下面。在该图表中,您可以看到名为“board”的类重命名为“h”,并且带有不同签名(init 和 ToImage)的两个方法都重命名为“a”。

     

    检查映射文件


     

    Dotfuscator 所产生的映射文件是 XML 格式的文件,除了已经提到的名称映射外,它还包含有关重命名过程效率的一些统计。


     

    映射文件也用于执行增量模糊处理。该过程使您可以从以前的运行中导入名称,这会通知模糊处理程序以它以前执行的相同方式进行重命名。如果您为已经模糊处理后的应用程序发布一个修补程序(或者新的插件),您可以使用与原始版本相同的名称集合来模糊处理更新。对于维护多个相互依赖应用程序的企业开发团队来说,这尤其有用。

     

    模糊处理程序缺陷


     

    在复杂的应用程序中,需要慎重对待模糊处理(尤其是重命名),它对正确的配置非常敏感。如果您不小心,模糊处理程序可能会破坏您的应用程序。在本部分中,我们将讨论当使用模糊处理程序时可能会出现的十分常见的问题。


     

    首先,当应用程序包括强命名的程序集时,您需要做更多的工作。强命名的程序集是经过数字签名的,允许运行库确定在签名后程序集是否已经更改。该签名是一个 SHA1 哈希,该哈希签有 RSA 公钥/私钥对的私钥。签名和公钥都嵌入到程序集的元数据中。由于模糊处理程序修改了程序集,在模糊处理后进行签名很重要。在开发过程中和进行模糊处理之前,应该延迟签名该程序集,然后在模糊处理后完成签名过程。有关延迟签名程序集的更多详细信息,请参阅 .NET Framework 文档,并且记住在测试延迟签名的程序集时关闭强名称验证。


     

    使用 Reflection API 和动态类加载也会使模糊处理过程复杂化。因为这些功能是动态的,所以它们趋向于取代由大多数模糊处理程序使用的静态分析技术。请考虑下面的 C# 代码片段,它按名称获得一个类型并动态对其进行实例化,将类型转换返回到接口:

    public MyInterface GetNewType() {
        Type type = Type.GetType( GetUserInputString(), true );
        object newInstance = Activator.CreateInstance( type );
        return newInstance as MyInterface;
    }
    


     

    类型的名称来自于另一个方法。GetUserInputString 可能会要求用户输入字符串,或者可能从数据库中检索字符串。任意一种方法中,类型名称都没有出现在用于恢复的静态分析的代码中,因此无法知道输入程序集中的哪个类型可能会以这种方式进行实例化。这个例子的解决方案就是防止实现 MyInterface 的所有潜在可加载的类型进行重命名(请注意,仍然可以执行方法和字段重命名)。这就是手动配置和了解进行模糊处理的应用程序扮演重要角色的原因所在。Dotfuscator Community Edition 为您提供了防止重命名选择类型、方法或字段的工具。您可以选择独立的名称;另外,您还可以使用正则表达式和其他标准(例如在作用域上的可视性)来编写排除规则。例如,您可以排除所有公共方法使其避免重命名。


     

    使用模糊处理程序的另一个问题发生在部署已模糊处理的应用程序之后,并试图支持它时。假设您的应用程序引发一个异常(这甚至会发生到我们最优秀的人身上),客户向您发送了如下所示的堆栈转储:

    System.Exception: A serious error has occurred
       at cv.a()
       at cv..ctor(Hashtable A_0)
       at ar.a(di A_0)
       at ae.a(String[] A_0)
    

    很明显,这比从未模糊处理程序中进行堆栈转储所得到的信息要少得多。好消息就是您可以使用在模糊处理过程中生成的映射文件来将堆栈跟踪解码回原始符号。坏消息就是有时在堆栈跟踪中没有足够的信息来明确地从映射文件中检索原始符号。例如,转储中忽略方法返回类型的通知。在利用增强的重载归纳重命名算法模糊处理的应用程序中,只有由返回类型区别的方法可能被重命名为相同的名称。因此,堆栈跟踪是模糊的。在大多数情况下,您可以使可能性变得足够小,这样就会以很高的确定性发现原始名称。为此,Dotfuscator Professional 提供了一个工具来自动将堆栈跟踪转换回原始的有问题的方法。

     

    小结


     

    您不需要让黑客为了不可告人的目的在您的应用程序中使用手头的 ILDASM 实用工具。您可以使用很好的模糊处理程序来保护您的代码。模糊处理产生了反向工程的障碍。在 Visual Studio .NET 2003 框中,Dotfuscator Community Edition 可以只通过几次单击就能够完成很好的模糊处理。

    相关文章,请参阅:
    Inside Microsoft .NET IL Assembler,作者是 Serge Lidin (Microsoft Press, 2002)
    Dotfuscator FAQ
    有关背景信息,请参阅:
    Ildasm.exeTutorial
    Anakrino
    http://vexeddotnet.benamotz.com
    http://www.preemptive.com

    展开全文
  • 类似汇编中我们写的跳转。这就是高级语言和低级语言的差别。低阶语言更繁琐和趋近于机器处理过程。比如汇编中的寻址,基本就是cpu取数和处理数的一个过程。 P-code中,顺序结构倒好处理,直接把赋值,函数调用搞定...
  • 当程序集以MSIL而不是机器代码的形式发布时,最令人关心的问题应该就是安全。正如前面所介绍的,程序集包含了关于包里面所有模块的manifest以及...从Listing 1可以看出,利用ILDASM对代码实施反向工程是极为方便的。
  • 反向编译

    2013-02-25 16:03:53
    计算机软件反向工程(Reversepengineering)也称为计算机软件还原工程,是指通过对他人软件的目标程序(可执行程序)进行“逆向分析、研究”工作,以推导出他人的软件产品所使用的思路、原理、结构、算
  • 汇编框架Capstone.zip

    2019-07-16 05:37:03
    Capstone 是一个反汇编框架,希望成为在二进制分析和安全通讯反向工程的最棒工具。可运行在 Windows, Mac OS X, Linux, FreeBSD, OpenBSD 和 Solaris, 可反汇编 ARM, ARM64 (ARMv8), MIPS, PPC, and x86 架构下应用...
  • 汇编编程简介

    千次阅读 2012-01-12 00:29:21
    如今需要用汇编写东西的场合是越来越少了,除了bootloader之类的应用,就是对代码片断进行优化,再有就是反向工程了。而真正要能在现代系统上玩转汇编,需要对CPU架构、计算机结构、操作系统、工具链都有深入的了解...
  • 对于任何新接触开发人员的人来说,这是我的必修课,它非常简单,并且将在几小时内教任何人基本的缓冲区溢出它从教授基本汇编到查找易受攻击的功能,对其进行模糊处理以及执行基本的缓冲区溢出以获取远程RCE的过程 ...
  • 汇编VB.NET加密工具,是一款非常好用的电脑端.net应用程序软件封装和加密工具,主要作用是尽可能地防止暴力脱壳... 关于反编译: 计算机软件反向工程(Reverse engineering)也称为计算机软件还原工程,是指通过对他
  • 这是我先前对Commodore宏开发系统(MADS)汇编程序进行反向工程的工作的延续。 MADS基于从PET上启动的工具集。 包括PET 2和PET 4的版本。 目的是生成可在本机环境中使用VICE的工具编译的源代码。 这是一项正在...
  • {软件工程}之逆向工程

    千次阅读 2013-03-27 23:37:26
    又称反向工程 是根据已有的东西和结果,通过分析来推导出具体的实现方法。比如你看到别人写的某个exe程序能够做出某种漂亮的动画效果,你通过反汇编(W32Dasm)、反编译和动态跟踪(OD)等方法,分析出其动画效果的实现...
  • 软件逆向工程概述

    2012-07-13 20:25:48
    2.4软件逆向工程概述软件逆向工程(Reverse Engineering,叉称反向工程)是指软件开发过程的逆向过程,即从可运行的程序系统出发.对目标文件进行反汇编,得到其汇编代码,然后对汇编代码进行理解和分析,从而得出...
  • 软件逆向工程的前世今生 一提“破解”、“逆向”等词汇,大家定然众口芬芸,莫衷一是,原因就是我们...Engineering)又称软件反向工程,是指从可运行的程序系统出发,运用解密、反汇编、系统分析、程序理解等多
  • 软件逆向工程(Software Reverse Engineering)又称软件反向工程,是指从可运行的程序系统出发,运用解密、反汇编、系统分析、程序理解等多种计算机技术,对软件的结构、流程、算法、代码等进行逆向拆解和分析,推导...
  •  逆向工程是将机器码bai转换为汇编代码或C语言代码du  这种谈话很费力。通常,逆向工程需要在实现目标的同时尽可能少地工作。逆向工程是抄袭技术吗  这就是我要做的。学历要求很低,需求很大。能力越强,收入越高...

空空如也

空空如也

1 2 3 4 5
收藏数 82
精华内容 32
关键字:

反向工程汇编