【问题标题】:Compiling old C code + X86 disassmbley it编译旧的 C 代码 + X86 分解它
【发布时间】:2021-06-10 22:05:42
【问题描述】:

我正在写《黑客:剥削的艺术》一书,我正在尝试与作者一起努力并亲自动手。
我下载了源代码,当我编译它们时,我得到了相同的输出 C 可执行文件。但是当我使用GDB反汇编时,它们有不同的地址和不同的反汇编代码!我执行与书中相同的命令!

顺便说一句,我已经用命令编译了:

gcc -m32 -g code.c

我使用的是 64 位 PC,我学习 x86 汇编。
那么有什么问题呢?是因为它是旧的源代码还是什么?

【问题讨论】:

  • 不同版本的编译器会产生不同的结果。那本书使用了一个更旧版本的 Linux。除非您使用他们正在使用的特定版本,否则您会看到不同的结果。
  • 我相信过去的一个版本的书使用的是 Ubuntu Feisty 7.04
  • godbolt.org 的编译器可以追溯到大约 gcc4.1,现在已经有几年了。 (使用-xc 在C 模式下编译。)不过,这可能没有本书那么古老。可能最大的事情是use gcc -fno-pie -no-pie,如果您使用的是默认为 PIE 的发行版,因为这是代码生成的重大变化。
  • @PeterCordes 艺术开发可追溯到 3.3.6

标签: c gcc compilation x86 reverse-engineering


【解决方案1】:

TL;DR 在正常情况下,您无法匹配在与书中不同的机器上编译的二进制文件的完全相同的地址。

即使这个问题有点抽象,我也会尽量简洁。请记住,为什么您的本地调试器和书中的地址之间的地址很多,所以我在下面列出的肯定不是详尽的。

  1. ASLR(地址空间布局随机化)

ASLR 的作用是将内存地址的较高字节随机化(因此,它不会随机化 ELF 内的函数变量之间的偏移量)作为针对众所周知的二进制利用策略的安全机制

假设我们已经编译了一些代码,例如function_A 和 function_B (假设我们在类 Unix 系统上,编译器的标志就是你建议的那个):如果你在 ELF 文件被加载到内存之前查看它,例如在 @987654325 的反汇编程序中@(所以你正在查看 ELF 本身的字节表示)你会发现 function_A 的地址类似于 0x0000ABCDfunction_B 的地址类似于 ``0x0000EF12`。如果您在main 中设置断点,运行二进制文件并再次检查地址,您会发现地址现在已更改为0xUUUUABCD0xUUUUEF12U = Unknown。 附言GDB 默认禁用 ASLR,因此要观察不同的地址加载,您必须关闭它并再次重复该过程,或者从 gdb 内部禁用 ASLR。

  1. 编译器更改

如果我没记错的话,这本书是在 2003 年左右首次出版的。从那时起,GCC 编译器发生了很大变化。考虑到即使是编译器代码的微小更改也会对其生成的可执行文件产生重大影响。理解为什么 function_A 的程序集表示甚至可能不接近它近 20 年前的表示是非常重要的。 (我确实知道这有点抽象)但是更多地研究这个需要我一本书来解释,但我可以建议你看看编译器:Principles, Techniques, and Tools aka The Dragon Book

  1. 操作系统环境

自从这本书出版以来,Ubuntu(以及一般的 Linux 发行版)版本已经发生了很大变化,它们也在不断发展,并添加了影响例如负责将程序加载到 RAM 上的加载程序。话虽如此,请记住更改操作系统——尤其是如果您更改 Linux 发行版系列(例如,从基于 Debian 的系统变为基于 Fedora 的系统)——会影响二进制文件在内存中的加载方式,这当然区分内存中的地址。

【讨论】:

猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-09-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多