重构反编译程序的控制流程
Reconstructing Control Flow of Decompiled Program
我正在为基本的已编译字节码(一种完全不同的语言)编写一个非常简单的反编译器(在 C++ 中)。执行器使用基于堆栈的机器,大多数指令很容易拼凑起来。
我 运行 陷入了一个有趣的困境,有条件和循环结构。如果前一个操作数的计算结果为假,则字节码中的操作码之一会设置执行程序的位置(有点像 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
语句。该代码基于 Edward J. Schwartz、JongHyup Lee、Maverick Woo 和 David Brumley 的论文“使用语义保留结构分析和迭代控制流结构的本机 x86 反编译”。
虽然它是用 C# 编写的,但将 class 移植到 C++ 应该不是很难。
如果您还有其他问题,可以通过 https://gitter.im/uxmal/reko 与我联系,或通过 johnkal at gmail dot com
.
与我联系
我正在为基本的已编译字节码(一种完全不同的语言)编写一个非常简单的反编译器(在 C++ 中)。执行器使用基于堆栈的机器,大多数指令很容易拼凑起来。
我 运行 陷入了一个有趣的困境,有条件和循环结构。如果前一个操作数的计算结果为假,则字节码中的操作码之一会设置执行程序的位置(有点像 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
语句。该代码基于 Edward J. Schwartz、JongHyup Lee、Maverick Woo 和 David Brumley 的论文“使用语义保留结构分析和迭代控制流结构的本机 x86 反编译”。
虽然它是用 C# 编写的,但将 class 移植到 C++ 应该不是很难。
如果您还有其他问题,可以通过 https://gitter.im/uxmal/reko 与我联系,或通过 johnkal at gmail dot com
.