使用基于字节码的虚拟机语言(例如Java,VB.NET,C#,ActionScript 3.0等),有时您会听到,只需从Internet下载一些反编译器,并在其中运行字节码一次,这是多么容易,并且通常,您会在几秒钟内想到与原始源代码相差不大的内容。据说这种语言特别容易受到攻击。
最近,我开始想知道,为什么您至少不了解本机二进制代码最初是用哪种语言编写的(以及尝试将其反编译成哪种语言),却为什么对本机二进制代码却听不懂呢。很长一段时间以来,我发现这仅仅是因为本地机器语言比典型的字节码疯狂得多,而且更加复杂。
但是字节码是什么样的?看起来像这样:
1000: 2A 40 F0 14
1001: 2A 50 F1 27
1002: 4F 00 F0 F1
1003: C9 00 00 F2
本地机器代码是什么样(十六进制)?当然,它看起来像这样:
1000: 2A 40 F0 14
1001: 2A 50 F1 27
1002: 4F 00 F0 F1
1003: C9 00 00 F2
指令来自类似的思维框架:
1000: mov EAX, 20
1001: mov EBX, loc1
1002: mul EAX, EBX
1003: push ECX
因此,考虑到尝试将某些本机二进制文件反编译为C ++的语言,它有什么困难?马上想到的只有两个想法:1)实际上比字节码复杂得多,或者2)操作系统倾向于分页程序并分散程序段会导致太多问题的事实。如果这些可能性之一是正确的,请解释。但是,无论哪种方式,您为什么基本上都没有听说过?
注意
我将接受其中一个答案,但我想先提一下。几乎每个人都在指一个事实,即不同的原始源代码片段可能映射到相同的机器代码。局部变量名称丢失,您不知道最初使用的是哪种类型的循环,等等。
但是,在我看来,像刚才提到的两个例子是微不足道的。但是,有些答案倾向于指出,机器代码和原始源代码之间的差异远比这种琐碎的事情大得多。
但是例如,当涉及局部变量名称和循环类型之类的内容时,字节码也会丢失此信息(至少对于ActionScript 3.0而言)。之前,我已经通过反编译器将这些东西拉回来,而且我真的不在乎变量是被调用strMyLocalString:String
还是loc1
。我仍然可以在较小的本地范围内进行查看,看看它的使用方式没有太大麻烦。而一个for
循环是相当多的同样的事情while
循环,如果您考虑一下。同样,即使当我通过irrFuscator运行源代码(与secureSWF不同,它不仅要做随机化成员变量和函数名称之外,所做的工作不多),看起来仍然可以像在较小的类中开始隔离某些变量和函数一样,如图了解如何使用它们,为它们分配自己的名称,然后从那里开始工作。
为了使这成为一个大问题,机器代码将需要丢失比这更多的信息,并且某些答案确实可以解决这个问题。