rea-reverse

原生二进制概览:ELF、PE 与 Mach-O

打开 ELF、PE 或 Mach-O 文件,查看它的架构和文件头、带熵值的节区与段、导入导出的库和符号、安全加固标志以及可打印字符串。不会运行或反汇编文件。

二进制文件不会离开你的浏览器. 文件在一个禁止联网的 Web Worker 中本地解析,不上传任何内容。 如何自己验证

把 ELF、PE 或 Mach-O 文件拖到这里

或

可执行文件、共享库(.so、.dll、.dylib)、驱动、目标文件以及通用(fat)Mach-O 二进制。最大 512 MiB。

这个工具不做的事

  • 只做静态解析:不运行、不反汇编、不反编译。想读代码,请用 Ghidra 或其他反汇编器打开文件。
  • 安全特性来自文件头、标志位和导入的符号名,只说明文件是怎么构建的,不代表文件是否安全;签名只检测是否存在,不做验证。

把一个原生二进制丢进 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。
  • 段与节区:名称、地址、文件偏移、文件大小和内存大小、权限(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 段。
  • 字符串:至少 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)、大小区间和耗时区间。不会包含文件名、哈希、符号名、字符串或文件的任何其他内容。完整列表见隐私页。
  • 工具页不展示广告。

如何自己验证

  1. 在选择文件之前,打开浏览器开发者工具,切到 Network(网络) 面板。分析一个二进制,切换一次切片,再下载字符串。你只会看到页面资源和 worker 脚本 /_astro/binary-worker-*.js 的请求,没有任何请求携带你的文件。
  2. 或者先打开页面,再断网(关掉 Wi-Fi,或者在 Network 面板勾选 Offline),然后分析文件,依然可以正常工作。
  3. 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 题目或你获得授权评估的文件。尊重所分析软件的许可证(包括其中限制逆向工程的条款)以及适用的法律。参见免责声明。

相关教程