ELF 二进制检查器
像 readelf 那样直接从字节读取 ELF 二进制,全过程在浏览器内完成。头部给出字长与字节序、OS/ABI、架构、入口地址,以及该文件是可重定位目标文件、普通可执行文件、位置无关可执行文件还是共享库——仅凭头部无法区分后两者,因为 PIE 和 .so 都是 DYN,只有解释器或 DF_1_PIE 标志能分辨。程序头列出加载器映射的内容,动态数组给出解释器路径、DT_NEEDED 中的每个库、库自己发布用的 SONAME,以及写死在文件里的 RPATH 或 RUNPATH;对不是自己构建的二进制,最后这一项值得看一眼,因为它会改变加载器查找库的位置。加固一行回答的正是 checksec 回答的问题,依据也相同:PIE 取自类型和 DF_1_PIE,NX 取决于 PT_GNU_STACK 是否可写可执行,RELRO 则按是否存在 PT_GNU_RELRO 以及是否设置 BIND_NOW 分为无、部分和完全。已剥离符号是指文件没有 SHT_SYMTAB,也就是 strip 去掉的那张表;动态符号表仍在,所以被剥离的库依然导出它的名字。有两件事它不做:不反汇编,也不告诉你是否启用了栈保护或 FORTIFY_SOURCE,因为这两者都要在符号表里找特定名字,而不是读一个头部标志。大端和 32 位文件同样能正确读取,因此从路由器或嵌入式镜像里取出的 ARM、MIPS、PowerPC 二进制和 x86-64 一样打得开。
使用方法
- 把二进制拖到方框里:没有扩展名的可执行文件、.so、.o 或核心转储都可以。
- 先看头部一行的架构和类型。PIE 可执行文件和共享对象都是 DYN,下面的解释器一行会告诉你是哪一种。
- 查看加固标签:发行版构建通常是 PIE、NX 和完全 RELRO,出现橙色标签就值得在分发前解释清楚。
- 在依赖库里看加载器将要查找的共享库,在 RUNPATH 里看二进制额外加入的非标准查找目录。
- 需要各部分大小时展开节列表:代码在 .text,常量在 .rodata,若保留了调试信息还会看到 .debug_* 节。
常见问题
- PIE 可执行文件和共享库有什么区别?两者都显示 DYN。
- ELF 类型确实相同,都是加载器可以映射到任意地址的位置无关代码。区别在于可执行文件有一个 PT_INTERP 程序头指明动态加载器(通常是 /lib64/ld-linux-x86-64.so.2),内核据此知道如何启动它;而库没有这一项,只会被别的程序加载。现代工具链还会在可执行文件的动态标志中设置 DF_1_PIE,这正是 readelf 报告的依据,也是本工具优先采用的判断;当旧链接器没有写入该标志时,再退回到看有没有解释器。
- PIE、NX 和 RELRO 实际防的是什么?
- PIE 让内核把二进制加载到随机基址,使 ASLR 不只作用于库,也作用于程序自身的代码;没有它,gadget 地址就是固定且已知的。NX 把栈标记为不可执行,注入的 shellcode 无法被直接跳转执行。RELRO 让重定位表在启动后变为只读:部分保护的是 main 之前解析的那些,完全则会提前解析所有函数,从而把 GOT 也设为只读,堵住经典的 GOT 覆写手法。三者都是链接期属性,所以无需运行就能从文件里读出来。
- 为什么说已剥离符号,我却还能看到函数名?
- 因为有两张符号表。这里说的剥离是指没有了 SHT_SYMTAB,那正是 strip 去掉、调试器需要的那张。动态符号表 SHT_DYNSYM 必须保留在任何导出或导入符号的文件中,否则动态链接无法工作——所以被剥离的库仍会列出它导出的一切,被剥离的可执行文件也仍会列出它导入的内容。这也是为什么 nm 说没有符号,而 nm -D 仍能打印出一份列表。
- 能读其他架构或大端的二进制吗?
- 能。头部开头的类别字节和数据字节说明文件是 32 位还是 64 位、使用哪种字节序,之后每个字段都通过这两者来读取,因此 AArch64、ARM、MIPS、RISC-V 或大端 PowerPC 的二进制与 x86-64 一样准确。常见机器类型按名称显示,其余显示原始编码。它做不到的是判断该二进制能否在你的机器上运行,那取决于内核、ABI 和库,而不只是头部。
- 构建 ID 有什么用?
- 它是链接器写在注释节里的哈希,用来标识这一次具体的构建。发行版用它把二进制和单独分发的调试符号对应起来:调试文件放在 /usr/lib/debug/.build-id/xx/yyyy.debug,拿到核心转储的调试器即使面对被剥离的二进制也能找到正确的符号。由于编译输出稍有变化 ID 就会改变,它也是判断两个文件是否真属同一次构建的可靠依据。
- 二进制会被上传到什么地方吗?
- 不会。文件用浏览器的 File API 读取,由页面里的 JavaScript 解析。没有任何内容发往服务器,也不存在可以接收它的服务端组件。这一点在本工具上尤其重要:你要检查的二进制往往正是不便上传的东西。页面加载后断开网络,一切照常工作。
相关工具
Mach-O 二进制检查器
在浏览器中解析 macOS/iOS 二进制:通用文件中的架构、段与节、依赖的 dylib、rpath、UUID 与代码签名。
PE 检查器:Windows EXE 与 DLL 查看
在浏览器里打开 Windows 的 .exe、.dll、.sys 或 .efi:架构、子系统、导入表、导出表、节,以及是否开启 ASLR、DEP 和 CFG。
Java 类文件分析器
在浏览器中解析编译好的 .class 文件:类文件版本与对应的 Java 版本、访问标志、常量池、字段、方法和引用的类。
WebAssembly 模块检查器
在浏览器中解析 .wasm 文件:各段大小、带完整类型的导入与导出、内存页数、start 函数,以及 name 与 producers 自定义段。
Mbox 归档查看器
在浏览器里切分 .mbox 归档:邮件边界、解码后的头部、MIME 结构、会话线索与重复 Message-ID,全程不上传。
SQLite 数据库检查器
在浏览器中打开 .sqlite 或 .db 文件并读取结构:页大小、编码、日志模式,以及每张表的真实行数。