ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

从PEID到DIE:查壳工具的进化与命令行批量识别实践

从PEID到DIE:查壳工具的进化与命令行批量识别实践

简介:Detect It Easy(以下简称DIE)是一款专业而强大的查壳与文件识别工具,在安全分析与逆向工程中用途广泛,尤其适合需要快速识别程序加壳类型、排查恶意样本或验证软件保护方案的场景。相比传统查壳工具PEID,DIE对超大型文件、复杂壳以及特殊格式的读取能力更强,能够一次性检测到底层信息,且支持Windows、macOS与Linux三大平台,并内置简体中文等多国语言界面。资源包以RAR压缩格式发布,整体大小约十三点五五兆字节,解压后共有一千三百六十二个文件,其中以脚本文件、HTML说明文档、动态链接库、可执行程序以及Qt相关资源为主,还包括多种插件与皮肤模块,目录结构清晰,便于使用者按需调用。目前已有四千一百四十七人学习或下载,覆盖安全运维、恶意代码分析、软件调试等多个方向。工具本身绿色免安装,支持文件拖放、右键菜单、自定义插件、脚本编写与十六进制编辑,拿到后即可直接使用,也可通过扩展机制构建个人查壳环境,整体实用性很强。

1. 从 PEID 换到 DIE:查壳工具这一步,解决的是“识别不上”的老问题

做样本研判和二进制分析的人,大概率都经历过这一幕:拿到一个看着不对劲的 exe,第一反应是扔进查壳工具里扫一下。以前我习惯开 PEID,可这几年越来越难受——PEID 的特征库停留在十几年前,遇到新版本 Visual Studio、Go、Rust 编译出来的程序,或者这两年常见的保护壳变种,经常直接回一个 Unknown。真正让我下决心换成 DIE(Detect It Easy)的,是一次应急分析里,同一个文件在 PEID 下完全认不出,切到 DIE 后不仅报了壳的类型,还把编译器、区段、熵值全列了出来。DIE 并不神秘,本质上它还是靠签名库在匹配,只是在特征库更新、分析维度和命令行支持上把 PEID 甩开了一个时代。这篇文章不吹“最强”,只讲清楚它比 PEID 好用在哪里,以及你把它接进日常工作流时真正要避开的坑。

2. 从 PEID 换到 DIE 前,先搞清楚 DIE 的“签名库”和扫描引擎

2.1 PEID 为什么老了,DIE 的签名机制强在哪

PEID 当年流行的原因很简单:体积小、打开就拖文件、结果直观。但它本质上是一个用固定特征库做字典匹配的工具,数据库多年不更新,对新编译器和新壳的覆盖率早就跟不上。更麻烦的是它还经常误报,看到一个字节串就敢断定是某个壳,实际可能只是程序里某个数据恰好撞上了特征。这种“宁可错杀一千”的态度在应急分析里很危险,你拿着错误结论去逆向,等于在错误的入口点浪费一晚上。

DIE 的底层思路不同:它的签名库是独立维护的文本化规则,社区持续在更新,新发布的壳和编译器版本通常几个月内就会有人提交签名。DIE 的签名不止覆盖加壳程序,还能识别编译器、链接器、安装包框架、加密库和混淆器。更重要的是,它不会拿一条特征就下结论,而是把文件按区块拆开,分别计算熵值、检查导入表、扫描区段权限,最后把命中的签名按相关度一起列出来。换句话说,PEID 给你一个答案,DIE 给你一串带着上下文线索的证据链,最终判断还是你自己下。

PEID 和 DIE 的核心差别,用一张表能看得很清楚:

对比项PEIDDIE
特征库更新停滞多年,依赖手动收集插件社区维护,随新版本持续更新
分析维度基本只看壳特征编译器、壳、加密库、区段、熵、导入表多维输出
误报处理单条特征命中即报多条命中按相关度排序,可结合上下文判断
批量能力无命令行,只能手动拖文件提供 diec 命令行,支持脚本和 JSON 输出
跨平台支持仅 WindowsWindows / Linux / macOS 均有发行版

这也是为什么我现在遇到不熟的程序,第一选择总是 DIE,而不是把旧 PEID 插件翻出来碰运气。

2.2 首次使用 DIE:GUI 布局和一次完整检测的操作顺序

DIE 不需要安装,下载对应平台的压缩包解压后直接运行。Windows 下按体系结构选 x64 版本,打开后就是一个主窗口,菜单栏有“选项”和“扫描”两个关键入口。

首次上手,按这个顺序走一遍最稳:

  1. 打开 DIE,把目标文件直接拖进主窗口。
  2. 默认状态会自动执行快速扫描,窗口左侧或上方会列出分析维度标签页。
  3. 先切到“签名”标签页,看命中了哪些特征,注意列表中可能有多个条目。
  4. 再看“区段”标签页,观察有没有 UPX0、UPX1、.vmp0 这类典型加壳区段名。
  5. 最后看“熵”标签页,代码段的熵值如果在 7.0 以上,通常意味着内容被压缩或加密过。

这套顺序的核心逻辑是先看结论、再看证据。快速扫描消耗的资源很小,十来个文件逐个拖进去也不会有压力。真正要谨慎的是那个“扫描”菜单里的深度扫描选项,它的开销跟快速扫描不是一个量级,适合单个文件上才开。

提示:DIE 的“签名”标签页里,命中列表是可能有多条的。后面小节会专门讲怎么从一堆命中里挑出真正跟壳有关的那个。

2.3 别把 Signature 第一行当“唯一答案”

DIE 的识别结果里,第一行命中并不一定代表该死的壳。举个例子,用 Visual Studio 编译的程序,DIE 经常会先命中“Microsoft Visual C++”编译器的特征,然后才是壳的特征。如果你只盯着第一行,很容易误以为这个程序没有加壳,实际上壳的特征就排在第二行。这就是 DIE 跟 PEID 的另一个区别:PEID 只有一个框,DIE 把信息分成多条,让线索之间互相印证。

我常用的复查流程是这样:先看签名标签页里所有命中,筛出跟保护框架相关的条目;然后对比区段名和入口点地址,如果区段里有明显不属于编译器的异常段名,比如 .aspack、.vmp0、.themida,基本可以直接认定加了壳;最后确认熵值,代码段熵值接近 7.9 的,说明代码被整体加密保护,哪怕签名列表里显示的只是一个编译器名称,也要继续用深度模式再扫一次。签名列表是起点,不是终点。

3. 用 diec 做命令行查壳:批量识别与 JSON 输出的落地写法

3.1 为什么命令行是 DIE 比 PEID 好用的一大半原因

PEID 没有命令行接口,这意味着你拿到一批样本时,只能一个一个拖进窗口,然后手动记录结果。这个动作在样本量超过十个以后就让人烦躁,超过几十个基本就是在烧时间。DIE 恰好补上了这块短板,它随主程序一起发布了一个命令行工具,Windows 下叫 diec.exe,Linux 和 macOS 下叫 diec。用法非常简单,对着单文件执行一次就能拿到基础信息:

diec -i suspicious.exe

执行后,命令行会输出一个文本报告,包含文件格式、入口点、编译时间戳、区段信息和签名扫描结果。这个命令适合快速验证单个文件,不用打开 GUI。输出里的签名部分,跟 GUI 的“签名”标签页内容基本一致,都是罗列所有命中的特征。所以你在批处理脚本里完全可以拿它当主力,把结果收集起来统一看。

命令行工具还有很多参数可选,但实际高频使用的就那几个:-i 指定输入文件,-j 输出 JSON 格式,-o 把结果写到文件而不是打印到屏幕。比如我想保留格式化的报告,可以这样写:

diec -i suspicious.exe -o report.txt

3.2 批量扫描:for 循环加 JSON,拿到“结论版”报告

真正体现 DIE 价值的是批量场景。假设你有一个 samples 目录,里面放了十几个待分析的可执行文件,现在要快速判断哪些加了壳、用的什么壳。一条命令就能把所有文件扫完:

mkdir -p results for f in samples/*.exe; do diec -j -i "$f" > "results/$(basename "$f").json" done

这段脚本的逻辑很直接:遍历 samples 目录下所有 exe 文件,对每个文件调用 diec,用 -j 参数让输出变成 JSON 格式,然后以原文件名为前缀保存到 results 目录。我把文件名用双引号包起来,是为了防止文件名里有空格或特殊字符导致命令被拆断,这是写批处理脚本时最容易忽略的细节。跑完以后,results 目录里每个样本都对应一份 JSON 报告,后续想提取壳名、编译器信息,写一段几行的 Python 脚本就能批量汇总,不用人工翻看十几个纯文本文件。

JSON 报告里的核心部分是签名列表,每一项表示一次命中,通常包含签名名称和一个置信度级别的描述。批量判断时,我会优先看签名列表里有没有疑似壳的条目,把文件分成“明确加壳、不明但可疑、没有加壳”三堆,然后再对有疑问的样本逐个开 GUI 做复查。这种分级处理的做法,比让批量脚本直接给出一个“是/否”的硬结论要稳得多,因为 DIE 的扫描结果只是线索,不是判决书。

3.3 CLI 参数速查表与组合建议

命令行工具的参数不算多,但不同组合应对的场景完全不同。我把最常用的几个参数列一下,方便你直接对照着用:

参数作用建议使用场景
-i指定输入文件路径所有查询的基本参数
-j以 JSON 格式输出结果批量扫描、写脚本解析时
-o将输出写到指定文件需要保留单文件报告时
-a自动检测模式不确定具体选项时可直接用
-d输出调试级别信息需要排查 DIE 自身问题或特征库加载异常时

单文件快速判断用diec -i file就够;需要保存在档案里用-o;写自动化流程统一用diec -j -i file然后自己解析。需要注意的是,不要默认在命令行里开启深度扫描,命令行模式下如果加了深度扫描参数,单个文件的耗时可能从几十毫秒涨到几十秒,在批量任务里会直接卡死整条流水线。深度扫描模式应该留在 GUI 里单独用,或者在确认单个文件有趣时才手动指定。

4. 深度扫描与启发式:DIE 怎么识别未知壳,以及怎么判断“它在撒谎”

4.1 Deep Scan 在做什么:入口点附近的额外检查

快速扫描主要对文件里的静态特征做匹配,速度快,但遇到经过变形处理的壳就容易失效。DIE 的深度扫描模式则是在整个文件范围内做更细粒度的检查,尤其关注入口点(EP)前后的代码区域。因为绝大多数壳的思想是一致的:先让壳代码接管控制流,在内存里解出原始代码,再跳到原始入口点。无论你怎么变形,这个流程总会在某个位置留下痕迹。

深度扫描就是去找这些痕迹的。它会在入口点附近寻找解压循环、重定位处理、反调试检测这类模式,然后把发现的线索跟签名库关联起来。一个典型场景是:快速扫描返回 Unknown,但切到深度扫描后,DIE 能在入口点附近找到跟 UPX 解压循环相似的特征序列,于是给出一个带不确定性的识别结果。这个模式在文件经过某种程度的代码变换时特别有用。

4.2 Heuristic Scan 是统计和规则,不是玄学

DIE 的启发式扫描(Heuristic)做得相对保守,它不像某些 AI 检测引擎那样拿大数据训练模型,更多是依靠统计规则来判断。比如检查区段权限的组合:正常编译的程序,代码段通常是“可读+可执行”,数据段是“可读+可写”;加壳程序为了在运行时会修改代码,经常会把代码段设置成“可读+可写+可执行”,这个特征在正常程序里很少出现。启发式引擎抓的就是这类统计层面的异常。

这套机制的优点是能识别签名库里还没有的新壳,缺点是误报率比特征匹配高不少。我在实际使用中把它定位为“分诊工具”而不是“诊断工具”:启发式扫出某种可能性之后,一定会用深度扫描和手动看汇编来佐证,不会只凭它输出的一个名称就写结论。特别是涉及样本建档的时候,误判的影响会被放大,你在报告里写错一个壳名,后面所有人都在跟着错的方向走。

三种扫描模式的差异和应用场景,可以这样区分:

扫描模式适用场景速度误报倾向建议用法
快速扫描批量筛选、日常初判极快低默认手段
深度扫描快速扫不出结果、特征被混淆较慢中单个文件复核时手动开启
启发式扫描样本可能用了未知变种壳慢较高作为线索,必须配人工验证

4.3 用熵值当快速分诊器:三个标签页配合着看

DIE 的熵值分析是个经常被低估的功能。熵值反映数据的混乱程度,正常编译的代码段熵值一般在 5.0 到 6.5 之间,数据段可能更高一些;如果你看到某个区段的熵值接近 7.9,那基本可以断定这段数据被加密或者压缩过。壳的存在就是为了隐藏真正的代码,所以一个加了壳的文件,代码段的熵值通常远高于正常编译的程序。

但这里有一个很容易翻车的细节:程序里如果嵌入了大量加密配置、图片资源或者压缩数据,这些区块的熵值也会很高,不代表文件一定加了壳。我一般会把熵值、签名列表和区段名这三样放在一起看:签名命中了壳名称、区段里出现了非正常的映射名字、代码区段熵值显著偏高,三者同时成立,才下“加壳”的结论。任何一个单独的维度都支持不了最终判断,这是我踩过几次坑之后沉淀下来的习惯。

5. 查壳工具翻车现场:DIE 也会误判的四个高频场景与处理思路

5.1 场景一:DIE 报 Unknown,PEID 反而报了壳名

现象:同一个文件放进 PEID 能认出壳,DIE 却返回 Unknown,直觉上会觉得是不是 DIE 识别能力不行。原因:PEID 的特征匹配比较粗放,一条简单的字节特征就能触发命名;DIE 对签名的可信度要求更高,宁可说 Unknown 也不愿意给一个不确切的答案。另一个更常见的原因是本地 DIE 的签名库版本太旧,没有包含这个新壳的定义。

解决:先查签名库是否最新,把 DIE 更新到新版本或替换新的签名数据库,再扫一次;还是报 Unknown 的话,切到深度扫描模式。如果深度扫描也没有结果,这个 Unknown 反而是一个重要结论——说明样本可能用了私有壳或新型壳,值得投入精力手工分析,不要因为 PEID 报了一个名字就直接采信。

5.2 场景二:双重壳只看到外层

现象:DIE 扫描一个文件,报了 MPRESS,你开始分析脱壳,却在后续逆向中发现内部还有一层 VMProtect。原因:DIE 的识别是基于静态特征的,内层壳的特征被外层壳覆盖,静态扫描看不到。这个现象在外层壳做了反特征处理时更明显。

解决:把“一次扫描的结论”当作“阶段性结论”,不要当作最终答案。我处理可疑文件的习惯是:脱掉一层壳之后,把脱出来的中间文件重新丢进 DIE 再扫一次,确认没有新的壳特征出现,才算走完查壳这一步。发现报的是 MPRESS、UPX 这类偏轻量壳时,脑海中要默认它可能只是第一层,往后要多留一个心眼。

注意:脱壳过程会改动文件本身,每脱完一层立刻扫描,中间文件别覆盖原件。原文件才是你回溯证据的根。

5.3 场景三:批量扫描时默认开了 Heuristic,结果跑了一整夜

现象:写好的批量脚本一开始跑得很顺,突然某一天扫描速度慢了几个数量级,排到第二天还没跑完,而且生成了一堆带可疑名称的结果。原因:脚本里加上了深度扫描或启发式扫描参数,这两个模式对每个文件都要做额外的计算,在样本量大的时候消耗会被成倍放大,误报也跟着变多。

解决:批量场景只让快速扫描开跑,把深度扫描和启发式当作人工复验环节的工具。我现在的批处理模板里默认只有-i和-j两个参数,宁可第一次跑出一些 Unknown,也不会让几百个文件在启发式模式里空转一整夜。文件量大的时候,速度本身就是正确率的组成部分。

5.4 场景四:把字符串标签页里的“壳字样”当成壳证据

现象:在 DIE 的字符串标签页里搜到了“UPX”或者“MPRESS”字样,就直接断定文件用了对应壳。原因:程序自身的数据区完全可以包含这些字符串,有些文件甚至会用壳的名字作为诱饵来干扰分析,正应了那句话:当你看到一个特征时,先想它是不是被制造的。

解决:字符串只是线索,不是证据。壳结论的确认路径应该是:签名列表里出现了对应条目,区段名呈现出壳特有的模式(比如 UPX0、UPX1),入口点代码形态符合壳的解压逻辑。三者相互印证之后,再把这个壳名写进分析结论。字符串标签页我只用它来寻找可疑路径名、配置文件和硬编码密钥,不给它裁决策件权限。

6. 把 DIE 放进自己的工作流:一条“脱壳前必查、脱壳后复验”的习惯

DIE 用熟之后,你会发现它的价值不只在“查出这个文件是什么壳”,更在于它给你重新定义了一套工作习惯。我现在处理任何可执行文件,都固定走三步:第一步,快速扫描,确认有没有壳特征;第二步,看熵值和区段,判断文件有没有被整体加密;第三步,如果第一阶段有疑点,先把文件原样保存进归档,再决定要不要深入分析。这三步里 DIE 承担的是第一步和第二步,第三步其实是它帮你划出的边界。

值得留意的是,DIE 的判断应该在脱壳前后各跑一次。脱壳前扫描确认保护框架的类型,脱壳后扫描验证中间文件是否还残留旧的壳特征。这个复验环节看起来简单,但它能避免一个很低级的错误:你以为壳已经处理干净了,实际上只拆了第一层,内层还在原地等你。我在自动化流程里也做了同样的逻辑,快速扫描后如果结果里带有壳相关条目,自动进入人工复核队列,而不是直接把结果写进报告。

最后分享一个我自己的教训。有一段时间我在批处理脚本里直接用签名列表的第一条结果做归档标记,跑了快一个月,回头抽查才发现一批文件全都被标成了编译器版本,真正的壳特征排在签名列表后面被忽略了。后来我把规则改成“有壳相关命中就先归档为可疑,等人工确认后再定级”,误判率才算压下来。DIE 替你做的是把可能性摆到桌面上,继续往哪个方向走,还是要人来做决定。希望帮到你。

本文还有配套的精品资源,点击获取

RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进