资讯动态

PEiD查壳工具进阶:从“Nothing found”到自定义特征库识别未知壳

发布时间:2026/9/9 3:15:28 来源:尧图企业网站定制
简介PEiD侦测未知壳加强版是一款面向逆向工程与安全分析人员的查壳工具包聚焦识别可执行文件所加的UPX、ASPack、MEW等已知壳并通过扩展签名库、行为分析插件增强对未知壳的侦测能力。资源共45个文件体积仅2.48MB核心包含PEiD.exe主程序、36个dll插件如FileInfo、kanal、ImpREC、UNUPX等以及txt/ini配置文件与签名数据另有bpl运行时库和少量c/h源码文件方便使用者了解插件接口并二次开发。目前已有233人学习下载。包内插件覆盖文件信息扫描、OEP查找、资源查看、CRC校验、壳脱壳辅助等方向适合搭建便携式查壳实验环境初级用户可用该加强版直接扫描程序获取壳类型中高级安全从业者则可结合源码与插件机制研究未知壳特征提取与绕过思路作为日常逆向分析工具箱中的有效补充。 第一次用PEiD的人十有八九会在扫到一个文件、看到“Nothing found”之后直接关掉窗口然后在报告里写下“未加壳”。我早年做样本分析时也干过这事后来被一个加了自定义壳的测试程序狠狠教育了一顿——那次教训之后我才明白PEiD这类查壳工具的真正价值不在于它“查到”了什么而在于它“查不到”的时候你能不能把那个“Nothing found”当成一条新的侦查线索。这篇文章要讲的就是怎么把一个官方停更多年的PEiD打造成一台能持续识别未知壳的“加强版”查壳机从它背后的特征码识别原理到手工扩充特征库的具体方法再到拿到一个未知壳样本时的完整分析链路。无论你是刚入门逆向的小白还是做恶意软件分析的老手这套思路都能直接用。1. 一个停更十几年的老工具为什么还没被淘汰1.1 它解决的是“看穿外壳”这一步先聊一个基础问题壳到底是个什么东西。Windows可执行文件加壳后程序原本的入口点被替换成一段“外壳代码”原始代码以压缩或加密的形式躺在文件里不直接可见。程序运行时壳的代码先拿到控制权在内存里把原始代码还原出来最后再跳转到真正的程序入口点也就是常说的OEP。对外部分析者来说不把壳这层皮看穿静态分析看到的全是壳的代码几乎拿不到原始逻辑。PEiD干的活就是在你开始正式分析之前快速判断“这个文件到底有没有壳如果有是什么壳”。这个判断直接影响后续所有决策壳是UPX还是Themida处理方法完全不一样。前者可能一条upx -d就能脱掉后者可能要花几天时间处理反调试、虚拟化和代码混淆。所以查壳虽然只是分析流程里的第一步却决定了后面几步走多快、走多远。1.2 新工具辈出它却一直留在工具箱里现在做个逆向或者病毒分析大家的工作流里通常不止一个查壳工具。DIEDetect It Easy和Exeinfo PE都是后起之秀特征库更新快、识别能力强DIE甚至能识别PE、ELF、Mach-O、APK等多种格式。按道理说PEiD这种官方版本停在0.95、十几年没有更新的老古董应该被淘汰了但实际很多人工具箱里依然留着它。原因很现实。PEiD是单文件绿色工具双击就能用不需要装运行库不依赖网络在隔离沙箱和Windows XP老分析虚拟机里跑得飞快。很多老病毒分析环境恰恰就是XP虚拟机新工具在这里反而不如PEiD顺手。再加上它的特征库文件userdb.txt是开放结构社区和个人随时可以往里加特征这意味着“版本旧”不等于“能力旧”。别人整合好的所谓“加强版”本质也只是预先塞了更多特征码进去而已真正会玩的人都是自己往里喂特征的。顺带说一句后来移动App加固流行也有不少人问PEiD能不能查APK的壳——不能PEiD只管Windows的PE格式APK加固得靠DIE或者JEB这类工具。不过它背后那套“特征匹配”的思路放到DEX壳上依然成立。2. “未知壳”卡在哪一步PEiD的查壳机制拆解2.1 壳在PE文件里留下的三类指纹想理解PEiD为什么查不出未知壳先得知道它查的是什么。壳不是完美隐身衣它必须在PE文件里留下痕迹而且是藏不住的那种。最典型的指纹有三类。第一类是入口点EP附近的机器码。壳的入口代码通常是“解压循环”或“解密循环”这种循环的指令组合在正常编译器生成的代码里非常少见。举一个经典例子UPX加壳后的程序入口处经常是一连串pushad、mov esi、lea edi、push edi之类的组合后面跟着rep movsb这类搬运指令。编译器不会生成这种开头但壳会。第二类是区段名字。老一代壳的区段名特征极其明显UPX会生成UPX0、UPX1ASPack会有.aspack、.adataNSPack会有NSP0、NSP1Themida会有.themidaVMProtect会有.vmp0、.vmp1。这些名字虽然不是官方规范强制要求的但绝大多数壳开发者懒得改等于免费送了个招牌。新一代壳学聪明了会起一些伪装名或者随机名这招就没那么灵了。第三类是区段权限。普通PE文件里代码段一般“可读可执行”数据段“可读可写”很少出现一个区段同时具备可读、可写、可执行三种权限。但壳要动态解密和改写代码它的区段往往就是RWX权限俱全。拿CFF Explorer或者PeStudio看一眼区段表这种异常权限组合本身就是强烈的加壳信号。2.2 特征码匹配的底层逻辑PEiD的识别机制说白了就是模式匹配。它解析PE文件头拿到入口点RVA换算成文件里的实际偏移然后把入口点附近的一段机器码抠出来去和userdb.txt里的每一条签名做比对。比对上了就显示壳的名字都比不上就显示Nothing found。签名的写法很直白就是一段十六进制字节序列用??表示任意字节。比如PEiD老数据库里UPX的经典签名长这样[UPX 0.89.6 - 1.02 / 1.05 - 2.90 - Markus Laszlo] signature 60 BE ?? ?? ?? ?? 8D BE ?? ?? ?? ?? 57 89 E5 50 54 53 56 52 8B ?? 8F ?? ?? ?? ?? 83 EC 28 ep_only true这里的ep_only true表示只在入口点处匹配这条签名。因为UPX的解压循环入口非常稳定锁定EP就够用了。如果这个壳的入口特征会变或者壳代码会把真正的解密逻辑放在别处就需要把ep_only设为false在全文件范围内搜索。代价是扫描速度变慢、误报概率也变高。2.3 老特征库为什么查不出“未知壳”原因其实就一句话特征码匹配是典型的“已知威胁检测”对没见过的东西天然失灵。PEiD 0.95自带特征库覆盖的主要是2000到2010年代流行的壳后来出现的VMProtect 3.x、Themida 3.x、Enigma等新一代壳入口逻辑完全变了老库里根本没有对应签名。更麻烦的是壳作者也在不断进化。往入口处插入花指令、随机化入口点、修改区段名、把特征字符串加密这些手段都能让老特征库失效。以前靠“看到UPX0区段就报UPX”的日子早过去了。所以遇到一个PEiD报Nothing found的文件不代表它没壳只代表它的壳特征不在你的签名库里。这也是“加强版”这个需求最核心的痛点——不是工具不行是特征库没喂饱。3. 亲手打造“加强版”给PEiD扩充特征库的完整流程3.1 读懂userdb.txt的签名语法PEiD的特征库文件就是同目录下的userdb.txt纯文本格式用记事本就能编辑。修改之前强烈建议先备份一份免得不小心写坏了一整行导致PEiD读取异常。签名的基本结构就是一个方括号的名字加上一行signature再根据需要加ep_only等选项[MyTestProtector 1.0] signature 60 E8 ?? ?? ?? ?? 5D 81 ED ?? ?? ?? ?? 8D 95 ?? ?? ?? ?? ep_only true几个字段的注意点。方括号里的名字就是识别成功后界面上显示的内容建议写成“壳名版本号”的格式方便后续区分同系列不同版本。signature是十六进制字节序列每个字节之间要有空格这个格式一个字都不能错。??是通配符但不要在一段特征里连续堆太多通配符否则误报率会直线上升。ep_only true意味着只在EP处匹配适合那些入口特征足够稳定的壳如果换成falsePEiD就会在整个文件里搜索这段特征速度慢且容易误报能不用就不用。3.2 从“Nothing found”到新签名的五个步骤我自己的习惯流程是这样的照着走基本不会出错。第一步先把待分析的样本拖进PEiD普通模式扫一遍再切深度模式和硬核模式各扫一遍确认是真的Nothing found。硬核模式会忽略ep_only限制强制全文件匹配有时候能捞到一些漏网之鱼。如果三种模式都查不到才进入下一步。第二步用x64dbg打开样本在入口点断下来单步走几步看代码行为。如果看到类似“从一个内存区域搬运数据到另一个区域”“动态获取API地址”的指令序列基本可以确定是壳在自解密。这一步是判断“有壳”最直接的手段比依赖任何工具都可靠。第三步静态提取特征。在调试器里选中EP附近的20到40个字节复制机器码或者用IDA直接把EP地址处的字节扣出来。挑特征的时候有个小技巧专挑那些正常编译器不可能生成的指令组合比如连续压栈后接rep movsb或者成片的xor、add花指令。这些片段信息量大作为签名最合适。第四步照着3.1的格式在userdb.txt末尾新起一个签名块保存文件重新打开PEiD拖入样本验证。如果还是Nothing found说明特征没写对或者壳在运行后才展开真实入口回去调整 ep_only 设置或者换一段特征字节。第五步也是最容易忽略的一步——复测。拿同系列其他版本的三五个样本跑一遍确认新签名能稳定识别同时又不会把普通编译器生成的文件误报成壳。复测通过之后这条签名才算真正可用。3.3 辅助工具生成特征但别指望全自动每次手工从调试器复制机器码再粘到文本编辑器里确实有点费手。OllyDbg和x64dbg圈子里有一些SigMaker类的插件可以选中一段代码后自动生成特征串省去手动整理的麻烦。但我的建议是可以拿来当辅助别全指望它。这类插件生成的签名往往非常长包含了大量非关键字节直接丢进userdb.txt只会让误报率暴涨。正确做法是把自动生成的签名当作草稿再手工裁剪去掉那些通用指令像push、mov这类高频指令只保留壳特异的组合最后控制在8到20个字节之间。特征太短容易撞车太长则失去普适性这个度需要在复测里慢慢调。4. 实战一个查不出来的样本是怎么被一步步定性的4.1 先读PEiD基础信息别急着关窗口有一回我拿到一个加了自定义壳的测试程序PEiD三个模式全扫一遍都是Nothing found。很多人到这里就直接放弃了但PEiD主界面中间那块信息列表其实还有一堆东西没看入口点、文件偏移、区段名、子系统、链接器版本、映像大小。那个样本的入口点显示在0x1A2D3C对于一个普通的32位程序来说这个位置非常奇怪——正常编译器生成的程序入口通常紧挨着启动代码节而不是飘在一个很深的偏移上。再看链接器版本显示0.00这也是个危险信号。编译器生成的PE头里链接器版本怎么也不可能填零只能是壳作者改过头或者根本没管这个字段。到这一步虽然不知道是什么壳但“这个文件有异常”的结论已经能下了。4.2 三路侦察入口点、区段表、资源段光有怀疑还不够我习惯再打开一个PE分析工具CFF Explorer或者PeStudio都行做交叉确认。重点看三处。第一看区段表。那个样本一共三个区段名字分别是.sys1、.sys2、.sys3正常的Visual C程序几乎不会起这种名字。更关键的是三个区段的权限全是可读、可写、可执行这种RWX组合在正常程序里极少出现但对壳来说却是标配。第二看入口点所在的区段。如果入口点落在最后一个区段而前面还有一个很大的空白区段往往是壳预留的解压目标区域。第三看资源段。加壳程序为了压缩体积资源往往已经被处理过表现为资源表很小甚至为空但文件整体体积却不小。这几个信号叠在一起就已经足够支撑“这是一个带壳程序”的结论了。注意PEiD查不出具体壳名不等于这个文件没壳把“查不出”直接等同于“没壳”是新手最容易踩的坑。4.3 动态调试确认把特征写成签名工具层面能确认“有壳”但要确定到底是什么壳最终得靠动态调试。我在x64dbg里重新加载样本停在系统断点后一路F8单步很快就看到一个明显的解压循环壳在往内存里搬运数据中间还穿插着LoadLibrary、GetProcAddress这类API调用用于动态解析导入函数。这种“边解压边修复导入表”的行为是绝大多数壳的共性。到这里壳的行为已经定性了剩下的就是把它的特征记住。我复制了EP处前30个字节的机器码挑了一段包含花指令和解压循环特征识别的片段写进userdb.txt再重启PEiD一拖稳定识别出这个自定义壳的名字。整个过程十分钟出头之后这个家族的新样本PEiD一眼就能认出来——这就是“加强版”的实际价值。5. 识别之后的下一步从“查出壳”到“定位OEP”5.1 为什么OEP是脱壳的核心目标查壳从来不是终点它只是分析链条的第一环。识别出壳的种类后真正的工作是找到原始入口点OEP把程序还原成可以静态分析的状态。壳的运行逻辑通常是一条固定路线先是壳入口初始化然后在内存里解压或解密原始代码接着修复导入表最后跳转到OEP。对分析者来说OEP就是那个“壳的工作结束、原始程序开始”的分界点。找到了OEP就能dump出一个相对干净的内存镜像再用PEiD扫一遍确认没有壳信息这时候整个文件才真正进入正常的逆向流程。定位OEP的方法很多ESP定律和内存断点是两种最容易上手的路径。5.2 两类壳的常用处理路径不同壳的研制路径差别很大我习惯把它们粗分成两类。一类是压缩壳UPX、ASPack、NSPack、MPRESS都算。这类壳的目的核心是压缩不做加密、不做反调试所以处理起来相对温和。UPX甚至可以直接用upx -d命令脱壳省时省力。ASPack和NSPack这类在调试器里用ESP定律几秒钟就能定位OEP。ESP定律的原理其实不复杂壳入口经常会先pushad把所有寄存器压栈压栈后栈顶刚好是进入壳之前的一个状态点对这个栈顶地址下硬件访问断点当壳即将跳回OEP时会访问这个地址调试器就能把断点停在跳转指令附近顺着跳转往前一步就是OEP。这个方法对压缩壳极其好用。另一类是保护壳Themida、VMProtect、Enigma这些属于此列。它们带反调试、代码虚拟化、完整性校验没有一键脱壳的捷径。面对这类壳与其死磕完整还原不如调整分析策略绕过反调试识别出哪部分逻辑被虚拟化了哪部分没有只分析可读的部分必要时再配合内存转储做局部还原。这类分析耗时以天计确实正常。需要强调一句以上所有方法请只用于分析你拥有或者已获授权分析的软件不要把它当作绕许可的思路。5.3 脱壳后的验证让PEiD再扫一次很多人脱完壳dump完就以为大功告成结果程序跑不起来又要回头排查。我的习惯是dump完成并修复导入表之后把生成的dump文件再丢进PEiD扫一次。这是一个非常直观的验证手段。如果扫描结果显示编译器信息比如“Microsoft Visual C 6.0”之类的字符串说明壳层已经剥掉OEP位置对了文件已经还原成接近原始编译产物的状态。如果还是显示之前的壳名说明OEP没找准dump出来的东西里还带着壳的尾巴。这个“脱壳前后PEiD结果对比”的方法比盯着代码纠结半天要省事得多。6. 别全信PEiD误报、干扰与多引擎交叉验证6.1 误报是怎么来的做了这么多年分析我早就学会了不百分之百相信单一查壳工具。PEiD会误报而且误报的坑还很隐蔽。最常见的一种情况是特征过宽。如果一条签名里通配符太多或者只包含了一段非常通用的指令序列它就可能同时匹配到多个完全不同的软件。比如某些花指令库被多个壳共用A壳的特征可能会命中B壳的文件。第二种情况是刻意伪装。壳作者会用工具在入口处插入一段正常编译器的入口代码或者塞一段其他壳的特征片段让查壳工具误判成别的产品。这就好比故意穿别人的外套目的就是误导监控。第三种情况是嵌套加载。一个文件里可能嵌入了另一个可执行体PEiD扫描时匹配到了嵌入体的特征而忽略了外层真正的壳。这种情况在捆绑类型的样本里特别常见。PEiD查到一个结果只能说明文件里有东西能“对上特征”至于这个东西是不是决定性保护层还需要人工判断。6.2 一套实用的多引擎验证工作流我自己的查壳工作流目前是三道工具并行。第一道用PEiD做快速过滤第二道用DIE交叉验证第三道用Exeinfo PE看版本细节。DIE的特征库活跃更新覆盖面广支持PE、ELF、Mach-O甚至APKExeinfo PE对壳的版本判断比较细。三个工具的结论一致时判断基本可信结论互相矛盾的时候以动态调试里看到的实际行为为准——壳到底在做什么调试器不会撒谎。还有一个让工具越用越强的习惯每当DIE能识别而PEiD不能我就把DIE给出的壳名和版本记下来去定位对应壳的EP特征补充进userdb.txt反过来如果PEiD能识别而DIE漏了也值得思考是不是DIE特征库也有盲区。查壳工具从来不是越多越好而是你越会喂它它就越懂你手里的样本。最后说点个人的习惯。我的userdb.txt里现在有大几十条自己补的签名很多就是在分析那些Nothing found样本时顺手加进去的。PEiD官方确实停止更新了但这恰恰是它最妙的地方——架子搭好了谁来喂特征谁就拥有一个定制版加强工具。下次再看到Nothing found别急着关窗口那其实是它在提醒你这里藏着一个还没被收录的未知壳等着你去把它变成已知。本文还有配套的精品资源点击获取

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价