如何使用Python访问Ring 0?

4

这个回答表明Python中类的命名并非因为特殊权限而进行,在这里让我感到困惑。

  1. 我如何在Python中访问较低级别的环?
  2. 用于访问较低级别环的低级I/O是什么?
  3. 如果是这样,我可以访问哪些环?
  4. 语句“此函数旨在进行低级I/O。”是指较低级别的环还是其他内容?
  5. C往往是操作系统编程中突出的语言。当Python中有OS类时,这是否意味着我可以通过该类访问C代码?
  6. 假设我正在处理奇怪的机器语言代码,并且我想以某种方式理解它的含义。 Python中是否有一些工具可用于分析这些内容?如果没有,是否有某种方式可以使用Python控制某个控制奇怪机器语言的工具?[评论中建议使用ctypes]
  7. 如果Python与低级别的特权无关,则它是否仍然提供一些包装器来控制特权?

2
@hhh:这个问题并没有太多意义。类不需要权限,用户需要。权限绑定在用户身上。 - S.Lott
2
@hhh:你只是在谈论API请求和权限。Python有一个大型的API请求库。哪些API请求可以使用,哪些会引发异常取决于您定义的用户权限。如果您想要的API不在Python库中,您有几个选择。通常我们会将它们编写为C语言作为Python扩展模块。还有一些像ctypes这样的模块,允许您调用其他操作系统API。但是您的用户权限决定了API是否有效或引发异常。您是在问如何使用ctypes吗? - S.Lott
@hhh:我不知道你所说的“低级IO”是什么意思。但是所有操作都是通过API完成的。而且所有API都受到特权保护。 - S.Lott
@S.Lott:这是您在自己的答案中写的关于os.open的语句:“此函数旨在进行低级I/O。”,链接在此处:https://dev59.com/ZVbTa4cB1Zd3GeqP7AzF#5602549。 - hhh
为什么要对这个进行负投票?我认为开一个单独的问题来讨论这个窄化的话题是很有意义的。 - hhh
显示剩余5条评论
5个回答

9
Windows和Linux都将内核代码使用ring 0、用户进程使用ring 3。这样做的好处在于,用户进程可以互相隔离,即使一个进程崩溃,系统也可以继续运行。相比之下,ring 0中的代码有bug可能会导致整台机器崩溃。
Ring 0代码如此关键的原因之一是它可以直接访问硬件。相比之下,当用户模式(ring 3)进程需要从磁盘读取数据时:
1. 进程执行特殊指令告诉CPU它想要进行系统调用。 2. CPU切换到ring 0并开始执行内核代码。 3. 内核检查该进程是否被允许执行该操作。 4. 如果允许,则执行该操作。 5. 内核告诉CPU已经完成。 6. CPU切换回ring 3并将控制权返回给进程。
属于“特权”用户(例如root/Administrator)的进程与任何其他用户模式代码一样运行在ring 3中;唯一的区别在于步骤3的检查总是成功的。这是一个好事情,因为:
- 拥有root权限的进程可以崩溃而不会导致整个系统崩溃。 - 许多用户模式的特性在内核中不可用,例如可交换内存、私有地址空间等。
至于在更低的ring中运行Python代码-内核模式是一个非常不同的环境,Python解释器根本没有设计用来在其中运行,例如分配内存的过程是完全不同的。
在您提到的另一个问题中,os.open()open()最终都会进行open()系统调用,该调用检查进程是否被允许打开相应的文件并执行实际操作。

1
当Python有像OS和SYS这样的类时,它们实际上与重要的特权系统/操作系统事物没有任何关系吗?我开始感到命名约定非常具有误导性。是否有任何想法,Python是否提供一些包装器来控制特权区域的系统语言代码,例如C? - hhh
1
os 模块提供了对操作系统提供的服务的一致访问(即无论您使用 Windows、Linux 等操作系统,都是相同的),而 sys 模块提供了特定于系统的功能。ctypes 模块允许您从 Python 调用 C 函数,但大多数 C 代码在用户模式(环 3)下运行,并在需要执行特权操作时向内核发出系统调用。 - SimonJ
@hhh:Python是C语言系统代码的包装器。要控制“特权”区域,您需要特权。这就是全部。只是特权 - 没有特殊的代码。 - S.Lott
@SimonJ:sys 不是用于系统特定功能的,sys 模块包含 Python 运行时的信息和服务。您可以使用 sys 执行各种操作,如获取命令行参数、检查 Python 版本、检查解释器限制、访问 stdin/stdout/stderr 对象、注册异常钩子、加载模块内省、注册调试/分析跟踪器以及修改运行时参数(如最大堆栈深度)。 - Lie Ryan

3
我认为SimonJ的回答非常好,但是根据你的评论,似乎你还没有完全理解。首先,在启动操作系统时,你所做的就是将内核加载到内存中并说“从地址X开始执行”。内核,也就是那段代码,本质上只是一个程序,但当然没有其他东西被加载,因此如果它想要做任何事情,它必须知道特定硬件的确切命令。
你不必运行内核。实际上,如果你知道如何控制所有连接的硬件,你根本不需要内核。但是,早在很久以前,人们就意识到可能会面临许多类型的硬件,并且具有跨系统相同的接口来编程将使代码可移植,并通常有助于更快地完成任务。
因此,内核的功能是控制连接到系统的所有硬件并将其呈现在称为API(应用程序编程接口)的公共接口中。在系统上运行的程序的代码不直接与硬件交互,而是与内核交互。因此,用户空间程序不需要知道如何请求特定硬盘读取扇区0x213E或其他内容,但内核需要知道。
现在,SimonJ的答案中提供的关于ring 3的描述是如何实现用户空间的——具有隔离的、非特权进程,具有虚拟私有地址空间,不能相互干扰,以获得他所描述的好处。
这里还有另一种复杂性水平,即权限的概念。大多数操作系统都有某种形式的访问控制,其中“管理员”对系统拥有完全控制,“用户”只有一组受限选项。因此,在这种方法下,内核请求打开属于管理员的文件应该失败。运行程序的用户构成了程序的上下文,如果你愿意的话,程序可以做什么受到该用户能够做什么的限制。
除非你的意图是编写内核,否则你几乎可以在root/administrator用户的userland中完成你想要实现的大部分事情,内核不会拒绝任何向它发出的API请求。它仍然是一个用户空间程序。它仍然是一个ring 3程序。但是对于大多数(几乎所有)用途而言,这已经足够了。作为非root/administrative用户也可以实现很多内容。
这适用于Python解释器,以及通过扩展运行在该解释器上的所有Python代码。
让我们来处理一些不确定性:
  • ossys的命名是因为它们是“系统”任务(与例如urllib2不同)。它们提供了操作和打开文件的方式。但是,这些任务通过Python解释器进行,进而调用内核。
  • 我不知道有任何内核模式的Python实现。因此据我所知,没有办法编写能在内核(Linux/Windows)中运行的Python代码。
  • 有两种类型的特权:硬件访问方面的特权和内核提供的访问控制系统方面的特权。Python可以作为root/管理员运行(事实上,在Linux上许多管理GUI工具都是用Python编写的),因此在某种意义上它可以访问特权代码。
  • 编写C扩展或将C应用程序控制到Python中,表面上意味着您正在使用添加到解释器(用户空间)的代码,或者控制另一个用户空间应用程序。然而,如果您在C中编写了一个内核模块(Linux)或驱动程序(Windows),则可以从Python加载该驱动程序并通过内核API与其交互。例如,创建C中的/proc条目,然后使您的Python应用程序通过读/写将消息传递到该/proc条目(内核模块必须通过write/read处理程序来处理)。实质上,您编写要在内核空间中运行的代码,并以多种方式之一添加/扩展内核API,以便您的程序可以与该代码交互。
  • “低级”IO意味着对发生的IO类型和如何从操作系统获取数据有更多的控制。它与Python中仍然提供易于读取文件的更高级函数(以控制为代价)相比较低级。这类似于C中的read()调用和fread()fscanf()之间的区别。

健康警告:如果编写内核模块出错,最好的情况是该模块无法正确加载;最坏的情况是您的系统会崩溃/蓝屏并且您需要重新启动。

关于机器指令的最后一点我无法在此回答。这是一个完全不同的问题,具体情况视情况而定。我相信有许多能够分析这样的代码的工具,但我不是逆向工程师。但是,我知道许多这些工具(例如gdb、valgrind)——钩入二进制代码的工具不需要内核模块即可完成其工作。


1

您可以使用inpout库http://logix4u.net/parallel-port/index.php

import ctypes

#Example of strobing data out with nStrobe pin (note - inverted)
#Get 50kbaud without the read, 30kbaud with
read = []
for n in range(4):
    ctypes.windll.inpout32.Out32(0x37a, 1)
    ctypes.windll.inpout32.Out32(0x378, n)
    read.append(ctypes.windll.inpout32.Inp32(0x378))   #Dummy read to see what is going on
    ctypes.windll.inpout32.Out32(0x37a, 0)

print read

1

[注意:我错了。在现代Unix系统上,用户模式代码不能再访问ring 0。-- jc 2019-01-17]

我已经忘记了我曾经了解的关于Windows权限的一切。在我熟悉的所有Unix系统中,root用户可以访问所有ring0权限。但是我想不出任何Python模块与特权环之间的映射。


也就是说,“os”和“sys”模块不会给你任何特殊权限。你拥有它们或者没有,这取决于你的登录凭据。


等一下。我在某处读到,系统在启动期间传递了环 0,但之后访问环 0 是不可能的(但如果某些操作系统真的将环 0 命令实现到用户空间中,那么可能会有例外情况,这听起来真的很可怕)。 - hhh
作为root用户,您可以读取或写入计算机中实际存在的任何地址。我曾经通过为设备驱动程序编写main()例程并以root身份运行它们来测试设备驱动程序。这不是在ring 0吗? - jcomeau_ictx
行为良好的程序通常使用内核提供的系统服务进行I/O操作,但至少在大多数Unix系统中,这是建议性的,而非强制性的。 - jcomeau_ictx
请注意,在NT世界中,“driver”的定义指的是Ring 0级别的事物,而在其他系统中,“driver”可能仅指较低的级别。必须找到一些适当的方法来测试我是否可以在obsd中进入Ring 0,这很有趣。 - hhh
1
据我所知,大部分内核代码都在Ring 0上运行,因此在引导后在Ring 0上运行并不是不可能的,实际上每当进行系统调用时都会切换到Ring 0。不可能的是在Ring 0上运行任意用户空间可执行文件。向Ring 0添加新代码的唯一方法是使用加载内核模块机制(init_module()/finit_module()),这需要root权限。 - Lie Ryan
是的,当我写下那段话时,我的“知识”可能已经过时了,现在肯定已经过时了。 - jcomeau_ictx

0
如何在Python中访问较低的环?
ctypes
低级io用于访问较低级别的环吗?
不是。
语句“此函数旨在进行低级I/O。”是指较低级别的环还是其他内容?
其他事情。
C往往是操作系统编程中突出的语言。当Python中有OS类时,这是否意味着我可以通过该类访问C代码?
所有CPython都是用C实现的。
os模块(它不是一个类,而是一个模块)用于访问操作系统API。 C与访问操作系统API无关。 Python直接访问API。
假设我正在玩弄奇怪的机器语言代码,并且我想以某种方式理解它的含义。 Python中是否有一些工具可用于分析这些内容?
“玩耍”?
“理解它的意思”?这是你的问题。你读代码,你就能理解。Python是否有帮助无法确定。你不明白什么?
如果没有,那么我还能用Python控制一些工具来控制奇怪的机器语言吗?[评论中建议使用ctypes]
ctypes
如果Python与低级特权无关,它是否仍然提供一些包装器来控制特权?
你不能“包装”东西来控制特权。
大多数操作系统都是这样工作的。
1.您授予用户帐户特权。 2.操作系统API检查授予请求操作系统API的用户的特权。 如果用户拥有特权,则操作系统API有效。 如果用户缺少特权,则操作系统API会引发异常。
就是这样。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接