将 x86-64 程序集转换为 C

逆向工程 部件 x86 C
2021-07-07 21:35:46

我正在尝试将 x86-64 程序集转换为 C 代码,但仍然不确定某些行。

这是汇编代码:

   ....
  pushq %rbp 
  movq %rsp, %rbp 
  subq $20, %rsp
  movl %edi, -20(%rbp) 
  movl $2, -4(%rbp) 

 jmp .L2
  movl -20(%rbp), %eax //1 Lines 1-3 divide %eax / -4(%rbp)
  cltd  //2 the quotient is stored in %eax
  idivl -4(%rbp) //3 Remainder is stored in %edx
  movl %edx, %eax 
  testl %eax, %eax
  jne .L3 
  movl $0, %eax 
  jmp .L4 

.L3: 
  addl $1, -4(%rbp)

.L2: 
  movl -4(%rbp), %eax 
  cmpl -20(%rbp), %eax
  jl .L5 
  movl $1, %eax

 .L4: 
  leave 
  ret 
  .....

在 C 中,它会是:

int function (int param) {
   int var1= 2; 
   while (var1 < param) {
       if (eax != 0) { // instead of eax, should it be var1?
           eax = eax / var1; // unsure about the body
   } 
return var1; 
}

如果有人可以帮助指导我走向正确的方向或向我展示我所缺少的东西,那就太好了。

2个回答

如果您提供了更多上下文,那么这个答案可能会更好,因为您遇到了哪些确切的汇编语句。

通常,编译器通常有一条指令,在某事开始时将变量移动到寄存器,使用该寄存器一段时间,然后将变量存储回去。在您的情况下,可以将其eax视为复制的临时变量var1,如下所示:

eax_temp_var1=var1;
eax_temp_var1=eax_temp_var1%var2;  // idivl; movl
if (eax_temp_var1 == 0)            // testl
    return 0;                      // movl $0, eax; jmp L4; leave; ret
var2++;                            // addl $1
if (var2<var1)
    goto L5;                       // movl; cmpl; jl
return 1;

当然,C 程序员不会像这样写前三行,而是

if (var1 % var2 == 0)

逆向工程的部分挑战是简化这样的代码以了解发生了什么。

请注意,在您发布的代码片段中,没有跳回,因为我们不知道 L5 在哪里;所以没有理由这应该是一个循环。(实际上,我猜整个事情是一个素性测试,而 L5 就在 之后jmp .L2,这将使它成为一个循环)。

此外,当程序到达 L4 时,eax将包含 0 或 1,因此永远不会返回 var1。

最后,我使用了 var1%var2,而不是 var1/var2。您自己评论了“edx 中的剩余部分”;thenedx移动到eax,然后eax测试它是否为零。因此,要测试的是余数,而不是商。

最后部分丢失了,但它看起来很像一个测试素性的简单函数。它尝试将 param 与从 2 到 (param - 1) 的每个数字相除。如果余数为零,则该函数已找到除数并返回 0。否则返回 1。

就像是:

bool is_prime(int param)
{
    int var1;

    for (var1 = 2; var1 < param; var1++)
    {
        if (param % var1 == 0) return false;
    }

    return true;
}

-20(%rbp) 是参数;那将是参数。

-4(%rbp) 是局部变量;那将是 var1。