c - 使用 GCC -march=i686 逆向工程 C 代码

标签 c gcc assembly reverse-engineering

这是我的 C 代码:

int test(int x, int y){
    int val=4*x;
    if (y>0){
        if (x<y) val=x-y;
        else val=x^y;
    }
    else if (y<-2) val=x+y;
    return val;
}

这是我在 GCC 命令行中输入的内容:

gcc -O1 -S -march=i686 test.c

这是我得到的S文件(只有计算部分):

pushl   %ebx
movl    8(%esp), %ecx
movl    12(%esp), %edx
testl   %edx, %edx
jle     L2
movl    %ecx, %eax
subl    %edx, %eax
movl    %edx, %ebx
xorl    %ecx, %ebx
cmpl    %edx, %ecx
cmovge  %ebx, %eax
jmp     L4

L2:
leal    0(,%ecx,4), %eax
addl    %edx, %ecx
cmpl    $-2, %edx
cmovl   %ecx, %eax

L4:
popl    %ebx
ret

我的问题是:我可以使用上面的 S 文件取回完全相同的 C 代码吗?我的意思完全一样。例如,我可以确定 val 的默认值是 4*x (C 代码的第 2 行)吗?我可以确定每个 if 语句的测试表达式吗?

我真的需要你的帮助。谢谢!!!

最佳答案

在这种情况下,你可以发现每个寄存器对应一个变量:

  • %eax - var
  • %ebx - 上下文临时变量
  • %ecx - x
  • %edx - y

如果您的意思是“完全”用于标识符,则只有在名为“符号表”的特殊结构时才有可能。 (在 GCC 中使用 -g 标志编译)

无论如何,您应该知道编译器总是可以优化代码。这意味着,在这种情况下,您的代码将更改为另一个具有相同数学含义的代码。如果你的代码是反向翻译的,它应该是这样的。

int test(int x, int y) {
    int val;
    if (y > 0) {
        if (x < y)
            val = x - y;
        else
            val = x ^ y;
    } else {
        if (y < -2)
            val = x + y;
        else
            val = 4 * x;
    }
    return val;
}

如果您不想优化,请使用标志 -O0 而不是 -O1

关于c - 使用 GCC -march=i686 逆向工程 C 代码,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17480649/

相关文章:

c++ - "fetch_and_store"是什么意思?

c - 图像处理基础知识

c - 当指向整数的指针转换为指向 char 的指针时,实际发生了什么?

c - 在 C 中将每年的秒定义为宏?

assembly - 为什么不能使用 "jump and link"和 "jump register"进行递归?

c++ - 任何人都知道任何可以使用 C++ 以字节为单位编码 asm 字符串的东西吗?

java - 如何在 JVM 中查看 JIT 编译的代码?

c - 引导跨平台编译器

c - GLFW 无法正确链接

c - 如何链接到不同的 libc 文件?