rea-reverse

不认识的文件:用魔数识别文件类型,再选对分析工具

基于 REA 6.4.0更新于 约 8 分钟读完
本页目录

结论先行:别看扩展名,看开头几个字节。Linux 和 macOS 上,file mystery 会直接说出格式,xxd -l 16 mystery 能看到原始文件头;Windows 上在 PowerShell 里用 Format-Hex -Path mystery -Count 16。拿这几个字节去对下面的表。如果开头是 PK,那它是个 ZIP 容器,到底是 APK、NuGet 包、JAR 还是 Office 文档,要看里面的文件名,不看开头字节。认出来以后,交给专门处理这种格式的工具。文末的对照表列出了本站的浏览器工具和对应的 REA 命令。

适合谁读:收到一个没有扩展名(或者扩展名不可信)的附件、构建产物或固件转储,想在打开之前先弄清楚它是什么的开发者。

读完你能掌握:

  • 魔数是什么,为什么扩展名只能当参考。
  • 开发和逆向中最常见的那些文件签名。
  • 怎么区分各种基于 ZIP 的格式。
  • file、xxd、PowerShell 和 REA 的 inspect-artifact 对同一批文件分别怎么说。
  • 每种格式该用什么工具打开。

示例文件:一共 8 个,全是我自己做的或者来自开源发布,统一改名为 mystery-a … mystery-h,不让扩展名泄露任何信息:macOS 上用 clang 编译的 C 程序;OpenWrt 25.12.5 根文件系统里的 busybox;从 nuget.org 下载的 Newtonsoft.Json.dll 及其 .nupkg 包(MIT 许可);用 wat2wasm 生成、只有一个函数的 WebAssembly 模块;一个 gzip 压缩的文本文件;OpenWrt 的 SquashFS 镜像;以及 NuGet 包里的 PNG 图标。

把不认识的文件当成不可信的东西。先静态识别,不要双击、不要运行,也不要用会执行宏的程序打开。如果文件来自别人的系统,先确认你有权分析它。参见 REA 的 DISCLAIMER.md。

为什么开头字节比扩展名可靠

大多数二进制格式都以一个固定签名开头,也就是“魔数”,好让加载器和解析器尽快拒绝错误的输入:Linux 内核认 \x7fELF,Windows 认 MZ,浏览器的 WebAssembly 引擎认 \0asm。扩展名只是命名习惯,谁都能改;而且很多格式(APK、JAR、DOCX、NUPKG)用的是同一种容器。

签名也有局限。JSON、HAR、source map 这类文本格式没有魔数,只能靠解析来认。有些魔数会撞车,比如 CA FE BA BE 既是 macOS 通用二进制的开头,也是 Java .class 文件的开头。签名也只说明文件“自称”是什么:一个被截断或损坏的文件,开头可以完全正确,照样解析失败。

第 1 步:看文件头

$ file mystery-*
mystery-a: Mach-O 64-bit executable arm64
mystery-b: ELF 32-bit MSB executable, MIPS, MIPS32 rel2 version 1 (SYSV), dynamically linked, interpreter /lib/ld-musl-mips-sf.so.1, no section header
mystery-c: PE32 executable (DLL) (console) Intel 80386 Mono/.Net assembly, for MS Windows
mystery-d: Zip archive data, at least v2.0 to extract, compression method=deflate
mystery-e: WebAssembly (wasm) binary module version 0x1 (MVP)
mystery-f: gzip compressed data, was "note.txt", ... from Unix, truncated
mystery-g: Squashfs filesystem, little endian, version 4.0, xz compressed, 4626494 bytes, 1214 inodes, ...
mystery-h: PNG image data, 512 x 512, 8-bit/color RGBA, non-interlaced

这是 macOS 自带的 file 5.41。它用一个庞大的签名库读文件头,常常还会补充细节:CPU、.NET 标记、图片尺寸。但它说的每个词不一定都对:它说这个 gzip 文件 “truncated”,可 gzip -tv mystery-f 报的是 OK。真正说了算的是字节本身:

$ xxd -l 16 mystery-c
00000000: 4d5a 9000 0300 0000 0400 0000 ffff 0000  MZ..............
$ xxd -l 16 mystery-e
00000000: 0061 736d 0100 0000 0107 0160 027f 7f01  .asm.......`....
$ xxd -l 16 mystery-g
00000000: 6873 7173 be04 0000 286c 426a 0000 0400  hsqs....(lBj....

Windows 上没有 xxd,可以用 PowerShell 自带的 cmdlet。微软的 Format-Hex 文档 举的例子正好就是这个场景:把 PDF 改成一个陌生的扩展名,再用它认出来。

Format-Hex -Path .\mystery-c -Count 16

-Count 和 -Offset 需要 PowerShell 6.2 或更高版本。写这篇文章时我手边没有 Windows,这条命令没有实际运行,输出格式请以官方文档为准。

第 2 步:对照签名

下表是我的示例文件,加上几个常见的相关格式。凡是标了示例名的行,都在那个文件上用 xxd 核对过。

开头字节(十六进制) ASCII 格式 示例
7F 45 4C 46 .ELF ELF:Linux、Android .so、大多数固件程序 mystery-b
4D 5A MZ PE/COFF:Windows EXE、DLL、.NET 程序集(PE\0\0 头的偏移存在 0x3C 处) mystery-c
CF FA ED FE / CE FA ED FE Mach-O 64 位 / 32 位,小端 mystery-a
CA FE BA BE 通用 Mach-O 或 Java class
50 4B 03 04 PK.. ZIP 及所有基于 ZIP 的格式 mystery-d
00 61 73 6D .asm WebAssembly 模块(后 4 字节是版本) mystery-e
1F 8B gzip mystery-f
FD 37 7A 58 5A 00 .7zXZ. xz (用 xz 生成)
68 73 71 73 hsqs SquashFS 小端(大端是 sqsh) mystery-g
27 05 19 56 U-Boot legacy uImage(固件内核) OpenWrt .bin
89 50 4E 47 0D 0A 1A 0A .PNG.... PNG mystery-h
62 70 6C 69 73 74 30 30 bplist00 Apple 二进制 plist
25 50 44 46 %PDF PDF(微软 Format-Hex 的例子)

签名在偏移 0 是最简单的情况。固件会把好几种格式首尾相接地拼在一起,SquashFS 可能从文件中间几 MB 处才开始。这种情况要用会搜索整个文件的扫描器,见 Binwalk 3 使用指南。

第 3 步:拆开 ZIP 家族

PK\x03\x04 只能说明它是 ZIP。至于是哪一种 ZIP,要列出里面的条目:

$ unzip -l mystery-d | head
     1104  03-08-2023 07:01   LICENSE.md
     2413  03-08-2023 07:06   Newtonsoft.Json.nuspec
     8956  03-08-2023 07:01   packageIcon.png
      653  03-08-2023 07:06   [Content_Types].xml
   580880  03-08-2023 07:09   lib/net20/Newtonsoft.Json.dll

有 .nuspec,再加上 lib/<框架>/ 目录,就是 NuGet 包。常见情况的特征文件:

ZIP 里有 它是
AndroidManifest.xml、classes.dex、resources.arsc Android APK
base/manifest/AndroidManifest.xml、BundleConfig.pb Android App Bundle(AAB)
Payload/<Name>.app/ iOS IPA
META-INF/MANIFEST.MF 加 .class 文件 Java JAR
*.nuspec、lib/<tfm>/ NuGet 包
[Content_Types].xml 加 word/、xl/ 或 ppt/ Office DOCX、XLSX、PPTX
AppxManifest.xml MSIX / AppX

这一步各家工具做得不一样。REA(morluto 的开源项目)6.4.0 的 inspect-artifact 先从字节判断是不是 ZIP,然后按扩展名确定子类型:.apk、.ipa、.msix/.msixbundle、.appx/.appxbundle,其余都算普通 zip(逻辑在 dist/domain/zipPackageFormat.js)。我对 mystery-d 运行它,得到 root_format: "zip",里面 8 个 DLL 按各自的字节被归为 pe。再把同一个 NuGet 包复制成 renamed.apk,它就报 root_format: "apk"。字节一模一样,结论却不同,所以 ZIP 的子类型最好自己列一下条目再下结论。

本站的 APK/AAB 分析工具 看的是内容。把这个 NuGet 包丢进去,它照常打开 ZIP,然后报 “No AndroidManifest.xml was found.”(中文界面为“没有找到 AndroidManifest.xml。”)。它区分 APK 和 AAB 的依据是有没有 AndroidManifest.xml 或 base/manifest/AndroidManifest.xml,和文件名无关。

第 4 步:让 REA 给出全貌

对于原生程序和容器格式,rea inspect-artifact <path> 按字节分类,还会建议下一步做什么。下面是 REA 6.4.0 在 macOS 上对每个示例的结果:

示例 root_format 建议的下一步
mystery-a(Mach-O) mach-o open_binary
mystery-b(ELF) elf open_binary
mystery-c(.NET DLL) pe 先 inspect_managed_artifact,再 open_binary
mystery-d(NuGet) zip(图里 25 个节点) 无
mystery-e、-f、-g、-h 报错:“Cannot open artifact: unsupported binary format.”

对 PE 文件,REA 附了一条低置信度的假设:“The PE artifact may contain managed CLI metadata or native code; inventory bytes alone do not distinguish them.” 这就是它建议先做托管检查的原因。inspect-artifact 本质上是归档和应用包的清点工具,不是通用的文件识别器:WebAssembly、gzip、SquashFS、图片都不在它的范围内,所以第一步还是 file 和 xxd。另外,它对 .pkg(xar!)和 .dmg(koly 尾部标记)的识别也要求扩展名匹配。REA 的安装见 REA 入门:安装并接入 AI 编程工具。

第 5 步:用对的工具打开

认出格式后,按下表去找工具。本站的浏览器工具在 Web Worker 里本地解析文件,不上传。2026-10-14 我用二进制、.NET、WASM、APK、ASAR 这几个工具的分析代码跑了示例文件(结果见表后),其余行列的是该格式对应的工具和命令。

格式 本站浏览器工具 REA 6.4.0 相关教程
ELF、PE、Mach-O 原生二进制概览 inspect-artifact,再用 Ghidra 跑 analyze ELF / PE / Mach-O 在线查看
.NET 程序集(带 CLI 头的 PE) .NET 元数据与 IL 查看器 inspect-managed-artifact 查看 .NET DLL 的目标框架
APK / AAB(ZIP) APK/AAB 分析工具 inspect-android-package 解包 APK 或 AAB
WebAssembly WASM 转 WAT 无 查看 WebAssembly
Electron app.asar ASAR 查看器 inspect-artifact(需要 .asar 文件名) 解包 ASAR 文件
HAR(JSON)或 Fiddler SAZ(ZIP) HAR 分析工具 inspect-web-network-capture HAR 文件分析指南
JavaScript source map(JSON) Source map 工具 trace-web-source-location 从打包代码还原源码
固件(uImage、SquashFS 等) 无 inspect-firmware-regions、extract-firmware(仅 Linux) 从固件里提取 SquashFS
EVM 合约字节码(十六进制文本) EVM 选择器提取 inspect-evm-interface EVM 函数选择器

几个实测结果:

  • 原生二进制概览接受任何文件,按魔数判断。它打开了 busybox(ELF32、MIPS、大端、已 strip),对 SquashFS 镜像和 WASM 模块报 “unknown magic”。
  • .NET 查看器把 Newtonsoft.Json.dll 读成 PE32,标志为 ILONLY 和 STRONGNAMESIGNED,元数据版本 v4.0.30319;对 Mach-O 文件则报“不是 PE 文件(缺少 MZ/PE 头)”。
  • WASM 转 WAT把 mystery-e 解析为版本 1,只有一个导出函数 add,类型 (i32, i32) -> (i32)。
  • ASAR 查看器拒绝了 NuGet 的 ZIP,报“不是 ASAR 归档”。ASAR 没有固定魔数,工具检查的是前 16 字节能否构成它的 size pickle 和 header pickle。

.NET、WASM、ASAR、APK 这几个页面的文件选择框按扩展名过滤(.dll,.exe、.wasm、.asar、.apk,.aab)。文件没有扩展名的话,直接拖到页面上就行,工具检查的是内容,不是文件名。

常见问题

签名对得上,文件还可能是别的东西吗? 可能。多格式文件(polyglot)能同时是两种合法格式,在别的文件末尾拼接 ZIP 数据也很常见。偏移 0 的签名决定文件会被怎么加载,但不代表它包含的全部内容。

文本文件怎么办? 文本文件没有魔数。看它是不是合法 JSON(HAR 和 source map 都是 JSON),有没有 shebang(#!),或者让 file 根据内容猜。

Windows 上有 file 命令吗? 默认没有。用 Format-Hex 配合上面的表,或者在 WSL 里用 file。

为什么 REA 把我的 .zip 识别成 apk? 对 ZIP 容器,6.4.0 按扩展名确定子类型。把文件改回正确的名字,或者先列一下条目。

授权声明:只识别和分析你自己的文件、开源软件、CTF 题目,或你有权检查的文件。

下一步