map exe反编译回C语言

map exe decompilation back to C language

我对汇编还很陌生,正在尽最大努力学习它。我正在上一门课程来学习它,他们提到了一个非常有帮助的 Hello World 示例,我没有遵守。

原始c文件:

#include <stdio.h>
int main()
{
printf("Hello Students!");
return 0;
}

这是使用以下命令反编译的:

C:> objdump -d -Mintel HelloStudents.exe > disasm.txt

反编译(汇编):

push ebp
mov  ebp, esp
and  esp, 0xfffffff0
sub esp, 0x10
call 401e80 <__main>
mov DWORD PTR [esp], 0x404000
call 4025f8 <_puts>
mov eax, 0x0
leave
ret

我在将反编译的输出映射到原始 C 文件时遇到问题,有人可以帮忙吗?

非常感谢!

将汇编反编译回 C 的技术术语是 "turning hamburger back into cows"。生成的程序集将 而不是 是源的 1 对 1 翻译,并且根据优化级别可能会有根本不同。您将获得在功能上与原始来源相同的东西,但它在结构上与该来源的相似程度存在很大差异。

push ebp
mov ebp, esp
and esp, 0xfffffff0
sub esp, 0x10

这都是序言,为 main 函数设置堆栈帧。它将堆栈指针 (ESP) 对齐 16 个字节,然后为传出函数参数保留另外 16 个字节的 space。

call 401e80, <___main>

这个对 ___main 的函数调用是 MinGW 如何在程序开始时将 libc 初始化函数安排到 运行,确保分配了 stdio 缓冲区和类似的东西。


序言到此结束;在您的源代码中实现 C 语句的函数部分以:

开头
mov DWORD PTR [esp], 0x404000

这写入字符串文字的地址 "Hello Students!" onto the stack. Combined with the earliersub esp, 16, this is like apush` 指令。在此 32 位调用约定中,函数参数在堆栈上传递,而不是在寄存器上传递,因此编译器必须在函数调用之前将它们放在此处。

call 4025f8 <_puts>

这会调用 puts 函数。编译器意识到您没有在 printf 调用中进行任何格式处理,并将其替换为更简单的 puts 调用。

mov eax, 0x0

main的return值加载到eax寄存器

leave
ret

恢复之前的EBP值,并拆除栈帧,然后退出函数。 ret 从堆栈中弹出一个 return 地址,只有当 ESP 指向 return 地址时才能工作。