AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • 主页
  • 系统&网络
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • 主页
  • 系统&网络
    • 最新
    • 热门
    • 标签
  • Ubuntu
    • 最新
    • 热门
    • 标签
  • Unix
    • 最新
    • 标签
  • DBA
    • 最新
    • 标签
  • Computer
    • 最新
    • 标签
  • Coding
    • 最新
    • 标签
主页 / unix / 问题 / 461689
Accepted
rhodeo
rhodeo
Asked: 2018-08-10 15:13:27 +0800 CST2018-08-10 15:13:27 +0800 CST 2018-08-10 15:13:27 +0800 CST

x86 Linux 中的物理地址 0 包含什么?

  • 772

我不确定这个问题应该放在这里还是在reverseengineering.stackexchange.com

引用维基百科:

在 8086 处理器中,中断表称为 IVT(中断向量表)。IVT 始终驻留在内存中的同一位置,范围从 0x0000 到 0x03ff,由 256 个四字节实模式远指针(256 × 4 = 1024 字节内存)组成。

这是我在 qemu 监视器中发现的:

(qemu) xp/128xw 0
0000000000000000: 0xf000ff53 0xf000ff53 0xf000e2c3 0xf000ff53
0000000000000010: 0xf000ff53 0xf000ff53 0xf000ff53 0xf000ff53
0000000000000020: 0xf000fea5 0xf000e987 0xf000d62c 0xf000d62c
0000000000000030: 0xf000d62c 0xf000d62c 0xf000ef57 0xf000d62c
0000000000000040: 0xc0005526 0xf000f84d 0xf000f841 0xf000e3fe
0000000000000050: 0xf000e739 0xf000f859 0xf000e82e 0xf000efd2
0000000000000060: 0xf000d648 0xf000e6f2 0xf000fe6e 0xf000ff53
0000000000000070: 0xf000ff53 0xf000ff53 0xf0006aa4 0xc0008930
0000000000000080: 0xf000ff53 0xf000ff53 0xf000ff53 0xf000ff53
0000000000000090: 0xf000ff53 0xf000ff53 0xf000ff53 0xf000ff53
00000000000000a0: 0xf000ff53 0xf000ff53 0xf000ff53 0xf000ff53
00000000000000b0: 0xf000ff53 0xf000ff53 0xf000ff53 0xf000ff53
00000000000000c0: 0xf000ff53 0xf000ff53 0xf000ff53 0xf000ff53
00000000000000d0: 0xf000ff53 0xf000ff53 0xf000ff53 0xf000ff53
00000000000000e0: 0xf000ff53 0xf000ff53 0xf000ff53 0xf000ff53
00000000000000f0: 0xf000ff53 0xf000ff53 0xf000ff53 0xf000ff53
0000000000000100: 0xf000ec59 0xf000ff53 0xf000ff53 0xc0006730
0000000000000110: 0xf000ff53 0xf000ff53 0xf000ff53 0xf000ff53
0000000000000120: 0xf000ff53 0xf000ff53 0xf000ff53 0xf000ff53
0000000000000130: 0xf000ff53 0xf000ff53 0xf000ff53 0xf000ff53
0000000000000140: 0xf000ff53 0xf000ff53 0xf000ff53 0xf000ff53
0000000000000150: 0xf000ff53 0xf000ff53 0xf000ff53 0xf000ff53
0000000000000160: 0xf000ff53 0xf000ff53 0xf000ff53 0xf000ff53
0000000000000170: 0xf000ff53 0xf000ff53 0xf000ff53 0xf000ff53
0000000000000180: 0x00000000 0x00000000 0x00000000 0x00000000
0000000000000190: 0x00000000 0x00000000 0x00000000 0xf000ff53
00000000000001a0: 0xf000ff53 0xf000ff53 0xf000ff53 0xf000ff53
00000000000001b0: 0xf000ff53 0xf000ff53 0xf000ff53 0xf000ff53
00000000000001c0: 0xf000d611 0xf000ec4e 0xf000ec4e 0xf000ec4e
00000000000001d0: 0xf000d61a 0xf000d623 0xf000d608 0xf000ec4e
00000000000001e0: 0xf000ff53 0x00000000 0xf000ff53 0xf000ff53
00000000000001f0: 0xf000ff53 0xf000ff53 0xf000ff53 0xf000ff53

我不确定如何理解这些价值观。它看起来不像一个中断描述符表(取消引用这些值会给出所有空值)。那么我到底在看什么?

memory x86
  • 3 3 个回答
  • 2576 Views

3 个回答

  • Voted
  1. Best Answer
    JdeBP
    2018-08-11T03:42:19+08:002018-08-11T03:42:19+08:00

    无论您的固件包含什么。

    在理想的现代系统上,处理器根本不会进入实模式,正如我在这篇题为“现代 64 位英特尔芯片 PC 以何种模式运行引导扇区? ”的 SU 问答中所解释的那样?,物理内存的第一个 KiB 与 Johan Myréen 在这里的另一个答案中所说的一样无关紧要。但是许多现代固件(仍然)具有兼容性支持,这意味着

    • 他们可以从保护模式退回(是的,退回,因为他们直接从虚幻模式进入保护模式),以便运行为实模式编写的系统软件,例如旧式 PC/AT 启动程序MBR 和 VBR;和
    • 它们提供了旧的实模式固件 API,并为这些 API 设置了上述系统软件所依赖的所有数据结构。

    这些数据结构之一是实模式 IVT。旧的实模式固件 API 基于int指令,实模式 IVT 由固件填充,作为其初始化的一部分,并带有指向这些指令的各种固件处理例程的指针。

    保护模式系统软件不需要旧的实模式固件API,并且从不以实模式运行处理器,因此物理内存的前1KiB中的实模式IVT未被使用。(记住,v8086 保护模式不寻址物理地址 00000000 及以上。它寻址逻辑地址 00000000 及以上,由页表转换。)在现代 EFI 系统中,固件将物理内存的内存映射移交给操作系统引导程序,告诉它哪些部分保留给固件用于其自身的保护模式 API 目的,以及操作系统可以自由继续使用哪些部分作为其物理内存池。理论上,物理内存的第一页可以属于后一类。

    在实践中,首先,固件通常将物理内存的第一页标记为“引导服务代码”,这意味着操作系统可以声明它并继续将其用作其物理内存池的一部分,但仅在引导之后- EFI 固件的时间服务已被操作系统关闭,固件减少为仅提供其运行时服务。add_efi_memmap在Finnbarr P. Murphy 显示的 Linux 内核日志(带有选项)中可以看到一个示例:

    [0.000000] efi:mem00:类型=3,attr=0xf,范围=[0x0000000000000000-0x0000000000001000)(0MB)
    xe 用另一个程序以更易于阅读的形式解码为:

    [#00] 类型:EfiBootServicesCode Attr:0xF
          物理:0000000000000000-0000000000001000
          虚拟:0000000000000000-0000000000001000

    其次,在实践中,Linux 明确忽略了这个物理内存范围,即使固件说它可以继续使用它。您会发现,在 EFI 和非 EFI 固件上,一旦 Linux 拥有物理内存映射,它就会对其进行修补(在名为 的函数中trim_bios_range),从而产生内核日志消息,例如:

    [ 0.000000] e820: 更新 [mem 0x00000000-0x00000fff] 可用 ==> 保留

    这不是为了应对现代 EFI 固件,实模式 IVT 不是固件 API 的一部分,而是为了应对旧的 PC98 固件,它是固件 API 的一部分,但固件会报告它(通过相同的 API)作为物理内存,可以被操作系统轻松覆盖。

    因此,虽然从理论上讲,物理内存范围可以包含任意代码或数据,具体取决于内核内存分配器和按需分页虚拟内存的瞬时需求;实际上,Linux 只是保持不变,因为固件最初设置它。

    在您的系统上,固件已经用实模式 IVT 条目填充它。当然,实模式 IVT 条目只是 16:16 远指针,如果您使用 2 字节 hexdump 查看内存,您实际上可以非常清楚地看到这一点。一些例子:

    • 大多数 IVT 条目指向 F000:FF53,这是实模式固件 ROM 区域中的地址。这可能是一个虚拟的例程,只不过是一个iret.
    • IVT 条目 1E指向 F000:6AA4,这是同一 ROM 区域中的一个表。
    • IVT 条目 1F指向 C000:8930,实模式视频 ROM 固件区域中的一个表。
    • IVT 条目 43指向 C000:6730,实模式视频 ROM 固件区域中的另一个表。

    进一步阅读

    • Finnbarr P. Murphy (2012-08-18)。UEFI 内存 V E820 内存。fpmurphy.com。
    • 现代 64 位 Intel 芯片 PC 以什么模式运行引导扇区?
    • 10
  2. Johan Myréen
    2018-08-10T23:01:47+08:002018-08-10T23:01:47+08:00

    最初的 8086 处理器架构(在 80286+ 处理器中实现为实模式)与在保护模式下运行的 Linux 无关。物理地址 0 处没有中断向量表,而是使用包含中断描述符的中断描述符表。IDT 可以位于内存中的任何位置。

    Linux 内核从固件(BIOS 或 EFI)获取物理内存映射,它告诉哪些物理内存页帧可用,哪些是保留的或不存在的。可用页框的范围不是连续的,但通常有很大的漏洞。传统上,x86 Linux 内核跳过了物理内存的启动,即使它被标记为可用。因此,Linux 内核不使用物理地址 0。

    • 7
  3. slm
    2018-08-10T16:15:42+08:002018-08-10T16:15:42+08:00

    转储内存

    这是在系统内部转储内存内容与必须在外部进行的另一种方法:

    $ head /dev/mem | hexdump -C
    00000000  53 ff 00 f0 53 ff 00 f0  53 ff 00 f0 53 ff 00 f0  |S...S...S...S...|
    00000010  53 ff 00 f0 53 ff 00 f0  cc e9 00 f0 53 ff 00 f0  |S...S.......S...|
    00000020  a5 fe 00 f0 87 e9 00 f0  53 ff 00 f0 46 e7 00 f0  |........S...F...|
    00000030  46 e7 00 f0 46 e7 00 f0  57 ef 00 f0 53 ff 00 f0  |F...F...W...S...|
    00000040  22 00 00 c0 4d f8 00 f0  41 f8 00 f0 fe e3 00 f0  |"...M...A.......|
    00000050  39 e7 00 f0 59 f8 00 f0  2e e8 00 f0 d4 ef 00 f0  |9...Y...........|
    00000060  a4 f0 00 f0 f2 e6 00 f0  6e fe 00 f0 53 ff 00 f0  |........n...S...|
    00000070  ed ef 00 f0 53 ff 00 f0  c7 ef 00 f0 ed 57 00 c0  |....S........W..|
    00000080  53 ff 00 f0 53 ff 00 f0  53 ff 00 f0 53 ff 00 f0  |S...S...S...S...|
    ...
    ...
    000afea0  00 00 00 00 00 00 00 00  aa aa aa 00 aa aa aa 00  |................|
    000afeb0  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
    *
    000b0000  ff ff ff ff ff ff ff ff  ff ff ff ff ff ff ff ff  |................|
    *
    000c0000  55 aa 40 e9 62 0a 00 00  00 00 00 00 00 00 00 00  |[email protected]...........|
    000c0010  00 00 00 00 00 00 00 00  00 00 00 00 00 00 49 42  |..............IB|
    

    分析

    000c0000 以上的部分可能与引导加载程序有关。为什么我会怀疑这个?位置处的代码 55aah000c0000通常可以作为内存中的标记,用于触发 BIOS 运行辅助引导加载程序等内容。

    参考:引导签名 - BIOS

      SS#1

    但是,鉴于此 55aah 出现在 c0000h-effffh 范围内,这部分很可能是 PNP 扩展标头:

    参考:BIOS 引导规范

    3.3 具有 PnP 扩展头的设备

    所有带有选项 ROM 的 IPL 设备都必须包含一个有效的选项 ROM 标头,该标头位于系统存储器地址 C0000h 和 EFFFFh 之间,边界为 2k,并以 55AAh 开头。仅当设备具有 PnP 扩展头时才能控制设备的启动。扩展头的地址位于偏移量 +1Ah 的标准选项 ROM 头中,包含用于配置器件的重要信息。它还包含指向设备选项 ROM(BCV 或 BEV)中代码的指针,BIOS 将调用这些代码以从设备启动。有关 PnP 扩展头的结构,请参见附录 A。具有 PnP 扩展头的 IPL 设备可以通过两种方式启动。它必须包含 BCV 或 BEV。

    53 岁...

    至于开头的53ffh数据。我不清楚那实际上是什么。进一步研究它很可能是在 BIOS 的 MBR 引导加载移交给 Linux 内核引导之后 Linux 内核在那里写的东西。

    通常,引导加载程序会将内核加载到内存中,然后跳转到内核。然后内核将能够回收引导加载程序使用的内存(因为它已经执行了它的工作)。但是,可以在引导扇区中包含 OS 代码并在 OS 启动后保持驻留

    进一步挖掘,我能够从一篇名为:通过 /dev/mem 进行恶意代码注入的研究论文中找到这一段:

    1 内存设备

    /dev/mem 是物理可寻址内存的驱动程序接口。mem 和 kmem 的初衷都是为了帮助调试内核。我们可以像使用常规字符设备一样使用该设备,使用 lseek() 来选择地址偏移量。kmem 设备类似,但在虚拟寻址的上下文中提供内核内存的映像。Xorg 服务器利用 mem 设备访问 VESA 视频内存以及位于物理地址 0x00000000 的 BIOS ROM 中断向量表 (IVT) 以在 VM86 模式下操作视频模式。DOSEMU 还使用它来访问 BIOS IVT,以便能够为各种任务(磁盘读取、打印到控制台等)进行 BIOS 中断。

    参考

    • 如何从 linux 系统转储内存映像?
    • 如何在 Linux 中转储物理内存?
    • 主引导记录
    • Compaq Computer Corporation Phoenix Technologies Ltd. Intel Corporation BIOS 引导规范版本 1.01 1996 年 1 月 11 日
    • Linux 内存分析 - forensic wiki
    • X86 程序集/引导加载程序
    • 4

相关问题

  • 堆什么时候用于动态内存分配?

  • RAM清理操作无需重新启动

  • 来自“git status -z -u”的高内存使用?

  • 内存资源监控程序

  • 进程是否可以分配高速缓存,以便内核在必要时可以占用它?

Sidebar

Stats

  • 问题 205573
  • 回答 270741
  • 最佳答案 135370
  • 用户 68524
  • 热门
  • 回答
  • Marko Smith

    如何将 GPG 私钥和公钥导出到文件

    • 4 个回答
  • Marko Smith

    ssh 无法协商:“找不到匹配的密码”,正在拒绝 cbc

    • 4 个回答
  • Marko Smith

    我们如何运行存储在变量中的命令?

    • 5 个回答
  • Marko Smith

    如何配置 systemd-resolved 和 systemd-networkd 以使用本地 DNS 服务器来解析本地域和远程 DNS 服务器来解析远程域?

    • 3 个回答
  • Marko Smith

    如何卸载内核模块“nvidia-drm”?

    • 13 个回答
  • Marko Smith

    dist-upgrade 后 Kali Linux 中的 apt-get update 错误 [重复]

    • 2 个回答
  • Marko Smith

    如何从 systemctl 服务日志中查看最新的 x 行

    • 5 个回答
  • Marko Smith

    Nano - 跳转到文件末尾

    • 8 个回答
  • Marko Smith

    grub 错误:你需要先加载内核

    • 4 个回答
  • Marko Smith

    如何下载软件包而不是使用 apt-get 命令安装它?

    • 7 个回答
  • Martin Hope
    rocky 如何将 GPG 私钥和公钥导出到文件 2018-11-16 05:36:15 +0800 CST
  • Martin Hope
    Wong Jia Hau ssh-add 返回:“连接代理时出错:没有这样的文件或目录” 2018-08-24 23:28:13 +0800 CST
  • Martin Hope
    Evan Carroll systemctl 状态显示:“状态:降级” 2018-06-03 18:48:17 +0800 CST
  • Martin Hope
    Tim 我们如何运行存储在变量中的命令? 2018-05-21 04:46:29 +0800 CST
  • Martin Hope
    Ankur S 为什么 /dev/null 是一个文件?为什么它的功能不作为一个简单的程序来实现? 2018-04-17 07:28:04 +0800 CST
  • Martin Hope
    user3191334 如何从 systemctl 服务日志中查看最新的 x 行 2018-02-07 00:14:16 +0800 CST
  • Martin Hope
    Marko Pacak Nano - 跳转到文件末尾 2018-02-01 01:53:03 +0800 CST
  • Martin Hope
    Kidburla 为什么真假这么大? 2018-01-26 12:14:47 +0800 CST
  • Martin Hope
    Christos Baziotis 在一个巨大的(70GB)、一行、文本文件中替换字符串 2017-12-30 06:58:33 +0800 CST
  • Martin Hope
    Bagas Sanjaya 为什么 Linux 使用 LF 作为换行符? 2017-12-20 05:48:21 +0800 CST

热门标签

linux bash debian shell-script text-processing ubuntu centos shell awk ssh

Explore

  • 主页
  • 问题
    • 最新
    • 热门
  • 标签
  • 帮助

Footer

AskOverflow.Dev

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve