【问题标题】:Why does this assembly code throw a seg fault?为什么这个汇编代码会引发段错误?
【发布时间】:2016-07-10 02:33:20
【问题描述】:

Assembly Language Step by Step一书提供了以下代码作为沙箱:

section .data
section .text

global _start                

_start:

    nop
    //insert sandbox code here
    nop

我在沙盒空间中包含的任何示例都是创建分段错误。例如,添加这段代码:

mov ax, 067FEh
mov bx, ax
mov cl, bh
mov ch, bl

然后编译:

nasm -f macho sandbox.asm
ld -o sandbox -e _start sandbox.o

当我在我的 OS/X 上运行它时会产生一个段错误。有没有办法获得有关导致分段错误的原因的更多信息?

【问题讨论】:

  • 在调试器下运行它会是一个好的开始。在这种情况下,崩溃的原因可能是因为在执行了程序中的最后一条 NOP 指令后,CPU 继续执行它之后恰好在内存中的指令。
  • 如果我在调试器中运行它,它会自动终止并出现段错误。
  • 理想情况下,您希望程序的行为在调试器下运行时不会改变。它至少应该告诉你你的程序在哪里崩溃以及是什么指令导致了崩溃。
  • Program received signal SIGSEGV, Segmentation fault. 0x00002002 in ?? () 有没有办法保护程序免受内存中出现的任何指令的影响?
  • 如果这是您的代码的总和,那么您正在崩溃,因为您正在运行超过代码的末尾。挂在那里的随机数据被解释为实际代码,一旦它尝试从您的内存区域读取或写入内存,就会导致段错误。

标签: macos assembly x86 nasm


【解决方案1】:

您遇到的问题是您创建了一个程序,该程序在您编写的代码末尾运行。

当您的程序执行时,加载程序最终会向您的_start 发出jmp。然后您的代码运行,但最后您没有任何东西可以返回到操作系统,因此它只会继续运行,执行代码之后发生在 RAM 中的任何字节。

最简单的解决方法是正确退出代码。例如:

mov eax, 0x1              ; system call number for exit
sub esp, 4                ; OS X system calls needs "extra space" on stack
int 0x80       

由于您没有生成任何实际输出,因此您需要使用调试器单步执行以查看发生了什么。编译后可以使用lldb单步执行。

lldb ./sandbox
image dump sections

记下您的可执行文件(不是 dyld)列出的 code 类型的地址。它可能是 0x0000000000001fe6。在 lldb 中继续:

b s -a 0x0000000000001fe6
run
register read
step
register read
step
register read

此时您应该已经过了 NOP 并看到寄存器中的变化。玩得开心!

【讨论】:

  • 我在移动指令后添加了ret。结果相同。我将ret 移到最终nop 之后,结果相同。
  • 我很抱歉。我在旧的 16/32 位实模式世界中呆了一分钟。这应该可以为您解决。
  • 非常感谢您提供的额外信息(我不知道 lldb 工具,我使用的是 gdb)。为类型代码列出的地址是0x0000000000001fe9。当我运行b s -a 0x0000000000001fe9 时,它会给我一个unable to resolve breakpoint to any actual locations 警告。在run 之后,它以状态= 1 存在,然后register readerror invalid thread
  • 仔细检查标记为代码的地址。确保您没有获取数据地址。
  • 执行从跳转的入口点开始,但跳转不是call。堆栈上没有返回地址。 (至少,不是在 Linux 中。我怀疑 OS X 确实在用户空间中运行 call。)它更有可能是 iretsysret。为了避免使您的答案过于复杂,我建议说“加载程序跳转到您的_start”,这给人的印象是运行jmp 指令。这种心智模型非常适合编写正确的用户空间代码。
猜你喜欢
  • 2016-02-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-01-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多