【问题标题】:Is it possible to distinguish between decompiled code and handwritten code?是否可以区分反编译代码和手写代码?
【发布时间】:2021-02-17 19:23:18
【问题描述】:

在我的一个 CS 课程中,我的老师叫我参加一个缩放会议,并指责我将我的 C 代码反编译成 AT&T x64 汇编语言。我没有反编译我的代码,所以我很困惑。

有没有办法区分手写代码和反编译代码?我想知道,这样我就不会意外地以似乎被反编译的方式编写代码......

【问题讨论】:

  • 反编译将汇编转换为C,但您似乎在谈论相反的事情,这只是“编译”。
  • @NateEldredge:他本可以通过编译器运行它,然后通过反汇编程序。
  • @Joshua:这仍然不涉及任何反编译。您可以从 C 源代码开始,编译为机器代码或 asm,反编译为 C 或 C++,然后再次编译……或者您可以从手写 asm 开始,反编译为 C 或 C++,然后在尝试优化你的 asm。
  • 我很想看看您的手写汇编,以及您的教授指出的作为指标的标志是编译器输出(这似乎是您所说的)。如果它是手写的,我很可能会指出 GCC 或 clang 永远不会发出它的多个迹象。绝大多数学生编写的 asm 都充满了简单但轻微遗漏的优化,例如在只需要 32 位时使用 64 位操作数大小。 (尽管公平地说,GCC 在编译不必要地使用unsigned long 或其他任何内容的源时,通常无法进行值范围分析。)

标签: c assembly x86-64 compiler-optimization


【解决方案1】:

是的,我们可以判断。当它不重要时,人类会将东西组织成逻辑块,因此逻辑按顺序发生,寄存器分配按顺序发生等等。另一方面,编译器会随意分配东西,当指令顺序无关紧要时以伪随机顺序发出指令,等等。

但是我们可以一眼看出学习汇编和反编译代码的人的手写汇编代码。编译器将使用初级课程中没有教授的过于高级的技巧。基本上,如果我们过早地看到一些没有完成作业和考试的人,它就会被反编译。

从历史上看,这是颠倒过来的,直到 15 年前,我们还在嘲笑编译器的程序集,就好像是新手编写的一样。不再。现在编译器是专家。

【讨论】:

  • 你在描述 optimized asm;是的,同意。特别是对于 3 操作数 ISA,编译器也很少将变量保存在一致的寄存器中。在禁用优化的情况下编译的迹象更加清晰:实现每个 C 语句的独立指令块,从不在这些块的寄存器中保留任何内容。 (除非您在 gcc 或 clang 中使用 register 关键字)。 Why does clang produce inefficient asm with -O0 (for this simple floating point sum)?
  • 还有其他内容:通用的标签名称 (L12345) 而不是有意义的标签名称、.size 等指令、代码对齐、堆栈金丝雀和endbr 等安全功能等。
  • @NateEldredge:命名、格式和指令可以由不完全天真的人重写,仍然保留实际指令,因此实际指令选择更像是指纹而不是“衣服” .但是,是的,对于 ESP / RSP 的每次更改,对编译器输出的完全幼稚的使用都会有类似的东西和 .cfi 指令,除非他们使用 How to remove "noise" from GCC/clang assembly output?。说句公道话,我见过一些没有费心发明有意义的标签名称的手写代码,但通常不是 GCC 或 clang 的 exact 样式。
猜你喜欢
  • 2023-03-25
  • 1970-01-01
  • 2018-07-27
  • 2010-09-13
  • 1970-01-01
  • 1970-01-01
  • 2013-05-30
  • 2011-06-14
  • 2012-03-14
相关资源
最近更新 更多