【问题标题】:How do I convert assembly code to C code?如何将汇编代码转换为 C 代码?
【发布时间】:2020-11-04 09:29:32
【问题描述】:

我需要一些帮助来解决这个问题。我正在尝试从汇编代码中对代码进行逆向工程,但我一直被 1 个命令关闭,我对为什么感到困惑。我得到的汇编代码(我的注释在#中)是这样的。

   0x00005555555545fa <+0>: push   %rbp
   0x00005555555545fb <+1>: mov    %rsp,%rbp #int x,y
=> 0x00005555555545fe <+4>: movl   $0x2b,-0xc(%rbp) #set x = 43
   0x0000555555554605 <+11>:    movl   $0x2fd,-0x8(%rbp) #set y = 765
   0x000055555555460c <+18>:    mov    -0xc(%rbp),%edx #load x into %edx 
   0x000055555555460f <+21>:    mov    -0x8(%rbp),%eax #load y into %eax
   0x0000555555554612 <+24>:    add    %edx,%eax #add x and y
   0x0000555555554614 <+26>:    mov    %eax,-0x4(%rbp) # y = x + y
   0x0000555555554617 <+29>:    mov    $0x0,%eax
   0x000055555555461c <+34>:    pop    %r bp
   0x000055555555461d <+35>:    retq   

这是我当前的代码和生成的汇编代码

int main(){
        int x,y;
        x = 43;
        y = 765;
        x = y;
        y = y + x;
}

   0x00005555555545fa <+0>: push   %rbp
   0x00005555555545fb <+1>: mov    %rsp,%rbp
=> 0x00005555555545fe <+4>: movl   $0x2b,-0x8(%rbp)
   0x0000555555554605 <+11>:    movl   $0x2fd,-0x4(%rbp)
   0x000055555555460c <+18>:    mov    -0x4(%rbp),%eax
   0x000055555555460f <+21>:    mov    %eax,-0x8(%rbp)
   0x0000555555554612 <+24>:    mov    -0x8(%rbp),%eax
   0x0000555555554615 <+27>:    add    %eax,-0x4(%rbp)
   0x0000555555554618 <+30>:    mov    $0x0,%eax
   0x000055555555461d <+35>:    pop    %rbp
   0x000055555555461e <+36>:    retq   

我很难弄清楚如何“将 x 加载到 %edx”,然后再添加 %eax 和 %edx。任何帮助都可以得到 c:

【问题讨论】:

  • 自己尝试一下。请查阅指令集参考以了解每条指令的作用,并根据您的想法编辑您的问题。提示:-x(%rbp) 是局部变量。
  • 您可以在英特尔的手册中查找说明(例如此处的 HTML 提取:felixcloutier.com/x86/idiv)。 idivl 当然是 AT&T 用于具有 dword 操作数大小的 idiv 的语法。如果你理解得更好,反汇编为 Intel Syntax 而不是 AT&T。另见When and why do we sign extend and use cdq with mul/div?
  • 不同的编译器或编译器版本可能以不同的方式实现相同的逻辑。 2 加载和添加 reg,reg 与内存目标添加没有有意义的不同。请记住,这段代码无论如何都对结果没有任何作用,因此如果在启用优化的情况下编译,则只会优化为 xor %eax,%eax / ret。您的编译器输出使用与原始 RBP 不同的偏移量也并不重要;两者都在使用 RSP 下面的红色区域中的空间,这是该函数堆栈框架的一部分。
  • 原始样本中没有您的x = y

标签: c assembly x86-64 reverse-engineering


【解决方案1】:

没有易于使用的工具来进行这种转换。 (换个方向很简单:将一些高级代码编译成汇编。)

虽然有一些像您的问题一样进行翻译的例子,但到目前为止,这是一个太复杂的问题,回报太少。这有点像在车辆碰撞后捡起碎片并确定车辆在碰撞前处于何种状态。 NTSB 在发生重大事故后经常会这样做,但付出的努力是相当大的。

【讨论】:

  • 实际上 ghidra (ghidra-sre.org) 带有一个反编译器,它提供了一个可以通过的源代码表示。
  • Avast 的 RetDec(可重定向反编译器)是开源的,基于 LLVM,在生成合理的源代码方面也做得不错。
最近更新 更多