惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Jina AI
Jina AI
V
Visual Studio Blog
博客园 - 司徒正美
TaoSecurity Blog
TaoSecurity Blog
博客园 - 聂微东
IT之家
IT之家
博客园_首页
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
C
Cyber Attacks, Cyber Crime and Cyber Security
博客园 - Franky
雷峰网
雷峰网
罗磊的独立博客
S
Schneier on Security
C
Cybersecurity and Infrastructure Security Agency CISA
The Cloudflare Blog
T
Tailwind CSS Blog
B
Blog RSS Feed
H
Help Net Security
T
The Blog of Author Tim Ferriss
C
CXSECURITY Database RSS Feed - CXSecurity.com
T
Threatpost
C
CERT Recently Published Vulnerability Notes
博客园 - 三生石上(FineUI控件)
P
Palo Alto Networks Blog
I
Intezer
G
GRAHAM CLULEY
Engineering at Meta
Engineering at Meta
S
Securelist
J
Java Code Geeks
V
V2EX
Y
Y Combinator Blog
Simon Willison's Weblog
Simon Willison's Weblog
L
LINUX DO - 热门话题
云风的 BLOG
云风的 BLOG
Spread Privacy
Spread Privacy
MongoDB | Blog
MongoDB | Blog
P
Privacy International News Feed
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
B
Blog
Forbes - Security
Forbes - Security
Google Online Security Blog
Google Online Security Blog
Help Net Security
Help Net Security
S
SegmentFault 最新的问题
N
Netflix TechBlog - Medium
Webroot Blog
Webroot Blog
Microsoft Security Blog
Microsoft Security Blog
SecWiki News
SecWiki News
Scott Helme
Scott Helme
aimingoo的专栏
aimingoo的专栏
N
News and Events Feed by Topic

See you soon

哟,好久不见,无线打印 | See you soon 试试将文章版本化管理吧 | See you soon 使用 Quadlet 将 Podman 中的 Postgres 当作 systemd 服务运行 | See you soon 大他者,那个无时无刻都在盯着你的东西 | See you soon Laws of Software Engineering,软件工程定律 | See you soon 浅记多因素身份认证 | See you soon Linux 内核中的度量单位 | See you soon 重置 GPG 智能密钥 | See you soon 向 NAS 引入 samba | See you soon 无法重复键入的 Fcitx5 | See you soon ZFS 降级事故 | See you soon 记被 XanMod Kernel 和 AppArmor 联合坑的一次踩坑 | See you soon agent 的 skill 与 toolcall | See you soon 记一次服务器被挂恶意挖矿二进制 | See you soon 活着的 Arc | See you soon 令 acme.sh 使用 Cloudflare 的 DNS API 签发与续签证书 | See you soon 于 Tokio 中卸载 CPU Bound 任务 | See you soon 如我所见,梦破碎的时候 | See you soon 74LS 家族手册 | See you soon JDK Projects 备忘录 | See you soon 关于历史 | See you soon 用 curl 下载 OnePlus 的 ROM | See you soon 实用命令切片 | See you soon 再见,Oh My Zsh。 | See you soon 你不应该复用 strings.Builder | See you soon 博客的明日 | See you soon 被 AppArmor 击杀的 Dockge | See you soon AI 时代的自我 | See you soon 支持删除的布隆过滤器 | See you soon 基于栈的虚拟机与基于寄存器的虚拟机 | See you soon RVA23 包含了什么 | See you soon Rust 的边界检查是否已经有很大的进步 | See you soon 使用 Rust 编写操作系统:Barebones | See you soon 使用 Rust 编写操作系统:引言 | See you soon 编译器笔记:rope | See you soon 编译器笔记:CST | See you soon Paradoxical 札记 | See you soon 简单的相似去重算法(基于向量) | See you soon 更加现代的 PaperMC Minecraft 插件设计指南 | See you soon 简单的 CFG 语法分析方法 | See you soon 简单地使用 Caddy 实现 CORS 配置 | See you soon 让 OpenCV 可以被静态链接 | See you soon 图片搜索笔笺 | See you soon 电路板设计笔记-保护 | See you soon 使用 Rust 实现 SnowflakeId | See you soon 农夫乐事 FaQ 启示 | See you soon 使用 Rust 实现拓展系统札记 | See you soon 遗传学定律的代码实现 | See you soon EN:The Journey of Rust and Procps | See you soon ZH:Rust 与 Procps 之旅 | See you soon 使用 debootstrap 与 schroot 构建一个纯净环境 | See you soon GPG添加新的用户信息 | See you soon GSoC2024 笔记:使用 Rust 重新实现 procps | See you soon JWT 小册 | See you soon 使用密钥登录 SSH | See you soon Guava:Cache | See you soon 编译器笔记:增量编译 | See you soon Gradle秘境:添加一个类似modCompileOnly的依赖块 | See you soon Minecraft:原始经济系统设计简述 | See you soon TinyRemapper笔记 | See you soon MicroOS:进阶 | See you soon MicroOS:起步 | See you soon Swapfile 指北 | See you soon GPG 物理密钥的安装与密钥的迁移 | See you soon 用GPG签名告诉大家这就是我的提交 | See you soon DFS:深度优先搜索 | See you soon 文章翻译:从init.vim到init.lua | See you soon 目录遍历攻击 | See you soon 在树莓派上编译 OpenCV | See you soon 关于卸载BlueStacks后遇到的问题 | See you soon
如何挂载.img文件,以及如何使用QEMU模拟arm64环境 | See you soon
Krysztal Huang · 2021-08-04 · via See you soon

在上一篇中编译 OpenCV 成功之后我把整个树莓派的 TF 卡使用 dd 命令导出成了 .img 文件作为备份。我会暂时有一段时间无法接触到我的树莓派,并且我还有很多步骤没有完成。

所以我就想是否能挂载到 x86 Linux host 上进行操作?

如何 dd 出系统镜像文件?

使用大部分 Linux 发行版都自带的 dd 命令即刻。

想象一下当初你是如何使用 dd 命令制作 Linux 的 LiveCD 的?

sudo dd if=<the_path_to_ISO_file> of=/dev/sdx

其中 /dev/sdx设备文件,通常他们存在于 /dev/ 目录之下.

那我们再想一想是不是可以反过来?

于是得出了以下命令:

sudo dd if=/dev/sdx of=rpimg.img

注意,这里必须为设备文件而不是设备分区文件,除非你想备份分区。

由于 TF 卡大小为 64GiB,换算为 GB 单位则为 60GB,是非常庞大的数据量,由于 Linux 系统调度的特性所以卡顿是很正常的现象。我的 TF 卡搭配 USB3.0 读卡器经过测试这个过程将会持续十分钟。

奇怪的想法

在思考是否可以在 x86 Linux host 上进行操作的时候我产生了一些疑问:

  • 此时的 img 文件为何种格式?
  • 是否可以使用 chroot 以及 QEMU 操作 img 文件内内容?

验证奇怪的想法

QEMU 是否可以模拟运行 arm64(aarch64)?

经过资料的查找我们可以发现树莓派所使用的 SoC 为博通 BCM2711,大架构属于 ARM v8。

因此需要查找 QEMU 现在是否可以模拟 ARM v8

在 debian 的软件包搜索当中我们发现 qemu-user-static 软件包中有如下描述

QEMU is a fast processor emulator: currently the package supports ARM, CRIS, i386, M68k (ColdFire), MicroBlaze, MIPS, PowerPC, SH4, SPARC and x86-64 emulation. By using dynamic translation it achieves reasonable speed while being easy to port on new host CPUs.

This package provides the user mode emulation binaries. In this mode QEMU can launch Linux processes compiled for one CPU on another CPU.

感觉上大概是完全可以的。

选择 user mode 的 QEMU 而不是 system mode ,原因有二

  1. 我们目标是挂载 img 并且使用 chroot 运行
  2. 这里使用 chroot jail 并不需要启动整个系统,相对而言其实是一套软件,因此是用户态。

另外这里并不是虚拟机。 chroot 本质上只是变更当前进程及其子进程的可见根路径。变更后,程序无法访问可见根目录外文件和命令。chroot 的大欺骗战术!

另外其实可以不使用 chroot,使用 Fakechroot 以及 PRoot 也是可以的

关于 PRoot 以及 Fakechroot 的用法可以参照以下链接

使用如下命令安装 qemu-user-static

sudo apt install -y qemu-user-static

他会自动配置 binary handle,如果执行的二进制文件架构是 qemu 支持的但是不是本机架构的话会自动使用 qemu 运行。

img 文件分析

逻辑

还记得上文中所提到的设备文件吗?在 Linux 当中把和设备交互的地方抽象成为了一个文件。

再联想一下 Linux 系统(乃至于各种 unix like 系统)当中的一个很大的特性:一切皆文件

我们是从 TF 卡中完整的复制内容到 img 文件,那么是否在这个 img 文件当中包含了分区信息?

如果说我们知道了 img 文件当中的分区的起始点与结束点,那么他不就可以被抽象成为类似设备文件一样的东西了吗?

验证由 dd 设备文件而来的 img 文件是否拥有完整的分区格式

祭出我们常用的fdisk命令,其堪称操作设备文件的瑞士军刀。

对 img 文件使用以下命令。我的 img 文件名为 rpios.img。

他输出了以下内容

Disk rpimg.img: 59.69 GiB, 64088965120 bytes, 125173760 sectors

Units: sectors of 1 * 512 = 512 bytes

Sector size (logical/physical): 512 bytes / 512 bytes

I/O size (minimum/optimal): 512 bytes / 512 bytes

Disklabel type: dos

Disk identifier: 0xf9f150b0

Device Boot Start End Sectors Size Id Type

rpimg.img1 8192 532479 524288 256M c W95 FAT32 (LBA)

rpimg.img2 532480 125173759 124641280 59.4G 83 Linux

fdisk 对 img 文件成功读取了分区信息,并且认为他是一个合法的设备

挂载 img 文件,使其内部可以被操作

man pages上写道

The loop device is a block device that maps its data blocks not to a physical device such as a hard disk or optical disk drive, but to the blocks of a regular file in a filesystem or to another block device. This can be useful for example to provide a block device for a filesystem image stored in a file, so that it can be mounted with the mount(8) command.

其上大概解释就是loop device(回环设备)是由块设备映射成的文件,

mount命令的 man pages 有如下一段解释

If no explicit loop device is mentioned (but just an option `-o loop’ is given), then mount will try to find some unused loop device and use that, for example

mount /tmp/disk.img /mnt -o loop

但是他挂载的 img 文件是单分区的,而我们的 img 文件含有多个分区

This type of mount knows about three options, namely loop, offset and sizelimit, that are really options to losetup(8). (These options can be used in addition to those specific to the filesystem type.)

所以如果我们镜像如果是多分区,我们可以使用 offset 和 sizelimit 参数来挂载。由于是最后一个分区所以我们就偷懒不写 sizelimit 了。

因此我们的命令就会如下

mkdir mp # 新建 img 文件挂载到的文件夹,把分区挂在这里

sudo mount ./rpimg.img ./mnt -o loop,offset=$((532480 * 512)) -t ext4

有可能遇到 loop 设备被占用的情况,这个时候我们需要使用 losetup -f 命令获取哪个 loop 设备可用。

由于第一个分区是启动分区而且我们不操作他,所以我们不挂载他。

这里输入成功后是无回显的,证明他成功了

于是我们ls mnt看看

bin boot data dev etc home lib lost+found media mnt opt proc root run sbin srv sys tmp usr var

是完整的根目录结构,意味着我们的目的成功了!

使挂载 img 后的内容成为 chroot jail

debian wiki 上写了 chroot 的用法(英文)

同时 arch wiki 上也有 chroot 用法的介绍

最关键的部分如下

  • 绑定 /sys 到 rootfs 的 sys 文件夹
  • 绑定 /dev 到 rootfs 的 dev 文件夹
  • 绑定 /proc 到 rootfs 的 proc 文件夹
  • 复制本机的 DNS 服务器配置文件到 rootfs

其中由于树莓派系统的 rootfs 自带了 DNS 配置文件,所以我们不需要再复制本机的 DNS 配置文件。

因此我们可以得出以下命令

cd mnt # 切换到 img 文件的挂载文件夹

sudo mount --bind /proc proc # 挂载 proc

sudo mount --bind /dev dev # 挂载 dev

sudo mount --bind /sys sys # 挂载 sys

#cp -L /etc/resolv.conf etc/resolv.conf # 复制 DNS 配置文件,可选

最后我们尝试使用 chroot 启动他。

可以看到标识符发生了变化,那么意味着我们成功的挂载了 img 文件并且进入了其中。

卸载 img 文件的挂载

当我们对 img 文件操作完毕后需要卸载 img 文件的挂载才算是完成了工作。

当然最简单的方法就是重启系统了,全自动卸载。我们这里使用手动卸载节约时间

sudo losetup -d /dev/loop0 # 卸载回环设备

sudo umount ./mnt/dev # 卸载 dev 绑定

sudo umount ./mnt/proc # 卸载 proc 绑定

sudo umount ./mnt/sys # 卸载 sys 绑定

sudo umount ./mnt # 卸载 img 文件挂载

sudo sync # 同步更改到磁盘

OK,大功告成。