把一个原生二进制丢进 Ghidra 或 IDA 之前,最好先弄清楚它是什么:面向哪种 CPU,是库还是可执行文件,链接了哪些库,构建时开了哪些加固选项,有没有哪一部分像是被加了壳。通常这意味着要依次跑 file、readelf、otool、nm、strings 和一个 checksec 脚本,而且还得看你手头是什么操作系统。
这个工具把这些信息集中在一个页面里,支持 ELF(Linux、Android、BSD、固件)、PE(Windows 的 EXE、DLL 和驱动)以及 Mach-O(macOS 和 iOS,包括通用二进制)。文件头和各类表都在浏览器里解析,不会运行、反汇编或上传文件。
使用步骤
- 准备好要看的二进制:ELF 可执行文件或
.so,Windows 的.exe、.dll、.sys,或者 Mach-O 可执行文件、.dylib、通用二进制。文件里的任何代码都不会被运行。 - 把它拖到上方的拖放区,或者点“选择文件”。文件头和各类表在浏览器里解析,文件不会上传。
- 先看基本信息(格式、架构、位数、文件类型),再看安全特性表,然后是带熵值的节区、导入导出和字符串。
真实输出示例
我们下载了 SQLite 官方的 64 位 Windows DLL,把 sqlite3.dll 拖进本页,再把页面显示的结果复制下来。排版做了压缩(标签和值放在同一行,长表格做了截断),所有值都原样保留。
样本: sqlite-dll-win-x64-3540100.zip 里的 sqlite3.dll(SQLite 3.54.1,公有领域),2026-11-02 从 sqlite.org 下载 (sqlite.org/download.html)
基本信息
格式 PE32+
架构 x64 (0x8664)
位数 64 位
字节序 小端
文件类型 DLL (库)
入口点 RVA 0x3779 (VA 0x180003779)
子系统 WINDOWS_GUI
时间戳 2026-10-16T15:16:21Z (0x6ad23fc5) (可复现构建会在这里存一个哈希值)
链接器版本 14.51
映像基址 0x180000000
文件大小 3.4 MB
SHA-256 4b59d3cded9dc1608544160f3b4b10ac974c6ac0d6ffc23064e5f4c8dbd05aea
imphash 04d6d066d04f6497fcb78013cf2630a0
符号 导入 126 个,导出 379 个
安全特性
ASLR(DYNAMIC_BASE) 是 DYNAMIC_BASE
高熵 ASLR(64 位) 是 HIGH_ENTROPY_VA
DEP / NX(NX_COMPAT) 是 NX_COMPAT
控制流保护(CFG) 否 no GUARD_CF
SafeSEH 或无 SEH(32 位) 不适用 table-based exception handling
带 Authenticode 签名(未验证) 否 empty security directory
强制签名校验(FORCE_INTEGRITY) 否 no FORCE_INTEGRITY
.NET 程序集(CLI 头) 否
节区(Section) (9)
名称 地址 文件偏移 文件大小 内存大小 权限 类型 熵
.text 0x1000 0x400 2.8 MB 2.8 MB r-x CODE 5.84
.rdata 0x2c7000 0x2c5800 419.0 KB 418.7 KB r-- IDATA 5.15
.data 0x330000 0x32e400 35.5 KB 44.6 KB rw- IDATA 3.06
…
.reloc 0x360000 0x357400 16.0 KB 15.6 KB r-- IDATA 2.85
链接的库 (1)
KERNEL32.dll 导入
导入与导出 (导入 126 个,导出 379 个)
FlushFileBuffers 导入 KERNEL32.dll
GetDriveTypeW 导入 KERNEL32.dll
…
sqlite3_open 导出 #150 0x37dd
…能做什么
输入。 拖入或选择一个文件,最大 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;没有节区头的二进制则读PT_DYNAMIC指向的符号表)及其类型;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:栈不可执行(
- Go 构建信息:Go 可执行文件会显示
go version -m输出的内容:Go 版本、主包和主模块、每个依赖模块的版本、校验和以及=>替换,还有构建设置(-buildmode、-compiler、-trimpath、-ldflags、CGO_ENABLED、GOOS、GOARCH、GOAMD64或GOARM64、vcs、vcs.revision、vcs.time、vcs.modified等)。还可以按go version -m的原样格式查看和下载。这条记录在-ldflags="-s -w"和strip之后依然存在;文件看起来是 Go 程序但记录已经没了时,报告会直接说明。 - 字符串:至少 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。Go 构建信息按 Go 自带的 debug/buildinfo 读取:在 .go.buildinfo(ELF)、__go_buildinfo(Mach-O)或第一个可写数据节(PE)里找 16 字节对齐的 \xff Go buildinf: 头,然后解码 Go 1.18 起的格式(头后面紧跟带长度前缀的版本和模块信息字符串)或 Go 1.13 至 1.17 的格式(指向 Go 字符串的指针,按头里给出的指针宽度和字节序、经段映射读出)。每个字符串上限 4 MiB。
每次读取都做边界检查,文件里声明的每个数量在使用前都有上限:节区、段、加载命令和库各 4,096 个,符号 100,000 个,单个表 64 MiB。某个表损坏或被截断时,只跳过这一部分并记在“说明”里,报告的其余部分照常显示。worker 运行超过两分钟会被终止。
SHA-256 用 WebCrypto 计算。WebCrypto 不支持流式哈希,所以会把文件读进内存一次,熵和字符串扫描也复用这份数据。PE 的 imphash 采用 pefile 的算法(get_imphash):按表中顺序取标准导入,DLL 名转小写并去掉 .dll、.ocx 或 .sys,拼成 dll.function,再算 MD5。Go 构建信息在 Go 1.27 和 Go 1.17 为 Linux(amd64、arm64、386、大端 ppc64)、Windows 和 macOS 编译的程序上与 go version -m 逐行核对过。各项结果都在为本工具编译的测试二进制上和 pefile、llvm-readelf、llvm-readobj、otool、nm、codesign、llvm-strings 的输出核对过。
文件如何保持私密
文件不会上传:
- 工具运行在一个单独的框架(iframe)里,来源是
tools.rea-reverse.com。下面说的处理都在这个框架里、在你的设备上完成。 - 这个页面在正文之后展示一个广告。广告脚本运行在
rea-reverse.com上,而框架属于另一个源(origin),浏览器不允许广告脚本或本页的任何其他脚本读取你拖入的文件或结果。 - 框架的内容安全策略拦截它的脚本能发起的所有请求(
connect-src 'none',也不加载任何第三方资源)。框架不能自行打开窗口或让本页跳转;只有你点击报告里的链接时才会打开页面。它传给本页的只有自身高度和下面这些统计事件。 - 解析、哈希、熵计算和字符串扫描都在你设备上的 Web Worker 里完成。
- 节区、符号、库和字符串都以纯文本显示,文件里的任何内容都不会被当作 HTML 解析或执行。
- 统计事件只有粗粒度信息:成功或错误码、格式(
elf、pe、macho或fat)、粗略的架构(如x86-64、arm64)、大小区间和耗时区间。不会包含文件名、哈希、符号名、字符串或文件的任何其他内容。框架把事件交给本页,由本页发送。完整列表见隐私页。 - 不想要任何广告和统计?在单独页面打开工具。
如何自己验证
- 打开浏览器开发者工具的 Network(网络) 面板,加载本页。发往
tools.rea-reverse.com的请求就是框架:它的 HTML、样式、字体和脚本,以及 Worker 脚本/_astro/binary-worker-*.js。发往 Google 域名的请求是本页的广告。 - 清空日志,然后分析一个二进制,切换一次切片,再下载字符串。在过滤框里输入
domain:tools.rea-reverse.com:最多只会再出现一次 Worker 脚本/_astro/binary-worker-*.js(为下一次运行准备的新 Worker),没有任何请求带着你的数据。广告请求可能还会继续,但它们来自本页,不带框架里的任何内容。 - 点开来自
tools.rea-reverse.com的binary-overview/文档,查看 Headers:它的Content-Security-Policy里有connect-src 'none'和frame-ancestors https://rea-reverse.com。在 Chrome 里,Application(应用)> Frames 也能看到框架的源和策略。Worker 运行在default-src 'none'; script-src 'self'; connect-src 'none'这条策略下,浏览器不允许它发出任何网络请求。 - 检查隔离:在 Console(控制台) 里,上下文选
top,运行document.getElementById('tool-frame').contentDocument,结果是null;frames[0].document会抛出SecurityError。广告脚本拿到的也是这个结果。 - 或者先打开页面再断网(关掉 Wi-Fi,或在 Network 面板勾选 Offline),然后分析文件,照样能用。
局限
- 不分析代码。 没有反汇编、反编译、控制流或模拟执行。这些请用 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)。二进制没有节区头时(固件里很常见,sstrip之后就是这样),动态符号从PT_DYNAMIC恢复:DT_SYMTAB和DT_STRTAB经PT_LOAD段换算成文件偏移,符号数取自DT_HASH,没有的话取自DT_GNU_HASH的哈希链。两种哈希表都没有时,表的结尾只能估计(到DT_STRTAB或DT_VERSYM为止),报告里会注明。这种文件的.symtab已经没了,所以只列动态符号。处理器专用的段类型和节区类型(0x70000000起)按文件的e_machine命名(MIPS_ABIFLAGS、ARM_EXIDX、RISCV_ATTRIBUTES等),不认识的显示为LOPROC+0x…。程序头必须位于文件前 64 KiB 内,超过 2^53 的 64 位偏移(内核映像)会被拒绝。 - Go 构建信息来自 Go 链接器写入的记录。不用模块(GOPATH 模式)构建的程序只有 Go 版本;Go 1.12 及更早版本构建的程序不读取。混淆器和加壳工具可能删掉或加密它,这时如果 Go 专用节区或 Go build ID 还在,报告会说明没找到记录(加壳后的文件可能根本不显示 Go 部分),本工具不会再从符号或
runtime.buildVersion推断 Go 版本。特别大的记录最多保留 10,000 个模块和 1,000 项构建设置。 - 字符串只找可打印 ASCII(
0x20–0x7e),单字节或 UTF-16LE 编码单元。其他编码、压缩数据里的字符串以及运行时拼出来的字符串都找不到。 - 其他格式(没有 MZ 头的 COFF 目标文件、静态库、Java class 文件、WebAssembly)不解析。
.wasm请用 WASM 分析工具。
合规
请只分析你自己编译的程序、开源软件、CTF 题目或你获得授权评估的文件。尊重所分析软件的许可证(包括其中限制逆向工程的条款)以及适用的法律。参见免责声明。
对应的命令行
file 给出格式和 CPU(macOS 自带的 file 5.41):
$ file sqlite3.dll
sqlite3.dll: PE32+ executable (DLL) (GUI) x86-64, for MS WindowsLLVM 的 objdump -p 打印 PE 头(这里是 macOS 自带的 /usr/bin/objdump,Apple LLVM 21.0.0;Linux 上用 llvm-objdump -p)。DllCharacteristics 里是 ASLR 和 DEP 标志,安全目录为空说明没有 Authenticode 签名:
$ objdump -p sqlite3.dll
…
Characteristics 0x2022
executable
large address aware
DLL
…
Magic 020b (PE32+)
…
Subsystem 00000002 (Windows GUI)
DllCharacteristics 00000160
HIGH_ENTROPY_VA
DYNAMIC_BASE
NX_COMPAT
…
Entry 4 0000000000000000 00000000 Security Directory
…
Entry e 0000000000000000 00000000 CLR Runtime Header
…$ objdump -h sqlite3.dll
…
Sections:
Idx Name Size VMA Type
0 .text 002c53cf 0000000180001000 TEXT
1 .rdata 00068aa8 00000001802c7000 DATA
2 .data 00008e00 0000000180330000 DATA
…
8 .reloc 00003e8c 0000000180360000 DATA$ shasum -a 256 sqlite3.dll
4b59d3cded9dc1608544160f3b4b10ac974c6ac0d6ffc23064e5f4c8dbd05aea sqlite3.dll常见问题
怎么判断一个 DLL 是 32 位还是 64 位?
把它拖进来,看基本信息里的“格式”和“架构”:PE32+ 是 64 位映像,PE32 是 32 位映像,架构一栏给出 CPU,比如上面的 SQLite DLL 是 PE32+、x64 (0x8664)。file 和 objdump -p 打印的是同样的 Magic 和机器类型字段。
能当作在线 checksec 用吗?
可以,用来先看一眼没问题。安全特性表依据的东西和 checksec 是同一类(文件头、标志位和导入的符号名),对 ELF、PE、Mach-O 用的是同一套方式,也不用安装任何东西。措辞有意保持中性:缺少某个特性只是构建方式的事实,不代表存在漏洞。
在这里打开二进制,文件会被上传吗?
不会。文件在你的浏览器里解析,不会发到任何服务器,文件里的代码也不会被执行或反汇编。
为什么某个节区的熵接近 8?
压缩或加密过的数据看起来是随机的,而随机字节的熵接近每字节 8 比特。UPX 之类的壳、内嵌的 .zip 或图片资源、加密的载荷都会这样。代码和文本通常在 4.5 到 6.5 之间,比如上面 SQLite 的 .text 节区是 5.84。
共享库显示“PIE:不适用”,是有问题吗?
没有问题。共享库本身就是位置无关的,PIE 这个问题只针对可执行文件。同理,NX、PIE 和 RELRO 对目标文件也不适用,因为目标文件不会被单独加载。
为什么 fat 二进制里的偏移都很小?
通用二进制里 Mach-O 的偏移是相对每个切片开头的,和 otool 的输出一致。切片列表里写着每个切片在文件中的起始位置。
更新于
相关教程
- 用 REA + Ghidra 免费分析原生二进制:在同样的二进制上反编译、搜索字符串、查交叉引用、追踪功能。
- 用 AI 逆向 Windows EXE/DLL:REA + Ghidra 实操:从这里列出的 PE 导入导出,一路找到背后的函数。
- macOS 应用逆向:用 REA 分析 Mach-O、Swift 符号和 NIB 界面:应用包里的 Mach-O、Swift 符号和 NIB。
- 用 AI agent 做二进制补丁对比:先在这里确认两个版本的架构和节区对得上,再比较它们。
- ELF / PE / Mach-O 在线查看:读懂三种格式的基本信息、节区和符号,判断构建产物是否已 strip。
- 不运行就能判断 EXE / DLL 是 32 位、64 位还是 ARM64:Machine 和 Magic 字段,以及 .NET AnyCPU 程序集为什么看起来像 32 位。
- 检查自己构建的二进制加固选项:同一个程序开关加固参数各编一次,对照这里的安全特性表。
- 这个 Mac 应用是不是通用二进制?:对比通用二进制的 arm64 和 x86_64 切片,找出缺切片的依赖和未签名的切片。
- 从固件 .bin 里提取 SquashFS 根文件系统:切出并解包路由器的根文件系统,再把里面的 BusyBox 和守护进程放到这里查看。
- CTF 逆向入门:从 file、strings 到拿到第一个 flag:把这里的格式、字符串和节区信息当作练习题的前三步。
- 用 REA 分析 Go 二进制:读出 Go 版本、依赖模块和 VCS 提交:从 build info 里读出 Go 版本、依赖模块和 VCS 提交,去过符号的构建也能读。
- 用 REA 调用 Frida:给自己编译的原生程序做动态插桩:在这里的符号表里找到函数名之后,到自己编译的程序里在运行时 hook 它。