返回

文章详情

剖析苹果的稀疏图像格式 (ASIF)

Hacker News2026年6月28日 16:10

2026-06-18 · 18分钟阅读 · Erik Schamper 在2025年的WWDC上,苹果公司宣布了macOS 26 Tahoe。macOS Tahoe中的新特性之一是新的磁盘映像格式:ASIF。ASIF是专为虚拟机使用而设计的(其文档位于虚拟化框架下),它从现有的虚拟磁盘格式中汲取了很多灵感。实际上,这意味着它又是一个稀疏虚拟磁盘格式,并且功能与稀疏的VMDK、VHDX或QCOW2文件非常相似(对于不熟悉的人来说,它允许您以更小的“稀疏”方式存储大磁盘或文件)。在macOS Tahoe发布之前不久(2025年底),我觉得写一个ASIF文件的解析器会是一个有趣的练习。自那以后已经过了一段时间,但我想回过头来展示我如何处理这些类型问题的过程。也许有些不熟悉逆向工程文件格式的人可以学到一两件事。出于这个原因,您会在本文中偶尔发现一些“研究笔记”,其中包含一些额外的见解。让我们创建一个测试文件,使用苹果文档中列出的命令,写入测试模式并开始:研究笔记 在测试方面,我通常喜欢写入测试模式,以便验证内容与“偏移量”匹配。在这种情况下,基本上就是编号的1 MiB字节块。确实有更好的测试模式,但对于初步查看文件格式,填满文件也很重要。拥有可预测和可验证的模式可以使后续步骤更容易。❯ diskutil image create blank --fs none --format ASIF --size 1GiB file file.asif created ❯ diskutil image attach -nomount file.asif /dev/disk4 ❯ python3 Python 3.14.0 (main, Oct 7 2025, 09:34:52) [Clang 17.0.0 (clang-1700.3.19.1)] on darwin 输入 "help", "copyright", "credits" 或 "license" 以获取更多信息。>>> fh = open("/dev/disk4", "wb") >>> for i in range(255): ... fh.write(bytes([i] * 1024 * 1024)) >>> fh.close() ❯ hdiutil detach disk4 "disk4" 已弹出。直观的十六进制转储 如同往常一样,我们开始通过直观的十六进制转储观察是否能分辨出一些细节。❯ xxd file.asif | head -5 0000 0000 73 68 64 77 00 00 00 01 00 00 02 00 00 00 00 00 s h d w · · · · · · · · · · · · 0000 0010 00 00 00 00 00 00 02 00 00 00 00 00 00 04 14 00 · · · · · · · · · · · · · · · · 0000 0020 8a f9 ea d2 cf 38 49 c0 8e ec 00 95 cf 5c 78 99 · · · · · 8 I · · · · · · \\\ x · · · 0000 0030 00 00 00 00 00 1d cd 65 00 00 08 00 00 00 00 00 · · · · · · · e · · · · · · · · 0000 0040 00 10 00 00 02 00 00 00 00 00 00 00 ff ff ff ff · · · · · · · · · · · · · · · · 我们可以立即发现某种文件魔法,后跟一些大端格式的整数。研究笔记 每当您在逆向工程文件格式时看到一些魔法字节,在线搜索任何可用信息总是个好主意。我通常搜索字符串/字节表示、大端十六进制和小端十六进制的组合,在各种搜索引擎(Google、GitHub、VirusTotal Retrohunt)中查找。在这种情况下,我没有找到任何有用的信息。至于“寻找字节序”或整数字段,这几乎就像骑自行车一样,经过一段时间就会掌握。我想有一个小提示就是从左到右以4字节(uint32)的块进行扫描,然后是8字节(uint64),再可能分成更小的块(uint16甚至uint8),直到您可以解析出合理的看起来的整数(十六进制的圆基数,或者与文件中的偏移量交叉参考,选择性地乘以您发现的其他值)。如果您看到“自然顺序”格式的整数,则是大端。如果看起来是反向的,则是小端。让我们快速输入一个粗略的结构,做出最佳猜测实际整数的宽度,用dissect.cstruct进一步检查:# /// 脚本 # requires-python = ">=3.10" # 依赖 = ["dissect.cstruct"] # /// import sys from dissect.cstruct import cstruct , dumpstruct asif_def = """ struct header { char magic[4]; uint32 field4; uint32 field8; uint32 fieldC; uint64 field10; uint64 field18; char field20[16]; uint64 field30; uint64 field38; uint32 field40; uint32 field44; uint32 field48; uint32 field4C; }; """ c_asif = cstruct ( asif_def , endian = ">" ) with open ( sys . argv [ 1 ], "rb" ) as fh : header = c_asif . header ( fh ) dumpstruct ( header ) 0000 0000 73 68 64 77 00 00 00 01 00 00 02 00 00 00 00 00 s h d w · · · · · · · · · · · · 0000 0010 00 00 00 00 00 00 02 00 00 00 00 00 00 04 14 00 · · · · · · · · · · · · · · · · 0000 0020 8a f9 ea d2 cf 38 49 c0 8e ec 00 95 cf 5c 78 99 · · · · · 8 I · · · · · · \\\ x · · · 0000 0030 00 00 00 00 00 1d cd 65 00 00 08 00 00 00 00 00 · · · · · · · e · · · · · · · · 0000 0040 00 10 00 00 02 00 00 00 00 00 00 00 ff ff ff ff · · · · · · · · · · · · · · · · header magic[4] 0x0000 4字节 b'shdw' field4 0x0004 4字节 0x1 field8 0x0008 4字节 0x200 fieldC 0x000c 4字节 0x0 field10 0x0010 8字节 0x200 field18 0x0018 8字节 0x41400 field20[16] 0x0020 16字节 b'\x8a\xf9\xea\xd2\xcf8I\xc0\x8e\xec\x00\x95\xcf\x5c\x78\x99

赞助内容

NordVPN Next-gen Antivirus

本站免费、广告极少。如果觉得有帮助,可以请我们喝杯咖啡 —— 任何金额都对持续运营有实际帮助。

请我喝杯咖啡