@born 提出了一些很棒的观点,但我认为绝对值得一提的是,整个想法本质上并没有什么不可能。不过,编译和抓取程序集可能不是最好的选择。
将整个事情视为不可能的事情是不对的。IDA 显然在该领域具有潜力;选择伪代码并单击“复制到程序集”。它将在程序集中生成注释,将其映射到伪代码函数的来源。
这是一个程序的三个不同相关阶段的比较;源代码、伪代码和 ASM:
来源 ( clang -w -o test
) :
int main(void)
{
printf("hello world");
}
请注意不正确但功能正常的 使用printf("string")
而不是printf("%s", "string")
。这是另一场辩论,但它会搞砸反编译
IDA 反编译(伪代码):
int __cdecl main(int argc, const char **argv, const char **envp)
{
printf("hello world", argv, envp);
return 0;
}
这是错误的。printf 不会接受这些值,由于“hello world”中缺少格式化“%s”字符串,因此需要 0 个额外参数。一个简单的错误搞砸了伪代码输出。
由 IDA 反汇编(注意其中一些说明可能不正确)
push rbp
mov rbp, rsp
sub rsp, 10h
; 2: printf("hello world", argv, envp);
lea rdi, aHelloWorld ; "hello world"
mov al, 0
call _printf
; 3: return 0;
xor ecx, ecx
mov [rbp+var_4], eax
mov eax, ecx
add rsp, 10h
pop rbp
retn
假设您想编辑字符串:
当然,只需编辑它引用的位置。哦,但是您想要一个超过 11 个字符的字符,因此您需要找到某个未使用的地方并将字符串指针映射到该地址。那很复杂。
该程序的整个可执行部分也有 12 条指令长。你几乎没有空间来改变任何东西,添加东西是一个完全不同的球赛。
尚未完成的可能原因
- 一个巨大的障碍是伪代码有时是多么不可靠。将 Hopper 伪代码与 IDA/Ghidra 的某个时候进行比较,作为一个很好的例子。这是一种有根据的猜测,而不是可靠的猜测。有些甚至不创建变量,尝试编译 Hopper 伪代码是浪费时间。
- 大多数需要修补二进制文件的人想要或需要修补程序集。ASM 的工作方式与 C 不同,当您打补丁时,您需要更多地考虑程序集的工作方式,而不是用于创建它的 C 代码。
- 我所知道的大多数反编译器在单独修补程序集方面已经相当糟糕。一个非常基本的十六进制编辑器做得更好。尝试修补超过 4 个字节的 IDA 会让你头疼
不过,我不认为这几乎是不可能的。不是通过编译肯定的。但是你可以尝试的是这样的:
这两者都需要了解组装以验证补丁是否正确;错误的程序会使您的程序停止运行,并且没有任何工具可以可靠地正确执行此操作。
#2 仍然有缺陷。我花了 2 个多小时来完善单个函数的反编译/反汇编;正确命名内存中的所有内容,手动定义每个结构等。即使使用完美的反编译,它仍然需要编译。
也许您可以在一些复杂的脚本中自己完成这项工作。这是一个问题,我建议您在有经验时重新审视;这是一个非常有趣的话题,IDAPython 可能使它几乎可行。