我正在为基本编译的字节码(一种完全不同的语言)编写一个非常简单的反编译器(用c++)。执行器使用基于堆栈的机器,大多数指令都很容易拼凑在一起。
在条件和循环结构方面,我遇到了一个有趣的困境。如果前一个操作数的计算结果为false,字节码中的一个操作码将设置执行器的位置(有点像jmp指令)。因此,如果满足条件,执行程序将在当前指令指针处继续执行。 现在,我已经将这些实现为简单的goto,但是我想扩展这个功能,将原始的if/else结构拼凑在一起。以下是原始源代码的示例:function myFunction() {
if (this.var1 == "foo") {
this.var2 = "bar";
} else {
this.var2 = "baz";
}
}
和我的反编译输出:
goto label23;
function myFunction() {
if (!(this.var1 == "foo")) {
goto label16;
}
this.var2 = "bar";
goto label21;
label16:
this.var2 = "baz";
label21:
return 0;
}
label23:
是否有一种方法可以应用于这个"反编译"的程序?以某种方式将条件拼凑在一起,使其与原始来源相似?我知道没有一个反编译器是完美的,但是我很好奇像Ghidra这样的反编译器是如何解决这类问题的。因为我的字节码不一定是机器码(更像是压缩的源代码),所以我假设我的用例比Ghidra的反编译器简单得多。
Reko是一个试图从机器代码重构类c代码的反编译器。它有一个通道,重建高级结构,如if
,while
和switch
语句。该代码基于论文"使用语义保持结构分析和迭代控制流结构的本地x86反编译"。作者:Edward J. Schwartz, JongHyup Lee, Maverick Woo, David Brumley。
虽然它是用c#编写的,但将一个类移植到c++应该不是很困难。如果您有其他问题,可以通过https://gitter.im/uxmal/reko联系我,或者给我发邮件到johnkal at gmail dot com
。