为什么将字符插入可执行的二进制文件会导致它“中断”?

时间:2013-12-31 01:08:48

标签: c linux compiler-construction linker hex-editors

为什么将字符插入可执行的二进制文件会导致它“中断”?

并且,有没有办法在不破坏编译程序的情况下添加字符?

背景

我很早就知道可以使用十六进制编辑器来更改已编译的可执行文件中的代码并仍然可以正常运行...

实施例

作为下面的应用程序中的示例,Facebook可以更改为Lacebook,程序仍然可以正常执行:

enter image description here

enter image description here

但它打破了新角色

我也知道如果添加了新字符,它将破坏程序并且不会运行,或者它会立即崩溃。例如,在My前添加Facebook即可实现此目的:

enter image description here

我所知道的

我不知道

  • 我不太了解操作系统和可执行文件之间的关系。我猜想当你输入程序名称并按回车键时,你基本上是指示操作系统“执行”该文件,这基本上意味着将文件加载到内存中,设置处理器指向它的指针,然后告诉它'去!'
  • 我理解为什么在二进制文件的文本字符串中添加额外字符会导致问题

我想知道

  1. 为什么多余的字符会导致程序中断?
  2. 什么东西决定程序被破坏?操作系统?操作系统是否也将此程序保留为沙盒,以便它现在不会使整个系统崩溃?
  3. 有没有办法通过十六进制编辑器将多余的字符添加到已编译程序的文本字符串中,而不是让应用程序中断?

3 个答案:

答案 0 :(得分:5)

当程序编译成机器代码时,它包含许多对程序存储器中指令和数据地址的引用。编译器确定程序所有内存的布局,并将这些地址放入程序中。可执行文件也被组织成部分,并且在开头有一个目录,其中包含每个部分中的字节数。

如果您在程序中插入了某些内容,那么之后所有内容的地址都会向上移动。但是程序中包含对程序和数据位置的引用的部分不会更新,它们会继续指向原始地址。此外,包含所有部分大小的表格不再正确,因为您增加了所修改部分的大小。

答案 1 :(得分:4)

  

我不太了解操作系统和可执行文件之间的关系。我猜想当你输入程序名称并按回车键时,你基本上是指示操作系统“执行”该文件,这基本上意味着将文件加载到内存中,设置处理器指向它的指针,然后告诉它“去!

现代操作系统只是将文件映射到内存中。在需要之前,他们不会费心加载页面。

  

为什么多余的字符会导致程序中断?

因为他们将文件中的所有其他信息放在错误的位置,所以加载器最终会加载错误的东西。此外,代码中的跳转最终会出现在错误的位置,也许是在指令的中间。

  

什么东西决定程序被破坏?操作系统?操作系统是否也将此程序保持为沙箱,以便它现在不会使整个系统崩溃?

这取决于究竟是什么搞砸了。可能是您移动标题并且加载程序注意到标题中的某些参数具有无效数据。

  

有没有办法通过十六进制编辑器将多余的字符添加到已编译程序的文本字符串中而不会让应用程序中断?

可能不可靠。至少,您需要可靠地识别需要调整的代码部分。这可能是非常困难的,特别是如果有人试图故意这么做的话。

答案 2 :(得分:3)

机器语言可执行文件的格式基于硬偏移,而不是解析字节流(如文本程序源代码)。在某处插入字节时,文件格式将继续引用原始偏移处插入点之后的信息。

文件格式本身可能会出现偏移,例如标题告诉加载程序文件中的内容以及它们的大小。

硬偏移也发生在机器语言本身,例如指向程序数据或分支指令的指令。

假设一条指令说“从我们现在的地方向下分支200个字节”,并在这200个字节中插入一个字节(因为字符串碰巧在那里你想要改变)。哎呀;该分支仍然覆盖200个字节。

在某些机器上,即使你修复它,分支甚至不能是201字节,因为它会被错位并导致CPU异常;你必须添加四个字节来将其修补为204(以及使文件保持健全所需的无数其他东西)。