资讯详情

从ipa中提取Assets.car资源:跨平台解压与解析实战

📅 2026/9/17 5:08:01 | 华诺云谱 👁 阅读
从ipa中提取Assets.car资源:跨平台解压与解析实战
上个月朋友丢过来一个.ipa让我帮他看看包里的启动图是不是最新版。这活儿本来很简单把.ipa后缀改成.zip解压进到Payload目录就行。结果我就卡在了一个Assets.car文件上文件在眼前双击打不开预览不显示拖到 Photoshop 里也不认。上网一搜一大半帖子把文件名写成Assert.car思维绕了一大圈才理清楚。这篇文章就把我从.ipa包里解压、提取Assets.car文件的完整过程写一遍顺带把三个平台的操作差异、重新打包签名、以及过程中最容易翻车的几个细节都讲清楚。如果你要分析应用资源、核对素材版本、做包体瘦身或者只是想从某个测试包里抠出 AppIcon 来用这篇内容可以直接照着操作。先纠正一个小知识点实际文件名叫Assets.car不是Assert.car。网上很多人会打成后者搜索时两种关键词都能搜到相关讨论后面我会专门说这个命名的来龙去脉。1. 先把问题拆开ipa 解压和 car 文件解析是两件事很多人的第一反应是.ipa不就是个压缩包吗解压出来不就好了。等解压完才发现Assets.car还是打不开。这不是操作的问题而是我们把“解压 ipa”和“解析 car 文件”两件事混到一起了。1.1 一个典型 ipa 包内部长什么样.ipa的本质就是一个Zip压缩包只不过扩展名特殊。Xcode 构建完成后会把目标 App 的产物和资源封装成这样的结构TestApp.ipa └─ Payload/ └─ TestApp.app/ ├─ TestApp // 二进制可执行文件 ├─ Info.plist ├─ CodeResources ├─ _CodeSignature/ │ └─ CodeResources ├─ Assets.car // 编译后的资源目录 ├─ .lproj/ // 本地化资源 └─ Frameworks/ // 动态库你平时在手机桌面上安装的 App安装包解开后就是这个结构。其中Assets.car负责保存图标、启动图、通用图片、色彩定义、数据集等编译后的资源。它通常位于.app根目录下用ls -lh能直接看到。1.2 Assert.car 的正确文件名应该是 Assets.car先把命名的事情说清楚。你在搜索引擎里输入Assert.car能看到大量与本文主题一致的帖子但这个写法实际上是asset资源被误打成了assert断言后的产物。正确的名字是Assets.car由 Xcode 编译Assets.xcassets目录生成。car不是官方英文缩写业内习惯上把这种文件叫作 car 文件。为了不跟搜索习惯脱节我全文把Assert.car作为关键词保留但实操时你要找的是Assets.car。如果你在解压后的 ipa 里看到的是Assets.car说明解压过程完全正常不是出错了。1.3 为什么普通解压工具拿 car 文件没办法我习惯用一个类比.ipa是行李箱Assets.car是行李箱里的保险柜。压缩软件能打开行李箱却打不开保险柜。Assets.car内部不是简单地堆了一排 PNG它有自己独立的头部、索引表和数据区。苹果用私有的CoreUI框架对这类文件做读取外部没有公开的文件格式规范。压缩软件只能把 car 文件从 ipa 里“取出来”没法把 car 数据区里的图片直接展示给你看。所以完整的流程应该是两步把.ipa解压定位到Payload/TestApp.app/Assets.car。用专门的工具解析Assets.car把里面的图片资源导出。知道这两步的区别后面所有操作就不会觉得很诡异了。2. 第一阶段在 Windows、macOS、Linux 上解包 ipa 的实操方案工欲善其事必先利其器。第一步不是解析 car而是先把 ipa 完整、无损地解出来。不同平台踩的坑不一样这里分别给方案。2.1 图形界面方案最朴素、最快但有几个容易被忽略的设定Windows 上最常见的做法是把TestApp.ipa复制一份后缀改成TestApp.zip。如果文件管理器里看不到扩展名先在“查看”菜单里勾选“文件扩展名”。然后右键解压到当前目录即可。只依赖 Windows 自带 zip 功能大多数 ipa 能解但遇到包含大量文件、路径特别深的包时会出问题。建议装 7-Zip 或 Bandizip主要不是为了花哨功能而是为了处理两个实际问题超长路径.app内部目录层级很深某些资源路径超过 Windows 历史遗留的 260 字符限制后右键解压会中断或者解出来之后文件无法删除、无法重命名。7-Zip 对长路径的处理比系统自带解压更宽容。中文文件名乱码部分企业定制的 ipa 会带中文文件名。解压软件默认按本地代码页处理可能导致文件名变乱。Bandizip 在右键菜单里可以直接选“自动检测编码”能规避绝大多数乱码问题。这里多说一句关于z01的问题。z01通常是分卷压缩包的第一卷用来配合zip解压。正式分发的 ipa 不会做成这种分包形式。遇到.z01就说明你拿到的不是标准 ipa先把所有分卷下载到同一目录再用支持分卷的解压工具处理。还有一个经常被一起问到的“压缩包忘记密码了怎么解压”如果包本身是企业用工具加密后分发的密码由分发方管理技术上没有通用的“右键绕过密码”方案。我们平时说的 .ipa 解压指的是未加密的常见安装包跟加密文件破解是两回事。遇到加密包正规路径是联系分发方要密码。2.2 macOS 命令行unzip 与 ditto 各擅胜场macOS 上双击 ipa系统会用“归档实用工具”自动解压。但如果你是做资源分析或者准备重新签名我更推荐命令行。快速解压用 unzipunzip -q TestApp.ipa -d test_extract-q是安静模式避免刷屏-d指定输出目录。如果后面要重新给 .app 签名打包建议改用 dittoditto -x -k TestApp.ipa test_extractditto 会保留解压出来的文件的 Symbolic Link、文件权限和扩展属性。这些属性对代码签名校验是有影响的之后要重新签名时能少踩不少坑。只提取素材、不打包回装的话用 unzip 就够。2.3 Linux记住 unzip 之外的编码参数Linux 服务器上处理 ipa 是很多 CI 场景的刚需。基础解压unzip TestApp.ipa -d test_extract如果遇到解压后文件名乱码原因是 Zip 格式对文件名字符集没有强制规定Windows 端打包工具经常用 GBK 写入文件名Linux 端按 UTF-8 解码自然就乱了。这种情况可以指定代码页unzip -O gbk TestApp.ipa -d test_extract或者用 7-Zip7z x TestApp.ipa -mcp936-mcp936表示使用 GBK 代码页。如果你的 ipa 内部路径全是 ASCII这一步可以省略。顺便提一嘴Linux 下还经常遇到.tar.gz、.7z这类格式它们跟 ipa 没关系但命令容易混淆。.tar.gz用tar -zxvf.7z用7z x。记住之后日常解压基本就不会范迷糊了。2.4 三平台操作对比平台推荐方式适用场景Windows后缀改 zip 7-Zip/Bandizip图形化快速查看、手动提取macOSditto -x -k TestApp.ipa test_extract需要保留权限属性、准备重签macOSunzip -q TestApp.ipa -d test_extract只做素材提取不涉及重新打包Linuxunzip -O gbk或7z x -mcp936服务器批量处理、自动化脚本3. 第二阶段解包 Assets.car把真正能用的图片导出来ipa 解压出来后进入.app目录重点找Assets.car。接下来这一步才是整篇文章的高潮部分。3.1 先确认这个文件和其他资源不一样进入 .app 目录后先用file命令看文件类型cd test_extract/Payload/TestApp.app file Assets.car输出通常是Assets.car: data说明这不是 PNG、不是 plist、也不是常见的文本文件。再用十六进制看一下头部head -c 64 Assets.car | xxd你会发现完全不是常见图片格式的魔数。再用strings扫一眼可读字符串strings Assets.car | head -50如果里面能看到AppIcon、tabbar之类的资源命名说明数据还在只是需要一个能将索引与数据区对应起来的解析工具。3.2 macOS 官方方案assetutil 生成 JSON 清单macOS 上最稳定的工具是 Xcode 自带的assetutil。装好 Xcode 或 Command Line Tools 后直接执行xcrun --sdk iphoneos assetutil --info Assets.car assets_info.json这样会把 car 文件里所有资源条目输出成一个 JSON 文件。打开后你能看到非常详细的信息例如[ { AssetType : Image Set, Name : AppIcon, RenditionName : AppIcon60x602x.png, Idiom : iphone, Scale : 2, SizeOnScreen : 60x60, PixelWidth : 120, PixelHeight : 120 } ]Name对应Assets.xcassets里的资源集名称RenditionName是渲染后的文件名Idiom表示设备类型PixelWidth/PixelHeight是最终像素尺寸。这一份 JSON 基本就是 car 文件内资源的目录表用来核对资源版本非常方便。这是 macOS 上的官方路线不用下载任何第三方解析器是最稳的方案。3.3 真正导出图片常见工具的取舍assetutil 给出的是索引真正把图片一张张导出还要靠渲染工具。实践中我见过三类做法cartoolmacOS 上的 GUI 工具打开 car 文件后能直接预览所有图片一键导出到目录。它对设计同学比较友好不需要写命令。acextract命令行工具适合脚本化操作。大概用法是acextract -i Assets.car -o extracted具体参数以它仓库 README 为准。Asset Catalog Tinkerer同样是 GUI 工具能把 car 文件里的资源列表可视化适合做资源差异对比。这些工具都是围绕 CoreUI 的私有机制来做的所以不能保证每个版本的 car 文件都能完全兼容。经验是常用的 Xcode 编译出来的 car 文件它们基本都能处理。3.4 不想装第三方工具时的备用方案用 Python 直接抓图片如果你在 Linux 或 Windows 环境一时没有现成解析器可以用一个取巧的办法很多 car 文件里仍然保留了标准 PNG/JPEG 原始数据只要在二进制文件里搜索图片魔数就能把图片“切”出来。一个简化版的 Python 脚本import os CAR_FILE Assets.car OUT_DIR car_extracted os.makedirs(OUT_DIR, exist_okTrue) with open(CAR_FILE, rb) as f: data f.read() png_sig b\x89PNG\r\n\x1a\n count 0 i 0 while True: pos data.find(png_sig, i) if pos -1: break end data.find(bIEND, pos) if end ! -1: end len(bIEND) 4 # IEND chunk 尾部还有 4 字节 CRC out_path os.path.join(OUT_DIR, fextracted_{count}.png) with open(out_path, wb) as out: out.write(data[pos:end]) print(out_path) count 1 i end else: i pos 8这个脚本的思路很简单在Assets.car里找 PNG 文件签名然后找IEND块作为结束位置把中间的数据落盘。跑完后car_extracted目录里会多出一批 PNG。不过这个方案有局限如果图片在 car 内部被特殊压缩过比如用了 Apple 的 RLE 或 PVRTC 编码二进制里没有标准 PNG 头脚本就搜不到。遇到这种情况我建议还是换到 macOS 环境用上一节的专业工具处理不要花大量时间手写解析。4. 改完 Assets.car 或替换过文件之后签名与重打包的连环坑如果你只是做资源提取看到上一节就可以停了。但很多人实际是想替换图标、改素材然后重新生成一个 ipa 装到真机上。这一步就绕不开代码签名。4.1 为什么解压出来再原样放回去会安装失败iOS 系统对已经签名的 .app 有一套完整性校验机制。签名时会计算包内所有文件的哈希写入_CodeSignature/CodeResources。系统在安装和启动时都会校验这些哈希。只要改动过Assets.car哪怕只是改了一个字节校验值就对不上。iOS 会拒绝安装或者在启动时直接闪退。这不是解压步骤的问题是签名机制在正常起作用。4.2 用自己的开发者证书重新签名手动重签的大致流程如下解压 ipa。改完要改的文件。删除旧的签名信息rm -rf Payload/TestApp.app/_CodeSignature用你的证书重新签名codesign -f -s iPhone Developer: 你的名字 (TEAMID) Payload/TestApp.app查看本机可用证书security find-identity -v -p codesigning重新打包zip -qr TestApp-resigned.ipa Payload/这样做出来的新包安装流程和普通开发包一样。如果只是个人开发调试更方便的方式是用 Xcode 连真机直接装不需要手动重签。还有一点要提醒这个技术只适用于你自己有权限的应用或者你自己开发的测试包。改别人的应用资源再用自己的证书重签涉及授权问题不要拿来看似“顺手”的操作去搞不合规的事。4.3 “只读”才是资源分析的正确姿势我做资源核对的时候绝大多数情况不会触碰签名。操作路径很简单解压 ipa、取 Assets.car、导出图片、比对完成。这样全程不修改 .app 里的任何内容也不会触发签名问题。只有当你确定要生成一个新安装包时才需要考虑重签。如果只是内部验收素材一个只读流程足够满足需求别给自己找额外麻烦。4.4 想要修改 car 资源正确做法是回到 Assets.xcassets 重新编译有人会问能不能直接编辑 car 文件把里面某一张图标换掉答案是能做的人极少而且维护成本极高。正规做法是回到 Xcode 工程在Assets.xcassets里修改图片然后重新构建。Xcode 的 asset catalog 编译器会自动生成新的Assets.car同时处理好所有尺寸、色彩模式、比例因子。这样生成的资源在签名环节也更容易过关。5. 实战记录把某个测试包里的 AppIcon 完整抠出来讲了这么多原理最后用一个完整例子把流程串起来。假设你已经拿到一个TestApp.ipa想导出它的应用图标。5.1 解压并定位文件cd ~/Downloads mkdir -p app_extract unzip -q TestApp.ipa -d app_extract cd app_extract/Payload/TestApp.app file Assets.car如果输出Assets.car: data说明定位成功。5.2 生成资源清单xcrun --sdk iphoneos assetutil --info Assets.car asset_info.json然后用编辑器打开asset_info.json搜索AppIcon。你大概率能看到这样的记录{ AssetType : Image Set, Name : AppIcon, RenditionName : AppIcon60x602x.png, Idiom : iphone, Scale : 2, PixelWidth : 120, PixelHeight : 120 }这里的关键字段是RenditionName或Name。如果文件名是标准的导出后也能直接对应。5.3 导出图片用 GUI 工具时直接打开Assets.car勾选AppIcon导出。如果要用脚本把上一节的 Python 脚本保存为extract_car.py放到Assets.car同目录下运行python3 extract_car.py运行完car_extracted目录里就会出现多张 PNG。用file或sips查看尺寸file car_extracted/*.png sips -g pixelWidth -g pixelHeight car_extracted/extracted_0.png正常情况下你能看到与清单中PixelWidth、PixelHeight一致的输出。5.4 导出不完全时的处理思路脚本方式偶尔会缺图或者导出文件打不开。此时回到 macOS用专业工具打开同一个 car 文件基本都能补齐。我在实际项目里最常遇到的场景是从旧版本 ipa 里提取一套历史资源用来对比老图标和新图标差异。car 解析工具基本能解决 90% 的问题剩下的 10% 是因为文件里存在 Apple 专有压缩格式比如 LaunchScreen 的某些颜色或数据资源。遇到这种情况最省力的办法是从工程源码里的Assets.xcassets重新导出而不是跟二进制格式较劲。这套流程对我来说最大的价值就是不用每次都跑到 Xcode 里到处找素材。拿到一个 ipa几条命令下去就能把资源目录翻个底朝天。希望这篇内容对你也能派上同样的用场。
📝

华诺云谱内容团队

资深建站顾问 · 行业研究员

10年+企业数字化服务经验,专注智能建站、SEO优化与品牌营销,持续输出建站技巧、行业洞察与营销干货,已帮助5000+企业实现数字化增长。

你可能需要的服务

订阅华诺云谱资讯周报

每周一封,精选建站技巧、SEO与营销干货,直达邮箱。已有 8,000+ 企业主订阅,助你少走弯路。