Java 中是如何进行混淆的?

How is obfuscation done in Java?

今天我遇到了一个混淆的 class(一个罐子里有很多混淆的 classes)我不知道这种混淆是如何完成的。

一个例子:

  protected void a(ChannelHandlerContext ☃, ByteBuf ☃, ByteBuf ☃)
    throws Exception
  {
    int ☃ = ☃.readableBytes();
    if (☃ < this.c)
    {
      ☃.b(0);
      ☃.writeBytes(☃);
    }
    else
    {
      byte[] ☃ = new byte[☃];
      ☃.readBytes(☃);

      ☃.b(☃.length);

      this.b.setInput(☃, 0, ☃);
      this.b.finish();
      while (!this.b.finished())
      {
        int ☃ = this.b.deflate(this.a);
        ☃.writeBytes(this.a, 0, ☃);
      }
      this.b.reset();
    }
  }

}

如你所见,所有的参数变量都是一个雪人。这怎么能被撤销?还有它首先是如何完成的; JVM 如何能够 "process" 那些并毫无问题地执行代码?

澄清一下,我不会使用此代码,它仅用于教育目的。我在学校上计算机科学课程,因为我们正在学习 Java 并讨论反编译等限制。我有兴趣了解更多,所以我决定研究更大的项目,尤其是服务器。这段代码是从 Minecraft 的 Spigot 服务器(一个游戏)中提取出来的,它是 Bukkit 服务器的 Minecraft 的一个分支,应该是开源。

protected void a(ChannelHandlerContext ☃, ByteBuf ☃, ByteBuf ☃)

这是无效的。不能有多个同名参数。可能是您没有阅读具有正确文本格式的 unicode 文本。

首先,你应该注意,是参数有这个unicode,而不是方法。为什么这很重要? 参数不需要指定名称,因为它们大多由数字引用索引。然而,它可以被指定,我假设大多数 java 运行时实际上不检查这个名称,因为它不需要执行。 相反,需要 class 名称、方法名称和字段名称。

关于你提到的 Spigot,Spigot 确实是开源的。但是,您很可能反编译了一个 class,它最初来自原始的 Mojang Minecraft 服务器,它不是开源的并且确实被混淆了。

编辑:如果您想调查这些 classes,我最近发现了一个名为 Bytecode Viewer 的工具,可在 https://github.com/Konloch/bytecode-viewer 这个工具有多个反编译器以及一些选项来查看更像字节码版本的 class 文件。 我发现的一个函数示例包含以下字节码数据:

     <localVar:index=1 , name=☃ , desc=D, sig=null, start=L1, end=L2>
     <localVar:index=3 , name=☃ , desc=D, sig=null, start=L1, end=L2>
     <localVar:index=5 , name=☃ , desc=D, sig=null, start=L1, end=L2>

确实可见,unicode名称已经设置成一样了,不过没关系,最后索引(1,3,5)是用来引用这些变量的。

您的文本编辑器正在显示 unicode 字符的值。

我刚刚在 eclipse 上测试过,可以接受带有 unicode 字符的名称。

    public String publicationXmlUrl(int \u9090currentPage) {

但是写值不是:

   public String publicationXmlUrl(int ♥currentPage) {