把一个原生二进制丢进 Ghidra 或 IDA 之前,最好先弄清楚它是什么:面向哪种 CPU,是库还是可执行文件,链接了哪些库,构建时开了哪些加固选项,有没有哪一部分像是被加了壳。通常这意味着要依次跑 file、readelf、otool、nm、strings 和一个 checksec 脚本,而且还得看你手头是什么操作系统。
这个工具把这些信息集中在一个页面里,支持 ELF(Linux、Android、BSD、固件)、PE(Windows 的 EXE、DLL 和驱动)以及 Mach-O(macOS 和 iOS,包括通用二进制)。文件头和各类表都在浏览器里解析,不会运行、反汇编或上传文件。
能做什么
输入。 拖入或选择一个文件,最大 512 MiB。格式根据文件开头的字节判断,而不是看文件名:
- ELF:32 位和 64 位,小端和大端(
ET_EXEC、ET_DYN、ET_REL、ET_CORE)。 - PE:PE32 和 PE32+(EXE、DLL、SYS 驱动、EFI 映像)。带 CLI 头的文件会标注为 .NET 程序集,并附上 .NET 元数据与 IL 查看器的链接,用来查看它的类型和 IL。
- Mach-O:32 位和 64 位,任意字节序(可执行文件、dylib、bundle、目标文件、内核扩展)。通用(fat)二进制会列出每个切片的架构、偏移和大小;选中一个切片,报告就切换到它。
报告内容。
- 基本信息:格式、架构、位数、字节序、文件类型和角色、入口点、文件大小和 SHA-256。不同格式还有:
- ELF:OS/ABI、
PT_INTERP里的解释器(例如/lib64/ld-linux-x86-64.so.2或/system/bin/linker64)、DT_SONAME和 GNU build-id。 - PE:子系统、COFF 时间戳、链接器和系统版本、映像基址,以及 imphash。
- Mach-O:
LC_BUILD_VERSION或LC_VERSION_MIN_*里的平台、最低系统版本和 SDK,LC_UUID,dylib 的安装名,以及代码签名里的签名标识符和 Team ID。
- ELF:OS/ABI、
- 段与节区:名称、地址、文件偏移、文件大小和内存大小、权限(
r-x、rw-)、类型,以及每个区域字节的香农熵。高于每字节 7.2 比特(且不小于 1 KiB)的区域会标上“高熵”,表示压缩或加密的数据,例如加壳代码、内嵌压缩包或图片。这很常见,也完全正当,只说明反汇编器在那里看不到代码。 - 链接的库:ELF 的
DT_NEEDED;PE 的导入 DLL 和延迟加载 DLL;Mach-O 的LC_LOAD_DYLIB以及弱链接、再导出、懒加载和 upward dylib。 - 导入与导出:ELF 的动态符号(
.dynsym,目标文件和静态链接程序用.symtab)及其类型;PE 按 DLL 分组的导入,包括只有序号的导入和延迟加载导入,以及带序号和转发项的导出表;Mach-O 符号表里的外部符号,以及每个导入绑定到哪个 dylib。表格可以按名称或库筛选,也可以按方向筛选,每次渲染 500 行。 - 安全特性:根据文件头、标志位和导入符号名得出的检查清单:
- ELF:栈不可执行(
PT_GNU_STACK)、PIE、RELRO(部分,或加上BIND_NOW的完整 RELRO)、栈保护 canary 和 FORTIFY 线索(是否导入__stack_chk_fail和__*_chk)、符号表是否被剥离。 - PE:ASLR(
DYNAMIC_BASE)、高熵 ASLR、DEP(NX_COMPAT)、控制流保护(CFG)、32 位映像的 SafeSEH 或NO_SEH、是否带 Authenticode 签名、FORCE_INTEGRITY、.NET。 - Mach-O:PIE、栈不可执行、栈保护线索、是否带代码签名(CodeDirectory 版本和标志,ad hoc 还是带 CMS 签名)、Hardened Runtime、
LC_ENCRYPTION_INFO的cryptid、__RESTRICT段。
- ELF:栈不可执行(
- 字符串:至少 6 个字符(可设为 2 到 64)的可打印 ASCII 和 UTF-16LE 字符串,并标出各自所在的节区。按偏移列出前 20,000 个并可筛选;点击“全部下载为 .txt”会按“偏移、编码、节区、文本”的格式导出全部字符串(最多 2,000,000 个)。
- 导出:整份报告可以下载为 JSON。
原理
页面用 Blob.slice 读取文件,文件头、节区表、符号表和名称都是按需从文件里读出来的。ELF 先读 ELF 头和程序头,再读节区头及其名称表、PT_INTERP、note、动态段(字符串经由 DT_STRTAB,通过 PT_LOAD 段换算成文件偏移)和符号表。PE 读 DOS 头和 COFF 头、可选头及其数据目录、节区表,再顺着 RVA 读导入表、延迟导入表、导出表和 load config。Mach-O 逐条遍历加载命令、nlist 符号表和代码签名的 SuperBlob。
每次读取都做边界检查,文件里声明的每个数量在使用前都有上限:节区、段、加载命令和库各 4,096 个,符号 100,000 个,单个表 64 MiB。某个表损坏或被截断时,只跳过这一部分并记在“说明”里,报告的其余部分照常显示。worker 运行超过两分钟会被终止。
SHA-256 用 WebCrypto 计算。WebCrypto 不支持流式哈希,所以会把文件读进内存一次,熵和字符串扫描也复用这份数据。PE 的 imphash 采用 pefile 的算法(get_imphash):按表中顺序取标准导入,DLL 名转小写并去掉 .dll、.ocx 或 .sys,拼成 dll.function,再算 MD5。各项结果都在为本工具编译的测试二进制上和 pefile、llvm-readelf、llvm-readobj、otool、nm、codesign、llvm-strings 的输出核对过。
文件如何保持私密
文件不会上传:
- 解析、哈希、熵计算和字符串扫描都在你设备上的 Web Worker 里完成。
- 节区、符号、库和字符串都以纯文本显示,文件里的任何内容都不会被当作 HTML 解析或执行。
- 统计事件只有粗粒度信息:成功或错误码、格式(
elf、pe、macho或fat)、粗略的架构(如x86-64、arm64)、大小区间和耗时区间。不会包含文件名、哈希、符号名、字符串或文件的任何其他内容。完整列表见隐私页。 - 工具页不展示广告。
如何自己验证
- 在选择文件之前,打开浏览器开发者工具,切到 Network(网络) 面板。分析一个二进制,切换一次切片,再下载字符串。你只会看到页面资源和 worker 脚本
/_astro/binary-worker-*.js的请求,没有任何请求携带你的文件。 - 或者先打开页面,再断网(关掉 Wi-Fi,或者在 Network 面板勾选 Offline),然后分析文件,依然可以正常工作。
- worker 运行在内容安全策略
default-src 'none'; script-src 'self'; connect-src 'none'之下,浏览器不允许它发出任何网络请求。
局限
- 不分析代码。 没有反汇编、反编译、控制流或模拟执行。这些请用 REA + Ghidra。
- 安全特性是线索,不是结论。 canary 和 FORTIFY 只看是否导入了相应的辅助函数,所以静态链接的程序即使开了这些选项也可能显示“否”。缺少
PT_GNU_STACK时显示为“未知”,因为默认行为取决于平台。 - 签名只检测,不验证。 Authenticode 和 Mach-O 代码签名只报告是否存在及其基本字段,不检查证书、哈希或公证。
- imphash。 导入表不完整时不计算;导入表里有
ws2_32.dll、wsock32.dll或oleaut32.dll的纯序号导入时也不计算,因为 pefile 用内置的名称表解析这些序号,而本工具没有附带这些表。和 pefile 一样,延迟加载导入不计入 imphash。 - Mach-O 导出来自符号表。导出 trie(
LC_DYLD_INFO、LC_DYLD_EXPORTS_TRIE)和 chained fixups 不解码,所以去掉了外部符号的二进制显示的导出会比dyld_info少。入口点只显示LC_MAIN的;LC_UNIXTHREAD只标出名称,不解码其中的寄存器状态。 - ELF 不显示符号版本(
@GLIBC_2.2.5);没有节区头、只有DT_SYMTAB的动态符号表不会被读取。程序头必须位于文件前 64 KiB 内,超过 2^53 的 64 位偏移(内核映像)会被拒绝。 - 字符串只找可打印 ASCII(
0x20–0x7e),单字节或 UTF-16LE 编码单元。其他编码、压缩数据里的字符串以及运行时拼出来的字符串都找不到。 - 其他格式(没有 MZ 头的 COFF 目标文件、静态库、Java class 文件、WebAssembly)不解析。
.wasm请用 WASM 分析工具。
常见问题
为什么某个节区的熵接近 8?
压缩或加密过的数据看起来是随机的,而随机字节的熵接近每字节 8 比特。UPX 之类的壳、内嵌的 .zip 或图片资源、加密的载荷都会这样。代码和文本通常在 4.5 到 6.5 之间。
为什么 fat 二进制里的偏移都很小?
通用二进制里 Mach-O 的偏移是相对每个切片开头的,和 otool 的输出一致。切片列表里写着每个切片在文件中的起始位置。
我的 DLL 时间戳是一个未来的日期。
采用确定性或可复现构建设置(例如 MSVC 的 /Brepro)时,COFF 时间戳里存的是哈希值而不是日期。
共享库显示“PIE:不适用”,是有问题吗?
没有问题。共享库本身就是位置无关的,PIE 这个问题只针对可执行文件。同理,NX、PIE 和 RELRO 对目标文件也不适用,因为目标文件不会被单独加载。
这和 checksec 有什么区别?
检查的东西是同一类(文件头和导入),但这里对 ELF、PE 和 Mach-O 用的是同一套方式,也不用安装任何东西。措辞有意保持中性:缺少某个特性只是构建方式的事实,不代表存在漏洞。
合规
请只分析你自己编译的程序、开源软件、CTF 题目或你获得授权评估的文件。尊重所分析软件的许可证(包括其中限制逆向工程的条款)以及适用的法律。参见免责声明。
相关教程
- 用 REA + Ghidra 免费分析原生二进制:在同样的二进制上反编译、搜索字符串、查交叉引用、追踪功能。
- 用 AI 逆向 Windows EXE/DLL:REA + Ghidra 实操:从这里列出的 PE 导入导出,一路找到背后的函数。
- macOS 应用逆向:用 REA 分析 Mach-O、Swift 符号和 NIB 界面:应用包里的 Mach-O、Swift 符号和 NIB。
- 用 AI agent 做二进制补丁对比:先在这里确认两个版本的架构和节区对得上,再比较它们。
- 用 REA 做固件分析:Binwalk、Unblob 解包再交给 Ghidra:解开固件映像,再识别里面找到的 ELF 文件。
- ELF / PE / Mach-O 在线查看:读懂三种格式的基本信息、节区和符号,判断构建产物是否已 strip。
- 不运行就能判断 EXE / DLL 是 32 位、64 位还是 ARM64:Machine 和 Magic 字段,以及 .NET AnyCPU 程序集为什么看起来像 32 位。
- 检查自己构建的二进制加固选项:同一个程序开关加固参数各编一次,对照这里的安全特性表。
- 这个 Mac 应用是不是通用二进制?:对比通用二进制的 arm64 和 x86_64 切片,找出缺切片的依赖和未签名的切片。