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

推荐订阅源

博客园_首页
The GitHub Blog
The GitHub Blog
美团技术团队
Know Your Adversary
Know Your Adversary
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
The Register - Security
The Register - Security
Stack Overflow Blog
Stack Overflow Blog
Attack and Defense Labs
Attack and Defense Labs
G
Google Developers Blog
I
InfoQ
博客园 - 司徒正美
T
Troy Hunt's Blog
Google DeepMind News
Google DeepMind News
J
Java Code Geeks
MongoDB | Blog
MongoDB | Blog
博客园 - 聂微东
A
About on SuperTechFans
云风的 BLOG
云风的 BLOG
S
Security Affairs
M
MIT News - Artificial intelligence
Simon Willison's Weblog
Simon Willison's Weblog
K
KPMG report finds enterprise disconnect between AI and its ROI | CIO
T
Tailwind CSS Blog
量子位
Vercel News
Vercel News
月光博客
月光博客
V
Vulnerabilities – Threatpost
N
News and Events Feed by Topic
Hugging Face - Blog
Hugging Face - Blog
酷 壳 – CoolShell
酷 壳 – CoolShell
L
LangChain Blog
D
Darknet – Hacking Tools, Hacker News & Cyber Security
L
LINUX DO - 最新话题
F
Full Disclosure
The Hacker News
The Hacker News
Hacker News: Ask HN
Hacker News: Ask HN
T
Tor Project blog
A
Arctic Wolf
Application and Cybersecurity Blog
Application and Cybersecurity Blog
Forbes - Security
Forbes - Security
IT之家
IT之家
Apple Machine Learning Research
Apple Machine Learning Research
B
Blog
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
Y
Y Combinator Blog
GbyAI
GbyAI
B
Blog RSS Feed
V
Visual Studio Blog
T
The Blog of Author Tim Ferriss
F
Fortinet All Blogs

博客园_首页

Milvus 和 PGVector,哪个更好? OpenClaw 已过时?在 VS Code 中运行 Hermes Agent! 分享一下笔者的 Mac 装机必备软件 第30篇文章:一个大三计科生的自白 Manim如何在数学公式中完美显示中文? Docker 部署 RocketMQ 5 并发编程核心概念辨析 C#事务处理最佳实践:别再让“主表存了、明细丢了”的破事发生 CLI 是什么?为什么大厂突然集体卷命令行? 【从0到1构建一个ClaudeAgent】协作-自主Agent UIImageView 设置图片不生效的原因排查 最小二乘问题详解20:无先验约束下的增量式SFM自由网平差 痞子衡嵌入式:大话双核i.MXRT1180之XIP应用里借助MU实现可靠Flash IAP的方法 AI Chat 封装, SemanticKerne.AiProvider.Unified 已发布 Windows下右键编辑js文件无法打开记事本——在注册表中使用环境变量 在后台服务中使用 Scoped 服务,为什么总是报错? H200 安装驱动并使用sglang启动模型 wireshark 抓包Trap上报告警内容 我用 AI 辅助开发了一系列小工具(2):图片压缩工具 [A Primer On MC and CC] 2.1 Memory Consistency 1 - 指令重排序和 SC 模型 Oracle数据库SCN推进技术详解与实践指南 玩转控件:封装个带图片的Label控件 Claude Code 4.7 真正该升级的不是模型,而是你的工作流 前端小白一句话,AI 帮我做了个颜值拉满的桌面媒体播放器。当代码不再是门槛,一句话编程就是现实。 5. WorkBuddy: 小龙虾的灵魂三件套,让你的小龙虾不只是工具 SQLite 分片方案实战:三种分片策略的深度对比 告别简陋 UI!一款基于 Fluent Design 和基于 WinUI 的开源免费、现代化的 Avalonia UI 控件库 关于二进制排列组合枚举的总结 AI开发-python-LangGraph框架(3-27-LangGraph从零实现大模型智能决策工作流) ElasticSearch主分片和副本分片概念详解 【002】HTTPS 粗解:证书、TLS 握手与对后端配置的影响 Hermes Agent 一周暴涨五万 Star,但我劝你别急着追 明明连接的是Redis的DB0,为什么能查到DB3的数据? 【从0到1构建一个ClaudeAgent】协作-Agent团队 熟悉电子元器件之后,电子小白下一步该怎么走? MAF快速入门(23)通过C#类定义Skills .NET 高级开发 | 手写一个对象映射框架 FastAPI数据库ORM怎么选?我肝了三个Demo后,终于不再纠结了 mysqldump 参数拾遗:在遗忘与铭记之间 C# .NET 周刊|2026年3月5期 Claude code入门 - 陈彦斌 一文学习入门 ThingsBoard 开源物联网平台 GitHub 热门项目 | 2026年04月16日 如何为GIT设置全局勾子,为每次提交追加信息 Number.isFinite和isFinite与isNaN()和Number.isNaN的区别 PortSwigger SQL注入LAB2 推荐一个测试人必备的Skills,从功能到性能全搞定(附详细实操和安装下载方式) 筑基期:掌握Odoo基础核心知识点02(Odoo XML 开发方式详解) GLM模型这么火,咱们用vllm也咧一个呗! 深入理解 AbortController:从底层原理到跨语言设计哲学 字符串学习笔记 多租户系统框架的基础模块设计和分析设计 Apache SeaTunnel Zeta 为什么能做到“又快又稳”? AI开发-python-LangGraph框架(3-26-LangGraph基本概念及第一个简单样例) Vue 3 组件通信,别只会用 Props 和 Emits 了,这几个狠活儿你得看看 ElasticSearch7.X版本配置密码 用Manim实现动态交点计算--从一个动点问题说起 团结引擎+Addressable+Instant Game打包抖音小游戏 function call 实战:让 LLM 自动判断 pod 异常、调用日志工具并完成故障分析 bubseek —— 让 Agent 的足迹,变成团队的洞察 通过 C# 读取并导出 PDF 书签 如何用 GitHub Actions 实现 Steam 自动化发布 【从0到1构建一个ClaudeAgent】并发-后台任务 .NET 高级开发 | 定制 ASP.NET Core 框架 电子小白:什么是运算放大器(运放) zero2Agent:面向大厂面试的 Agent 工程教程,从概念到生产的完整学习路线 堆上的ORW HC32F460 USB CDC通信异常:非对齐访问异常排查 20260413-Hyperbridge 攻击事件:发生在默克尔山上的验证绕过 那些喊着AI 要淘汰你的人,正在靠你的焦虑赚大钱! 深度学习进阶(八)Swin Transformer 最小二乘问题详解19:带先验约束的增量式SFM优化与实现 SnapTranslate 3.0 正式发布:全局划词翻译 + 完整英语学习闭环,一站式搞定查词、记词、复习 工作的意义、工作的困难认知再思考 .NET + AI 进阶实战:基于类的技能开发 - 打造可治理的 Agent 能力模块 【从0到1构建一个ClaudeAgent】规划与协调-技能 上周热点回顾(4.6-4.12) 电子小白的工具三件套:面包板、杜邦线、万能板 单表五亿数据的查询优化 | Mysql、StarRocks 2. WorkBuddy:从“我是谁”到“帮我干活” C# 如何减少代码运行时间:7 个实战技巧 基于HelixToolkit.SharpDX 渲染3D模型 - 笺上知微 从零开始的双臂具身VLA起源及现阶段发展综述 - SkyXZ 记对 xonsh shell 的使用, 脚本编写, 迁移及调优 - pluvium27 受够了Vibe Coding的失控?换个起点,让AI事半功倍 从开始配置漏洞环境到漏洞复现流程 - 難しい 关于10年工作经验的程序员对OpenClaw的实战经验分享以及看法 - 虚无境 Any metadata 的内存布局 C# .NET 周刊|2026年3月2期 - InCerry 我帮你测过了,测试圈排名第二的 Skill 依然很牛逼 Skill Discovery | 无监督技能发现的经典工作总结 - MoonOut 上下文工程是什么?过时了么?一文讲明白! - 一枫说码 开了 TUN 模式还是直连?90% 的人都踩过这个坑 AScript扩展多种脚本语言 - rockey627 AI 学习笔记:Agent 的记忆机制 你能被装进一个文件里吗?——7 万人把同事"蒸馏"成了 AI - 我没有三颗心脏 Claude Code 通关手册(七):给 AI 装上技能包——Skills 完全指南 - 暮色之狐 在浏览器中快速编辑代码:VSCode Web 集成实践 - Newbe36524 蒸馏自己 skill?基于 Deepseek 的蒸馏器,丐版蒸馏方式,简单便捷 - To_Carpe_Diem Spring AI Aliababa和AgentScope,哪个更好? - 苏三说技术
Plist 二进制格式
chaoguo1234 · 2026-04-19 · via 博客园_首页

1 Plist 存储格式

Plist 文件有3种存储格式:

  • xml
  • JSON
  • 二进制

使用plutil -convert <fmt>命令可以在这3种格式之间相互转换。

<fmt>分别对应上面3种存储格式:

  • xml1

  • json

  • binary1

同时如果输出到控制台,<fmt>还可以选择是按照OC还是Swift的方式进行输出:

// 按照 OC 输出
MacBook-Pro:~ user$ plutil -convert objc -o - xxxx.plist
/// Generated from xxxx.plist
__attribute__((visibility("hidden")))
NSDictionary * const xxxx = @{
    @"BuildVersion" : @"50",
    @"CFBundleShortVersionString" : @"4.13",
    @"CFBundleVersion" : @"3146.1.2",
    @"ProjectName" : @"Notes",
    @"SourceVersion" : @"3146001002000000",
};

// 按照 Swift 输出
MacBook-Pro:~ user$ plutil -convert swift -o - xxxx.plist
/// Generated from xxxx.plist
let xxxx = [
    "BuildVersion" : "50",
    "CFBundleShortVersionString" : "4.13",
    "CFBundleVersion" : "3146.1.2",
    "ProjectName" : "Notes",
    "SourceVersion" : "3146001002000000",
]

上面命令中的-o -表示要输出到控制台。

2 Plist 二进制格式

Plist二进制格式描述在苹果CF代码库中的CFBinaryPList.c中。

Plist二进制格式整体如下:

Plist

从图上可以看到,HeaderTrailer的大小是固定的。

ObjectsOffset-Table部分是可变的。

下面给出了一个二进制Plist的内容,相关部分已经用不同颜色进行了区分:

Plist-Binary

将二进制Plist打印为xml输出到控制台的内容为:

MacBook-Pro:~ user$ plutil -convert xml1 -o - xxxx.plist
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
	<key>BuildVersion</key>
	<string>50</string>
	<key>CFBundleShortVersionString</key>
	<string>4.13</string>
	<key>CFBundleVersion</key>
	<string>3146.1.2</string>
	<key>ProjectName</key>
	<string>Notes</string>
	<key>SourceVersion</key>
	<string>3146001002000000</string>
</dict>
</plist>

可以将xml内容和二进制内容对照着看。

Header总共有8字节,定义如下:

// ForFoundationOnly.h
typedef struct {
    uint8_t	_magic[6];
    uint8_t	_version[2];
} CFBinaryPlistHeader;

2.1.1 magic

magic固定为plist

2.1.2 version

plist常见的version00

同时还有1516

版本1516都没有文档说明。

2.2 Trailer

Trailer固定位于二进制Plist的尾部,总共32字节。

Trailer的定义如下:

// ForFoundationOnly.h
typedef struct {
    uint8_t	_unused[5];
    uint8_t _sortVersion;
    uint8_t	_offsetIntSize;
    uint8_t	_objectRefSize;
    uint64_t _numObjects;
    uint64_t _topObject;
    uint64_t _offsetTableOffset;
} CFBinaryPlistTrailer;

2.2.1 Unused

Trailer开始的头5字节没有使用,始终是0

2.2.2 SortVersion

SortVersion表是Plist中的Key是否排序,占用1字节。

0表示未排序。

2.2.3 OffsetIntSize

OffsetIntSize表示Offset-Table中每一项占用的字节数。

在上面例子中可以看到,OffsetIntSize1,表示Offset-Table中每项只占用1字节。

2.2.4 ObjectRefSize

ObjectRefSize表示DictArray中引用的对象索引占用的字节数。

在上面例子中ObjectRefSize1,表示DictArray中引用对象的索引占用1字节。

Objects区域的第1个字节d5为例。

d5的高4bit代表数据类型,d代表Dict

d5的低4bitDict场景代表key-value对的个数,也就是这个Dict5key-value对。

d5后面0x01-0x051个字节代表keyOffset-Table中的索引。

0x06-0x0a1个字节代表valueOffset-Table中的索引。

如果ObjectRefSize2,那么这些索引就会占用2个字节。

2.2.5 Num-Objects

Num-Objects代表二进制Plist中的对象个数。

在上面例子中,有一个Dict,这个Dict5key-value对,因此总共有11个对象。

2.2.6 Top-Object

Top-Object表示根对象偏移量,一般都为0

在上面例子中,根对象就是plist节点。

2.2.7 Offset-Table Offset

Offset-Table Offset表示Offset-Table的偏移量。

在上面例子中,Offset-Table位于0x93处。

2.2.8 Offset-Table

Offset-Table中的每一项存储对象在Plist文件中的偏移量。

Offset-Table的项从0开始计数。

上面例子中Offset-Table的第0项为0x08

Plist二进制偏移0x08处的值是d5

d5代表了数据类型。

d54bit代表这是一个Dict

d54bit代表这个Dict5key-value对。

2.2.9 Objects

Objects区域就是二进制Plist的数据区。

3 Plist 二进制中的数据类型

常见的Plist二进制中的数据类型如下:

  • 0x00

0x00代表null

  • 0x08

0x08代表布尔值false

  • 0x09

0x09代表布尔值true

  • 0x1n

0x1n表示是int类型。

0x1n中的n可以取0~7,表示这个int占用2^n个字节,这些字节是大端在前排列。

比如0x11 0x20 0x30,那么n=1,表示这个int占用2个字节,为0x2030

int

  • 0x2n

0x2n表示是real类型。

0x2n中的n可以取值0~7,表示这个real类型占用2^n个字节,这些字节是大端在前排列。

real

  • 0x5n

0x5n表示ASCII字符串。

0x5nn取值0-f,表示这个ASCII字符串占用的字节数。

ASCII字符串的内容接在0x5n的后面。

string

但是如果n=f,那么后面的1个字节表示一个int类型,定义了这个ASCII字符串占用的字节数。

string2

比如有一个字节序列0x5f 10 0f

0x5f表示这是一个ASCII字符串。

10按照上面int的定义,它后面的2^0=1个字节定义了这个整数,也就是0xf

那么,整个ASCII字符串就占用0xf个字节。

  • an

an表示是Array类型。

ann取值0-f,表示这个Array中元素的个数。

Array中每个元素在Offset-Table中的索引直接接在an后面。

array

如果n=f,那么就和0x5n中的一样。

array2

  • dn

dn表示是Dict类型。

dnn取值0-f,表示这个Dictkey-value对个数。

Dict后面先跟keyOffset-Table中的索引,接着跟着valueOffset-Table中的索引。

dict

如果n=f,那么就和0x5n中的一样

dict2

更多详细的类型参看CFBinaryPList.c