首页 / 资讯中心 / 文章详情

UEFITool-UE 0.10.0实战:拆解UEFI固件与提取BIOS模块

UEFITool-UE 0.10.0实战:拆解UEFI固件与提取BIOS模块 ★ FEATURED ARTICLE
简介UEFITool-UE-0.10.0是一款面向UEFI固件开发与调试的经典工具源码包适用于系统固件分析师、BIOS工程师及对UEFI内部实现感兴趣的进阶开发者。该版本提供固件解析、FFS文件提取与固件信息查看等核心能力能帮助使用者深入理解UEFI启动流程、固件模块组织与安全机制。压缩包共70个文件以33个C头文件和18个C源文件为骨干配合9个C源文件、Qt界面文件ui/pro及工程配置文件整体约191KB便于直接阅读源码、编译学习或二次移植。资源包含UEFIExtract与UEFITool两个工程模块可学习FFS解析、固件块提取、GUID/PE映像处理等关键实现目录中还附有README及工程配置说明。目前已有402人学习下载对想从代码层面掌握UEFI固件结构与工具链的人来说是一份体量紧凑、内容明确的参考资料。1. UEFITool-UE 0.10.0 是谁的刚需把 BIOS 固件拆成一棵可读的树拿到一块主板 BIOS 或者电脑厂商发布的固件升级包多数人第一反应是“先反汇编”这个思路十有八九会卡住。UEFI 固件不是一段连续可执行代码而是一层层嵌套的容器镜像里包着 Firmware VolumeVolume 里包着 FileFile 里又包着 Section中间还夹杂压缩段、填充区、GUID 表。直接拖进反汇编工具你看到的是失效的地址和没解开的 LZMA 数据块。UEFITool-UE 0.10.0 这类解析器解决的就是“拆”的问题它把整片固件还原成一棵可视化的树让你能按模块导出 PE32、ACPI 表、驱动和变量区再做哈希比对、差异分析或反汇编。这个系列是 UEFITool 新引擎分支专门优化了对现代固件里非标准嵌套、新压缩算法和怪异对齐的识别。适合搞固件安全测试、供应链审计、主板维修定位问题以及想在固件层面做二道检验的运维和开发。2. UEFI 固件为什么难拆从 Firmware Volume 到 Section 的嵌套模型想用好 UEFITool-UE 0.10.0得先理解它在拆什么。UEFI 规范和 Intel 的 PI 规范定义了一套“容器套容器”的固件布局。表面上看 BIOS 是一颗 SPI Flash 芯片的完整二进制实际上是多个区域的拼盘最前面是 Intel 固件描述符IFD中间是若干个 Firmware Volume后面可能还有 NVRAM 变量区、Gigabyte 或 OEM 自定义布局。解析固件核心工作就是把这些区域按头和指针逐步解开。2.1 FV→File→Section 三层容器反汇编之前得先解对壳Firmware VolumeFV是最大的逻辑容器头部有 FV Header记录着 GUID、块大小、格式版本。FV 内部被切成一连串 Firmware File每个 File 有 FFS Header头部里定义了文件类型有 PEIM、DXE 驱动、ACPI 表、NVRAM 变量、FFS_PAD 填充文件等。而一个 File 内部还可以继续拆成多个 Section常见的 Section 类型包括 PE32 镜像、UI 字符串、版本字符串、依赖表达式DXE_DEPEX和 GUID 定义数据。UEFITool-UE 解析时就是沿着这条链逐级剥读 FV Header 找 FFS 条目边界读 FFS Header 判断 File 类型和大小如果 File 包含压缩段通常是 EFI_COMPRESSION_SECTION就用内嵌的 Tiano LZMA 或 Efi 压缩算法解开再递归进去找嵌套的 FV 或 File。理解了这个模型你才看得懂工具界面里那些带缩进的树节点是什么意思也才知道为什么一个“DXE 驱动”真正的可执行文件藏在好几层里。多数固件分析翻车都是因为绕过了这层嵌套直接拿整机固件当二进制看。2.2 为什么选 UEFITool-UE 而不是老版 UEFITool 或 MMTool老版本 UEFITool 和 MMTool 本身能完成基本提取但对两个场景无能为力遇到非 Intel 标准的 FV 对齐方式时边界识别错乱导致后续模块位置全偏移遇到嵌套压缩段或新版本 LZMA 时要么解不开要么直接报错退出。UEFITool-UE 是社区维护的新引擎分支改动不是加几个按钮而是把“解析骨架”重写了。它按规范逐个解释 FV Map、FfsMap 和 GUID 定义遇到未知结构会标注出来而不是静默跳过这对找隐藏模块意义很大。还有一个选型理由UE 分支能同时输出“原样保护区”和“拆解结果”你看得到哪个包头被保留、哪一层被解压。相比之下不少老工具把解压过程当黑匣子只给结果不给过程。对调试来说能知道“这个文件在镜像里的物理偏移是多少、逻辑偏移是多少”非常有价值。同类的工具还有 UBU 和 ifrextractor但 UE 的覆盖面最全对新固件支持最主动。如果你手里既有 BIOS 整片镜像又有 OEM 出的 .cap 升级包我一般建议只留 UE 一个工具走完全流程避免多个工具导出来的中间产物互相矛盾。3. 拿到 tar.gz 后本地编译 0.10.0依赖、构建和第一次打开镜像UEFITool-UE 官方发布形式里Linux 平台经常给的是源码包。这个包不大编译也不慢但有一个很多人栽过的坑不装 ICU 库就直接 cmake编出来的程序要么无法处理 UTF-16 字符串要么在解析 UI Section 时段错误。我建议按下面这套顺序走能少踩两个坑。3.1 编译前的依赖检查Qt 与 ICU 版本为什么不能省图形界面依赖 Qt命令行工具依赖 ICU。ICU 在这里不是可选项UEFI 内部字符串大量使用 UTF-16LE若没有 ICU 的转换支持UNI 文本和 UI 段内容会乱码严重时直接崩溃。此外还需要 cmake 和一个可用的 C 编译器。# Debian/Ubuntu 系示例其他发行版对应包名自行替换 sudo apt update sudo apt install -y cmake g build-essential qtbase5-dev libicu-dev tar -xf UEFITool-UE-0.10.0.tar.gz cd UEFITool-UE-0.10.0 cmake -B build -DCMAKE_BUILD_TYPERelease cmake --build build -j$(nproc)这段命令背后的逻辑先让系统具备三样东西——Qt 头文件和库提供窗口框架、ICU提供字符集和文本处理、cmake提供构建配置。cmake 后面-DCMAKE_BUILD_TYPERelease不是玄学它会让编译器开优化UEFITool 处理几十 MB 固件时Release 和 Debug 的耗时差距能到数倍。-j$(nproc)是并行编译核心多时能明显提速。构建完build目录里会出现UEFITool、UEFIExtract等可执行文件。注意如果你用的是 Qt6 环境需要确认 CMakeLists 里是否已经把find_package(Qt6)的兼容处理写好某些版本源码只适配 Qt5硬编译会报错。这时最简单的做法是同时装 qt5-default 并显式把 QT_DIR 指到 Qt5 的 lib/cmake 路径。别用系统里残留的旧 Qt4初期版本名看着一样编译出来的界面能跑一打开固件就崩。3.2 用图形界面定位一个 DXE 驱动并导出 body编译完成后先把整片固件丢进图形界面跑一遍。./build/UEFITool firmware.rom界面左侧是一棵完整的树。展开第一个 Firmware Volume再展开里面的 Firmware File你会看到每个文件的信息区里有 GUID、类型、大小、物理偏移和校验状态。要导出一个模块右键某个 File选项里能看到两种导出Extract as is和Export body。它们的区别直接决定你后续工作是否顺利选项导出的内容适用场景Extract as is包含 FFS Header 在内的完整原始区段需要保持镜像布局、回写打补丁时Export body去掉 FFS 头只保留 Section 数据把驱动拖进反汇编器、算哈希、做差异对比我第一次用的时候没注意这两个选项全用 Extract as is 导出结果对比某个驱动和官方清单时哈希怎么都对不上折腾了半天才发现多了几十字节的头部。理解体导出逻辑之后习惯是先Export body拿到干净的 PE32再视情况决定是否回原镜像里做 patch两条路径分开走而不是混在一起。界面右下角的 Structures 标签页值得养成习惯选中一个 File这里会逐字节解释各字段含义包括 EFI_FFS_FILE_HEADER 里的 IntegrityCheck、Type、Size。遇到解析警告先切到这个页看哪一段偏移没对上再决定是修正对齐还是换别的 FV 布局去解析。4. 命令行批量提取固件UEFIExtract 的参数、输出与自动化图形界面适合单次、探索式分析但固件库稍大一点就撑不住了。一次固件更新里往往包含 EFI 驱动、OpROM、ACPI 表、微码、Logo 图片逐个人工导出会累到怀疑人生。这时候应该切到命令行工具 UEFIExtract把它跑成批处理脚本再把输出目录交给下游分析。4.1 先跑 -h 看清楚开关不同版本的 CLI 语义有差异UE 0.10.0 的命令行参数和更老的 0.28.x 不是完全兼容的所以我建议你路径确定后先执行一次帮助命令把本版本的开关含义确认清楚别凭记忆直接写脚本。./build/UEFIExtract -h常见输出里会出现几个核心开关一个作用于提取模式一个用于指定输出类型还有一个用于只提取文件名匹配的条目。不同版本写法略有差异有的版本用-a表示 all files有的版本要求-all也有的版本允许-acpi只提 ACPI 表、-drivers只提驱动。实际使用中我一般这样落地# 全量提取把所有能识别的内容按目录结构导出 ./build/UEFIExtract firmware.rom -all # 仅输出概要而不提取适合快速摸清固件组成 ./build/UEFIExtract firmware.rom -table这两种模式对应两类诉求-all是要真正拿到文件做后续分析-table只是先看这个固件里有什么。前者耗时和镜像大小成正比后者速度快、输出精炼适合大批量固件先“扫雷”。如果固件是 Qcow2 里导出的原始 flash 或者带 SPI 描述符的完整镜像UEFIExtract 也能直接吃不需要预先切分区域。它会自动跳过 IFD 里的非 UEFI 区域只解析可识别的 FV。4.2 全量导出后怎么从 dump 目录里找关键文件全量提取完成后输出目录会按 GUID 命名生成大量子目录结构大致是firmware.rom.dump/ 9454F4D0-A2C7-4F8E-9F2A-.../ body header 某个 Section 名.扩展名 ...一个重要经验不要靠文件名找东西。UEFI 固件里的 File 很少带人类可读的名字UI Section 里可能有也可能没有。可靠的定位方式是先看 table 输出拿到关键 GUID再去 dump 目录里按 GUID 对应文件夹找。另一个好用的小习惯是导完后直接对 body 文件批量算 SHA256把结果作为基线存下来后续固件版本做比对时省很多时间。dump_dirfirmware.rom.dump find $dump_dir -name body -print0 | sort -z | xargs -0 sha256sum baseline_sha.txt wc -l baseline_sha.txt这里find ... -name body只挑导出的正文文件不碰 headersort -z是为了让后续 diff 时文件顺序固定sha256sum输出的一列哈希加一列路径就是天然的指纹清单。执行完可以用wc -l检查数量是否和 table 里展示的 Firmware File 总数一致不一致时先不要启动下游分析回到图形界面看是哪些文件没有被正确解析。批量脚本在这里体现价值你不需要打开窗口、右键、层层展开一条命令把所有固件拍完输出稳定的目录结构后面无论是 grep 还是接入自动化流程都很顺。这也是命令行版存在的真正意义——把“拆固件”从人工操作变成投产流程里的一个环节。5. UEFI 解包避坑清单5 个让分析翻车的常见问题做得多了遇到的问题翻来覆去就是那几类。我把最容易让人卡住的现象、原因和解决办法列一下每一条背后都有真实的排查经历照着排查能帮你少走很多弯路。5.1 FV 文件解析失败不是固件坏了是引擎版本不对现象用旧版 UEFITool 打开某个 2023 年后发布的板卡固件树形结构里几个 FV 直接显示红色错误或者展开后是空的有时整个界面只解析出第一个 FV后面全断掉。直觉判断是固件损坏重新下载还是同样结果。原因这些新固件采用了非标准 FV 对齐方式或者 FV Header 里的 ExtHeaderOffset 指到了一个旧引擎没预料的偏移。旧引擎按固定对齐扫描边界就错了整个 Volume 的 FFS 条目全偏移。解决改用 UE 0.10.0 打开同一镜像如果还是失败看一下 Structures 页里具体是哪一段偏移对不上然后手动在设置里尝试不同 FV 对齐猜测。UE 的解析器对这类“非标”容忍度高很多多数情况能自动跳过填充区并正确识别边界。记住一个判断标准解析后 FFS 条目数量和布局符合预期才叫正常一片红不要视为“固件加密了”。5.2 提取回来的模块哈希对不上小心 Extract as is 和 body 的区别现象从固件里提取了某个 DXE 驱动和之前抓的官方发布版对比 SHA256怎么都不一样。查了文件大小发现比官方版本大了几十字节或者恰好小了几十字节。身体感受以为自己拿错了固件或者怀疑驱动被修改过白排查了半天。原因提取时选了Extract as is导出的内容包含 FFS Header通常 24 或 32 字节而官方发布版通常只对应 body 里的 PE32。带不带头哈希当然不同。解决需要做版本比对时统一用Export body导出再算哈希。脚本里也一样直接用find ... -name body取正文件即可。如果某个模块 body 还是个嵌套容器例如一个 FV 文件里包含多个 FFS用图形界面对该文件再次执行提取直到拿到真正的 PE32 数据段。5.3 满屏 Pad File 不是异常真正的风险藏在未命名模块里现象展开 Firmware File 列表时目录里一半条目是Pad File旁边还跟着一堆大小只有几十字节的小文件。新手看着觉得解包没解对或者固件被恶意填充了于是反复重跑。原因FFS_PAD 是规范允许的填充条目用于对齐或预留空间不是异常。但另一个情况要警惕有些 OEM 会把实际模块的 Name 字段留空或者写成不常见 GUID导致工具识别成“未命名模块”排在列表末尾。解决Pad File 直接跳过不要浪费时间。未命名模块则要认真对待记录其 GUID、类型、大小和依赖表达式。如果在两个固件版本的差异分析里新版固件多出一个未命名 DXE 驱动这就是需要重点审计的对象。我的习惯是先把所有未命名模块单独导出看是否有导入表、是否有 EFI Shell 命令字符串至少确认它不是空壳。5.4 升级包不等于整片镜像cap/exe 要先解出内核现象分析主板厂商给的 BIOS 升级包下载下来是个 .exe 或 .cap 文件直接拖进 UEFITool-UE 0.10.0界面提示无法识别文件类型。有人因此判断升级包加密了或者 UEFITool 不支持该厂商。原因.cap 或 Windows 的 .exe 升级包外壳里往往包着一段 EFI 应用程序运行时校验完硬件型号才把真正的 FV 释放到内存或写入 flash。UEFITool 只识别裸固件镜像、FV 镜像和部分带 IFD 的完整 ROM它不认识这个“可执行外壳”。解决先拆外壳。常见做法是把 .exe 用解包工具拆出内部的 .cap如果升级包是 .fd 或 .bin但带非标准前缀可以先在 010 Editor 或十六进制工具里搜索_FVHFV 头签名从该位置往后裁剪出合法 FV 区域再丢回 UEFITool。裁剪时注意保留完整 FV Header 和全部块数据只去掉前面的 shell 段。这个流程熟练后处理 OEM 升级包比处理完整 ROM 还快。5.5 NVRAM 不能当普通文件乱改改完校验直接挂现象全量提取后发现了 NVRAM 变量区文件有人觉得改掉其中某个启动项再刷回去就能实现启动配置调整。结果刷完机器无法点亮或者反复自动重置到默认值。原因NVRAM 区有自身的变量存储结构每个变量还有 Attribute区域级有校验和和写保护状态更重要的是多数固件在 DXE 阶段会校验变量区完整性。直接替换整个 NVRAM 文件等于把固件打成了不一致状态轻则配置被清空重则启动卡死在变量初始化。解决UEFITool 导出的 NVRAM 只用于分析不要直接回写。要修改单个变量要么用成熟的 UEFI 变量编辑工具连到设备的 SPI 上进行规范化改写并处理好校验要么在 UEFI Shell 环境里用命令调整。把“解析固件”和“修改固件”分开看待是我在做固件分析时最看重的一条边界。6. 进阶用法把 UEFITool-UE 0.10.0 做成固件差异分析基线工具顺手之后下一步是把它嵌进固件安全测试流程。我觉得最实用的进阶技巧是用脚本对比两次导出的 table让固件升级带来的差异一目了然而不是肉眼在一堆 GUID 里翻找。另一个习惯是提前维护一份 GUID 白名单减少无效告警。6.1 用脚本对比两次导出的 JSON 表抓新增模块先在每个固件版本上执行UEFIExtract -table保留结构化的输出。两个版本的表格分别保存为old_table.json和new_table.json然后用下面的脚本比较import json, sys def load(fn): with open(fn, encodingutf-8) as f: return json.load(f) def key(item): # 以 GUID 和类型作为唯一标识 return (item.get(guid, ), item.get(type, )) base {key(x) for x in load(old_table.json)} new {key(x) for x in load(new_table.json)} for item in load(new_table.json): k key(item) if k in base: continue print(新增:, item.get(guid), item.get(type), item.get(size))说明load读两个 JSONkey函数用 GUID 加类型做唯一键集合运算直接筛出新增条目最后打印的新增项往往是最需要人工审计的候选对象。脚本只看 GUID 和类型不看文件名是因为 UEFI 固件里文件名字段不可靠GUID 才是规范定义的稳定标识。跑完之后把新增项粘贴到查询平台看它属于哪个厂家、哪个协议再决定要不要继续往下挖。这里一个细节部分固件每次升级都会重新生成签名证书的 GUID第一次跑会发现证书相关条目全是新增这不是异常属于正常发布行为白名单里放过即可。6.2 提前维护一份 GUID 白名单让差异分析少一点噪音差异分析跑多了会发现 80% 的新增条目是固定的微码更新、板卡 Logo、ACPI 表。只有剩下 20% 需要人肉看。把前者沉淀成白名单能显著减少每次升级审计的噪音。我的做法是在固件分析工作目录下维持一个whitelist.json记着已知安全模块的 GUID、用途和最后验证日期脚本比对时直接过滤掉。# 把当前固件导出的 GUID 列表和历史的正常基线打一个 diff grep -oE [0-9A-F]{8}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{12} new_table.json | sort -u current_guids.txt comm -13 (sort -u whitelist_guids.txt) current_guids.txt这个操作等于把白名单当“已知好人”comm -13输出的是当前固件里出现了但白名单里没有的 GUID。出现一个陌生条目再回到图形界面定位、导出 body、查导入表或字符串效率高很多。以前没有这套流水线时每次升级公告出来我都得重新摸一遍固件重复劳动严重现在把白名单做进流程升级审计基本能压缩到十几分钟。这些年折腾固件的最大教训是别把解析工具当黑匣子。它给出的 GUID、边界、校验和本身就是审计线索比对着线索去核对模块远比闷头反汇编或盲目信任旧脚本可靠。工具轮子很多建立一套自己的差异基线才是让分析从手工走向半自动的关键。希望帮到你。本文还有配套的精品资源点击获取
阅读完成 · 觉得有帮助?
咨询建站