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) {
今天我遇到了一个混淆的 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) {