我正在针对以下C
代码测试几个反编译器
static int bar(int i) {
return ++i;
}
static int apply(int (*fun)(int), int i) {
return i % fun(i);
}
static int foo(int (*app)(int (*fun)(int), int), int i) {
return i / app(bar, i);
}
int main() {
return foo(apply, 7);
}
这是由 just 编译的clang test.c
。
; main
0x0 push rbp
0x1 mov rbp, rsp
0x4 sub rsp, 0x10
0x8 mov dword ptr [rbp-0x4], 0x0
0xf mov rdi, @apply
0x19 mov esi, 0x7
0x1e call foo
0x23 add rsp, 0x10
0x27 pop rbp
0x28 ret
; foo
0x30 push rbp
0x31 mov rbp, rsp
0x34 sub rsp, 0x20
0x38 mov [rbp-0x8], rdi
0x3c mov [rbp-0xc], esi
0x3f mov eax, [rbp-0xc]
0x42 mov rcx, [rbp-0x8]
0x46 mov esi, [rbp-0xc]
0x49 mov rdi, @bar
0x53 mov [rbp-0x10], eax
0x56 call rcx
0x58 mov edx, [rbp-0x10]
0x5b mov [rbp-0x14], eax
0x5e mov eax, edx
0x60 cdq
0x61 mov esi, [rbp-0x14]
0x64 idiv esi
0x66 add rsp, 0x20
0x6a pop rbp
0x6b ret
我知道参数/参数检测的一些限制(来自对另一个问题的回答)。但是每个反编译器似乎都以某种方式在其反编译语言的类型系统中存在不一致(我认为它们都试图反编译为C
或 伪C
)。
IDA v.7.4.191122
(评估版)给出:
int __cdecl main(int argc, const char **argv, const char **envp)
{
return foo(apply, 7LL, envp);
}
__int64 __fastcall foo(int (__fastcall *a1)(__int64 (__fastcall *)(), _QWORD), unsigned int a2)
{
return (unsigned int)((int)a2 / a1(bar, a2));
}
我不显示的结果bar
和apply
因为当时已经在这里存在不一致:IDA检测到foo
被称为与3个参数main
,但后来得出结论,foo
实际上已经2个参数。
接下来,Ghidra v9.1.build.2019-oct-23
:
void main(void)
{
foo(apply,7);
return;
}
ulong foo(code *param_1,uint param_2,undefined8 param_3)
{
int iVar1;
iVar1 = (*param_1)(bar,(ulong)param_2,param_3,param_1);
return (long)(int)param_2 / (long)iVar1 & 0xffffffff;
}
其具有相反的意见:foo
被称为在main
以2个参数,但在其定义中foo
有3个参数。
JEB v.3.8.0.201912242244
(评估版本):
unsigned long main() {
return foo(&apply, 7L);
}
unsigned long foo(unsigned long param0) {
unsigned int v0 = v1;
param0();
return (unsigned long)(v0 / ((unsigned int)v2));
}
这给出了 的完美结果main
,但随后声称它foo
是只有 1 个参数的函数(虽然它显示param0()
,但它保持param0
为unsigned long
)。
实际上,反编译的结果并不正确(这在某种程度上是可以理解的),但它们甚至不一致。我错过了一些配置吗?