【问题标题】:Are assembly language programs restricted by kernel modes as well?汇编语言程序是否也受内核模式的限制?
【发布时间】:2017-04-26 12:31:53
【问题描述】:

如果我要编写一个汇编语言程序,我是否可以破坏操作系统的安全机制——访问其他进程的地址空间、访问内核地址空间等?

编辑

如果我编写了一个汇编语言程序,它由操作系统提供的加载程序加载到内存中,操作系统在尝试访问受保护的内存地址空间时如何拦截我的程序?我的假设是这种保护内置于操作系统提供的系统调用和库中,如果您不使用这些系统调用和库,则可以破坏操作系统策略。

【问题讨论】:

  • 当然不是。安全不是知识问题。 CPU 只处理机器代码,与生成它的语言无关。
  • RE 您的编辑:否。保护内置于操作系统本身。您的汇编语言程序将作为标准进程运行,并受到与任何其他进程相同的安全限制。
  • 操作系统停止它。它的工作方式与用任何其他语言编写的程序完全相同。所有现代操作系统都实现了受保护的内存,并在自己的进程中运行每个程序,这样一个进程就不允许干扰其他进程(或系统本身)的内存。这实际上与汇编语言无关,而与操作系统的设计有关。
  • 内存保护和虚拟化通常由现代硬件(CPU)提供。操作系统开发人员使用这些功能在自己的进程空间中对代码进行沙箱处理。操作系统将确定对代码施加的限制。无论代码是手工编写的汇编代码还是高级语言编译的代码,所有执行的代码都会有相同的限制。
  • @BharatKhatri,兄弟,如果您能获得 Tom Shanley 的《保护模式软件架构》一书的副本,我想这对您很有帮助。这本书很好地介绍了“为什么”需要“保护模式”CPU 架构来为现代操作系统提供庇护,以及“如何”使用这些 CPU 功能实现某些操作系统部件。当然,缺少一些小细节(如果没有,我不会在这里寻找答案),但它可以为您提供大量信息。

标签: assembly operating-system


【解决方案1】:

保护内置于硬件中。每一个加载/存储(和代码提取)都会根据页表检查(使用TLB 来缓存页表条目)。

此外,如果由用户空间进程运行,特权指令(如 x86 的 LIDT 错误)。 (该手册条目的异常部分说它引发了#GP(0)“如果当前权限级别不是 0”)。

如果在一台机器上获得 root 权限只需要一点点手写 asm,那么安全的多用户操作系统将无法实现。由于它们存在并且实际上很常见,因此我们知道您的前提一定是错误的。 (Linux、Unix、OS X、Windows 都是以这种方式设计的。它们都存在允许攻击者运行任意内核代码的实现错误,但这不是重点。)

【讨论】:

    【解决方案2】:

    注意:此答案是Ira BaxterglauxosdeverPeter Cordes 提供的答案以及Cody Gray 提供的cmets 的合并


    如果您的程序作为操作系统控制的进程在硬件中提供足够的进程隔离(通常是地址空间管理保护)的机器上运行,则不会。

    对于大多数架构(包括 x86),保护是内置在硬件中的。

    大多数现代操作系统(包括 Windows、OS X、Linux、BSD 等)都使用分页来管理进程的内存。分页涉及到有页目录和页表,它们描述了每个虚拟页的属性:物理地址、权限等。

    页面目录和页表映射在内核空间中,因此不能被用户进程编辑。

    每个加载/存储(和代码提取)都会根据页表检查(使用TLB 缓存页表条目)。

    此外,如果由用户空间进程运行,特权指令(如 x86 的 LIDT 错误)。 (该手册条目的异常部分说它引发了#GP(0)“如果当前权限级别不是 0”)。

    【讨论】:

      【解决方案3】:

      对于大多数架构(包括 x86),保护是内置在硬件中的。

      对于 x86,有两种技术可以保护内核和其他程序的地址空间:分段和分页。大多数现代操作系统(包括 Windows、OS X、Linux、BSD 等)都使用分页作为主要技术,所以我将讨论它。

      分页涉及到有页目录和页表,它们描述了每个虚拟页的属性:物理地址、权限等。页目录和页表映射在内核空间中,因此不能被用户进程编辑。

      当内核切换到用户进程时,它会恢复用户进程的页面结构,因此它只有访问自己映射页面的权限。当它试图访问一些未映射的地址时,将引发页面错误。如果该地址的内存内容已被交换掉,它们将被取消交换,并且该过程将继续进行而不会注意到任何事情(可能会有一点延迟)。如果该内存地址没有被分配,因此没有被交换掉,程序将简单地终止。

      注意:也不是只有汇编语言会导致不安全的行为。尝试写入 C 中的随机地址,您会发现它很可能会立即崩溃。为什么?因为操作系统会通过缺页检测地址空间违规。如果它没有崩溃,则意味着您将写入一些属于它自己的地址空间的内存。

      【讨论】:

      • 分段本身不提供任何保护。通过在受保护模式下运行来提供保护,它为您提供四个“环”(特权级别)。
      • @CodyGray 感谢您发现错误,已编辑。
      • 你没有提到的关键点:用户空间进程不能修改自己的页表。这就是内核模式(环 0)与用户模式(环 3)的对比。我知道很难用简短的回答来总结这一点,也很难知道你可以假设读者有什么知识,但我认为这一点值得一提。我建议只说内核与用户模式,实际上不要提及 x86 环,因为这甚至不是一个特定于 x86 的问题,并且常见的操作系统只是使用环 0 和环 3,就像使用内核与使用环一样。仅具有该功能的拱门上的用户模式。
      • @fante :在 x86 硬件页表(提供虚拟内存和物理内存之间的映射)上,有一个 present 标志作为页表条目、页面目录条目等的一部分。这是还有一个位传递给页面错误处理程序,以决定如何继续。如果present 位为零,则会发生页面错误。
      • @fante 实际上它可以被解释但是页面错误处理程序希望解释它。海量存储和虚拟内存仅适用于这种情况。如果愿意,该标志也可用于请求进程之间的映射共享内存。事实上,页面错误处理程序可以忽略请求,让指令重试/失败,然后让应用程序出错。其他位(底部 3)指定虚拟地址所在的页面是否为只读(例如,写入只读会出现页面错误),以及页面是否允许监督(Priv 级别 0 到 2)或用户空间(隐私 3).
      【解决方案4】:

      如果您的程序作为操作系统控制的进程在硬件中提供足够的进程隔离(通常是地址空间管理保护)的机器上运行,则不会。 (好吧,您可以编写试图破坏安全性的指令,但在具有此类硬件的精心设计的操作系统下,它们只会在执行时陷入陷阱)。

      如果您运行的硬件不具备此类保护功能,那么您运行在与操作系统和其他应用程序共享的空间中,按照惯例以合作方式进行。这意味着您可以触摸并损坏操作系统和其他应用程序,但您不应该这样做。您是否选择违反该承诺取决于您;通常,它不会让您与该类型硬件的用户社区成为朋友。

      【讨论】:

      • 如果我编写了一个汇编语言程序,它由操作系统提供的加载程序加载到内存中,操作系统在尝试访问受保护的内存地址空间时如何拦截我的程序?我的假设是这种保护内置于操作系统提供的系统调用和库中,如果您不使用这些系统调用和库,则可以破坏操作系统策略。
      • 操作系统可以在你的进程地址空间中放置任何它喜欢的东西。您的程序无法看到其进程地址空间之外的内容。没有什么是易碎的。
      • 页表包含保护位,可用于限制处理器模式对页的访问。如果这些位设置为仅用于内核模式访问,则用户模式访问会触发访问冲突。
      • @BharatKhatri:保护内置于硬件中。每一个加载/存储都会根据页表检查(使用a TLB 缓存页表条目)。此外,如果由用户空间进程运行,特权指令也会出错。如果在一台机器上获得 root 权限只需要一点点手写 asm,那么安全的多用户操作系统将无法实现。既然他们是,我们知道你的前提一定是错误的。
      • @PeterCordes 这解释得更好。您能否详细说明特权指令?你说的是处理器 asm 提供的特权指令吗?
      猜你喜欢
      • 2011-04-20
      • 1970-01-01
      • 2011-01-01
      • 1970-01-01
      • 2013-03-10
      • 2016-09-27
      • 1970-01-01
      • 2017-01-26
      相关资源
      最近更新 更多