简介:面向开发者、逆向工程学习者与需要访问程序内部素材的用户,这份资源提供了一套EXE可执行文件解压工具,用于从非安装类可执行程序中提取嵌入的图像、文本、音频及其他二进制资源,便于分析程序结构、复用素材或开展教学调试。压缩包共167个文件,约5.14MB,以91个txt说明文档、42个exe组件、7个dll动态库为主,另含ini配置、wcx插件、doc手册与htm帮助页等,主程序UniExtract.exe配合多语言配置与变更日志,目录中bin与docs分别承载运行库与使用文档,结构清晰便于查阅。目前已有3511人学习下载,适合希望快速上手资源提取、了解EXE内部组织方式的初、中级读者参考,使用时请遵守许可协议与版权法规。
1. 拿到一个 EXE 却只想看里面的文件:先把解压环境定下来
上周帮同事处理一个老项目遗留的安装包,对方只丢过来一个 EXE,说里面有几个配置文件和图标资源要单独取出来,不想真去装一遍。这种场景其实很常见:拿到一个自解压包、一个安装器、一个打包好的绿色软件,你只想看它肚子里装了什么,而不是让它往系统里写注册表、铺目录。EXE 文件解压这件事,说简单也简单,说翻车也真翻车——用错工具,轻则解出来一堆乱码文件名,重则把安装器当程序跑起来,系统里多出一堆卸载不干净的残留。这篇记录的就是我反复装过几套解压环境后,留下来能照着走通的那一套:工具怎么选、版本怎么定、参数怎么配、解不出来怎么救。适合手上正卡着某个 EXE 打不开、又不想重装系统的开发者。
2. 选工具与备环境:三类 EXE 对应三套解压方案
EXE 文件解压不是一招通吃。同样是.exe后缀,背后可能是 InstallShield、NSIS、Inno Setup、自解压 CAB、.NET 单文件打包,甚至是加壳后的可执行体。工具选错,等于拿螺丝刀撬锁。我一般先做一次「体检」,再决定用哪套方案,这一步花五分钟,能省掉后面半小时的瞎试。
2.1 先判断 EXE 的真实类型
在动手解压前,先确认它到底是什么打包方式。Windows 自带的能力加上一个十六进制查看就够初判,命令行里用findstr扫特征字符串是最快的办法。
# 在 EXE 所在目录执行,扫描常见打包器特征串 findstr /M /C:"Nullsoft" /C:"Inno Setup" /C:"InstallShield" /C:"WinRAR" /C:"7-Zip" target.exe # 用 certutil 看文件头,判断是否为自解压 CAB 或 PE 结构 certutil -dump target.exe | morefindstr的/M表示只输出匹配到的文件名,/C:后面跟的是要精确匹配的字符串。命中Nullsoft基本就是 NSIS 打包,命中Inno Setup就是 Inno 安装器,命中WinRAR或7-Zip说明它是个自解压压缩包。certutil -dump会把文件按十六进制和 ASCII 混排打印,前几百字节里能看到MSCF就是 CAB 自解压,看到PK开头则可能是 ZIP 伪装成 EXE。这一步不需要装任何东西,系统自带命令就能跑。
判断结果直接决定后面走哪条路:自解压压缩包类,7-Zip 右键就能开;NSIS 和 Inno 类,7-Zip 也能读大部分,但遇到新版打包器会失败,得换专用提取器;InstallShield 老版本则往往要专门的 unpacker。我一般把这三类工具都备着,不指望一个软件通吃。
2.2 工具版本与安装方式的选择
工具不在多,在于版本对得上。7-Zip 我固定用 23.x 以上的稳定版,太老的版本对新型自解压头识别率明显下降;NSIS 提取用 7-Zip 自带的7z命令行配合-t#参数,或者单独备一个nsisunz类小工具;Inno Setup 的提取则用innounp,这个工具更新慢,但对付 6.x 之前的 Inno 包足够。安装方式上,我倾向绿色版解压即用,不写系统目录,避免为了解一个包反而污染环境。
# 以 7-Zip 命令行版为例,解压到指定工具目录,不注册右键菜单 mkdir -p /opt/exe-tools/7z tar -xf 7z2301-linux-x64.tar.xz -C /opt/exe-tools/7z --strip-components=1 # 验证可执行文件能跑,并看版本 /opt/exe-tools/7z/7zz itar -xf解 xz 压缩包,--strip-components=1去掉顶层目录,让7zz直接落在目标路径下。7zz i是 7-Zip 的「显示支持格式」命令,输出里能看到它当前能识别的所有容器类型,包括CAB、NSIS、PE等。这一步的意义是确认工具本身完整、动态库没缺,而不是等到解压时才报一个含糊的加载错误。Windows 侧同理,下载 7-Zip 的.exe安装包后选「提取到指定目录」,把7z.exe和7z.dll放同一个文件夹即可,不需要管理员权限。
提示:工具目录尽量避开中文路径和带空格的路径。7-Zip 命令行对含空格路径的处理依赖引号,脚本里漏一个引号就会把参数拆错,这类问题排查起来很费时间。
2.3 建立可复用的解压工作目录
解压出来的东西往往几百上千个文件,散落在下载目录里根本没法看。我习惯给每次解压建一个独立工作目录,原始 EXE 只读拷贝进去,解压产物放子目录,这样即使解坏了,删掉整个目录就干净了,不会误伤原文件。
# 建立工作区:orig 放原始文件,out 放解压产物 mkdir -p ~/exe-work/{orig,out} cp target.exe ~/exe-work/orig/ cd ~/exe-work # 用 7-Zip 列出内容而不解压,先看结构再决定 /opt/exe-tools/7z/7zz l orig/target.exe7zz l是 list 的缩写,只列目录树不落盘,输出里会显示每个条目的路径、大小、修改时间和属性。先l再x是个好习惯:如果列表里出现大量$PLUGINSDIR、[NSIS].nsi这类条目,说明是 NSIS 包,正常;如果列表直接报Can not open the file as archive,说明 7-Zip 不认识这个头,得换工具。工作目录分离还有个好处——后面做批量解压脚本时,输入输出路径都是确定的,不会因为当前目录漂移而出错。
3. 分类型解压实操:从自解压包到安装器逐类拆
工具备齐、目录建好,接下来就是按类型下手。这一章按「自解压压缩包 → NSIS → Inno Setup → InstallShield」的顺序推进,每类给一条能直接抄的命令,并说清参数为什么这么写。顺序是有讲究的:越靠前的类型越常见、越好解,先跑通简单的能快速确认工具链没问题,再啃硬的。
3.1 自解压压缩包:7-Zip 直接开
自解压包(SFX)本质是「解压程序 + 压缩数据」拼在一起,7-Zip 能跳过前面的解压程序直接读数据段。这类包解起来最省事,一条命令就够。
# 解压自解压包到 out 目录,-o 指定输出,-y 全部确认 /opt/exe-tools/7z/7zz x orig/target.exe -oout/sfx -y # 如果标准解压失败,强制按 CAB 类型再试一次 /opt/exe-tools/7z/7zz x orig/target.exe -tCAB -oout/sfx-cab -yx是带完整路径解压,-o后面紧跟输出目录且中间不能有空格,-y表示对所有询问自动回答 yes,适合脚本化。第二条命令里的-tCAB是强制指定容器类型,当 7-Zip 自动探测失败但文件头确实是MSCF时,手动指定类型往往能救回来。我遇到过几次自动识别把自解压包当成普通 PE 的情况,加-tCAB就正常了。解完先看out/sfx里有没有setup.exe或data目录,有就说明数据段完整取出来了。
3.2 NSIS 安装包:识别 $PLUGINSDIR 与脚本段
NSIS 包的标志是解压列表里出现$PLUGINSDIR和[NSIS].nsi。7-Zip 对 NSIS 的支持比较成熟,但要注意它默认只解「数据段」,脚本段里的安装逻辑不会执行,这正是我们要的——只看文件,不跑安装。
# 列出 NSIS 包内容,确认脚本段和数据段都在 /opt/exe-tools/7z/7zz l orig/nsis-setup.exe | head -40 # 解压全部内容,包括 $PLUGINSDIR 里的插件 DLL /opt/exe-tools/7z/7zz x orig/nsis-setup.exe -oout/nsis -yhead -40只是截取前几十行看结构,实际使用时去掉即可。NSIS 包解出来后,$PLUGINSDIR目录里通常是安装过程用的临时插件,真正的业务文件在根目录或app之类的子目录。如果 7-Zip 报Unsupported method,多半是 NSIS 用了较新的压缩算法(如 LZMA2 的某些变体),这时换 7-Zip 更新版本,或者用专门的 NSIS 提取工具按脚本偏移量取数据段。我一般先升级 7-Zip 试一次,不行再上专用工具,避免一上来就引入额外依赖。
3.3 Inno Setup 包:innounp 的版本匹配
Inno Setup 打包的安装器,7-Zip 有时能读有时不能,取决于 Inno 版本和压缩设置。稳妥做法是直接用innounp,它专门解析 Inno 的安装脚本和数据段。
# 用 innounp 列出 Inno 包内容 innounp -l orig/inno-setup.exe # 解压到指定目录,-d 指定输出路径 innounp -x -dout/inno orig/inno-setup.exe-l是列表,-x是解压,-d后跟输出目录。innounp的版本要和 Inno 打包版本大致对应:太老的innounp遇到 Inno 6.x 会报Unknown version,这时要么找更新版,要么退回 7-Zip 试-t#自动探测。我踩过的坑是拿一个几年前的工具去解新包,报错信息含糊,折腾半天才发现是版本不匹配。判断办法很简单——innounp -v看它自己支持的版本范围,对不上就换工具,别硬试。
3.4 InstallShield 与 .NET 单文件:兜底方案
InstallShield 老包(尤其是 5.x、6.x 时代)结构复杂,7-Zip 和 innounp 都未必吃得下,常见做法是用专门的unshield处理 CAB 段,或者先用i6comp类工具列出内容。.NET 单文件打包则是另一回事,它本质是自解压的托管程序集,7-Zip 能解出里面的 DLL,但文件名可能被哈希化。
# InstallShield:先尝试 7-Zip 按 CAB 解,失败再用 unshield /opt/exe-tools/7z/7zz x orig/installshield.exe -tCAB -oout/is-cab -y unshield x out/is-cab/data1.cab -d out/is-files # .NET 单文件:7-Zip 解出后按文件头重命名 /opt/exe-tools/7z/7zz x orig/dotnet-single.exe -oout/dotnet -y file out/dotnet/*unshield的x是解压,-d指定输出目录,输入是 7-Zip 从 EXE 里剥出来的.cab文件。file命令用来确认解出来的无扩展名文件真实类型,比如显示PE32 executable就是 DLL 或 EXE,显示PNG image就是资源图。这一步是兜底:当专用工具都失效时,至少能把数据段抠出来,再靠文件头人工归类。效率不高,但比干瞪眼强。
4. 解压参数与输出管理:让产物可读、可复现
解压本身只是第一步,产物怎么组织、参数怎么固化,决定了这套环境能不能反复用。我见过太多人每次解压都手敲命令、输出目录随手起名,过两天自己都找不到解出来的东西在哪。这一章讲参数取舍和输出管理,目标是让同一类 EXE 的解压过程可以写成脚本、重复执行、结果一致。
4.1 关键参数逐个说清
7-Zip 命令行的参数不多,但几个容易混的必须分清。x和e的区别是前者保留目录结构、后者把所有文件平铺到一层;-o和-w分别是输出目录和工作目录;-t强制类型;-p设密码。解 EXE 时我几乎只用x,因为安装包内部的目录结构本身就是信息,平铺会丢掉层级关系。
| 参数 | 作用 | 解 EXE 时的建议 |
|---|---|---|
x | 带路径解压 | 默认用这个,保留目录树 |
e | 平铺解压 | 仅在只想要单个文件时用 |
-o<dir> | 指定输出目录 | 必填,且目录提前建好 |
-t<type> | 强制容器类型 | 自动识别失败时用-tCAB或-t# |
-y | 全部确认 | 脚本里必加,交互环境可省 |
-p<pass> | 指定密码 | 加密自解压包才用,注意别写进历史 |
-t#是个特殊写法,表示让 7-Zip 遍历所有已知类型去试,比逐个指定省事,但会慢一些。我一般在不确定类型时先-t#跑一次,看它最终匹配到哪个类型,再把这个类型固化进脚本。密码参数-p要特别注意:写在命令行里会进 shell 历史,敏感场景下用交互输入或者环境变量传递,别图省事直接拼在命令后面。
4.2 输出目录命名与批量脚本
输出目录我固定用「源文件名 + 类型」的格式,比如target-nsis、target-inno,这样一眼能看出是用哪套方案解的。批量处理时写个小脚本,把判断类型和解压串起来,避免每次手动选工具。
#!/usr/bin/env bash # 批量解压当前目录下所有 exe,按特征串自动选工具 set -euo pipefail SEVENZ=/opt/exe-tools/7z/7zz for f in *.exe; do base="${f%.exe}" if findstr /M /C:"Nullsoft" "$f" >/dev/null 2>&1; then "$SEVENZ" x "$f" -o"out/${base}-nsis" -y elif findstr /M /C:"Inno Setup" "$f" >/dev/null 2>&1; then innounp -x -d"out/${base}-inno" "$f" else "$SEVENZ" x "$f" -o"out/${base}-auto" -y || \ "$SEVENZ" x "$f" -tCAB -o"out/${base}-cab" -y fi doneset -euo pipefail让脚本在任一命令失败、用到未定义变量、管道中任一段失败时立即退出,避免错误被吞掉。base="${f%.exe}"是去掉后缀取基名。分支逻辑按特征串走:NSIS 用 7-Zip,Inno 用 innounp,其余先自动探测、失败再按 CAB 兜底。||后面的兜底命令只在前面失败时执行,这是脚本里处理「不确定类型」的常用写法。这个脚本不追求覆盖所有情况,但能处理八成日常遇到的包,剩下的手工介入。
注意:脚本里的
findstr是 Windows 命令,在纯 Linux 环境下要换成grep -a对二进制做字符串匹配,比如grep -aq "Nullsoft" "$f"。跨平台迁移时这类命令差异最容易漏,跑之前先确认当前 shell 环境。
4.3 解压产物的完整性核对
解完之后不能只看「有没有报错」,还要核对产物是否完整。安装包解压常见的残缺是数据段截断、资源文件缺失、文件名乱码。核对办法是比对文件数量和总体积,再抽查几个关键文件能否正常打开。
# 统计解压产物文件数和总大小 find out/target-nsis -type f | wc -l du -sh out/target-nsis # 抽查可执行文件和资源文件是否可识别 file out/target-nsis/*.exe out/target-nsis/*.dll 2>/dev/null | headfind -type f | wc -l数文件个数,du -sh看总体积,两个数字和 7-Zip 列表里显示的对得上,基本说明没截断。file抽查用来发现「扩展名是 dll 但内容其实是文本」这类错位,安装包里偶尔会有占位文件或重命名的资源。文件名乱码则多半是编码问题,NSIS 和 Inno 内部用 UTF-16 或本地代码页存文件名,解压工具处理不当就会出乱码,这时换工具或指定编码参数,别硬改文件名——改了就丢失原始信息了。
5. 避坑与排查:五条解压翻车记录
解 EXE 这件事,报错信息往往比命令本身还难懂。下面五条是我实际踩过、并且在不同机器上重复遇到的坑,按「现象 → 原因 → 解决」记下来,遇到同类问题可以直接对号入座。
5.1 报「Can not open the file as archive」
现象:7-Zip 对某个 EXE 直接报无法作为压缩包打开,但文件明明能正常运行。原因通常是这个 EXE 不是自解压包,而是真正的安装程序(比如某些 InstallShield 版本),数据段不在文件尾部连续存放,7-Zip 的探测逻辑找不到入口。解决办法是先按第 2.1 节做类型判断,确认是 InstallShield 就走unshield路线,别在 7-Zip 上反复试。我一开始总以为是文件损坏,重下好几遍才发现是工具选错了。
5.2 解出来一堆$PLUGINSDIR却找不到业务文件
现象:NSIS 包解压后满屏$PLUGINSDIR,真正的程序文件不见踪影。原因是 NSIS 把安装期临时文件放在这个目录,业务文件可能被压缩在另一个数据块里,7-Zip 默认只解了第一段。解决办法是确认 7-Zip 版本足够新,必要时用-t#强制遍历,或者换 NSIS 专用提取器按脚本偏移取全部数据段。判断依据是列表里业务文件名是否存在——存在但没解出来,就是分段问题。
5.3 文件名全是乱码或问号
现象:解压成功,但文件名显示为乱码、方块或问号。原因是安装包内文件名用非当前系统代码页编码,工具按默认编码解析导致错位。解决办法是换用支持编码指定的工具版本,或在 7-Zip 里确认是否有-mcp类代码页参数可用;实在不行,保留原始字节、用十六进制查看器对照恢复,不要凭猜测重命名。乱码文件名一旦改错,后续按名索引的脚本全废。
5.4 解压中途报「Data error」或「CRC failed」
现象:解压到一半中断,提示数据错误或校验失败。原因可能是下载不完整、文件被截断,也可能是安装包本身用了工具不支持的压缩算法。解决办法是先核对原文件大小和哈希,排除下载问题;确认文件完整后,换更新版本的 7-Zip 或对应专用工具。CRC 失败不要强行忽略继续解,解出来的文件大概率不可用,白费功夫。
5.5 在 Linux 下跑 Windows 工具报缺库
现象:把 Windows 版提取工具拿到 Linux 下跑,报缺少 DLL 或无法执行。原因是这些工具是原生 Windows 程序,依赖 Win32 API。解决办法是优先用跨平台工具(7-Zip 有 Linux 版,innounp也有对应构建),确实只能用 Windows 工具时,在隔离的 Windows 环境里操作,别在主力环境里硬装一堆兼容层。我一般把这类操作放在独立虚拟机里做,解完只把产物拷出来。
6. 装完怎么验证:用三个样本跑通再收工
环境装没装好,不看命令能不能敲出来,看能不能稳定解出正确结果。我的验证习惯是准备三个不同类型的样本——一个自解压包、一个 NSIS 包、一个 Inno 包——依次跑一遍,每个都核对文件数和关键文件可识别性。三个都过,这套环境才算能用;有一个不过,就回到对应章节查工具版本或参数。
验证脚本可以固定下来,每次换机器或升级工具后重跑:
#!/usr/bin/env bash # 三样本验证:每个样本解压后核对文件数是否大于阈值 set -euo pipefail SEVENZ=/opt/exe-tools/7z/7zz check() { local dir="$1" min="$2" local n n=$(find "$dir" -type f | wc -l) if [ "$n" -lt "$min" ]; then echo "FAIL: $dir only $n files"; return 1 fi echo "OK: $dir $n files" } "$SEVENZ" x samples/sfx.exe -oout/v-sfx -y >/dev/null "$SEVENZ" x samples/nsis.exe -oout/v-nsis -y >/dev/null innounp -x -dout/v-inno samples/inno.exe >/dev/null check out/v-sfx 5 check out/v-nsis 10 check out/v-inno 10check函数接收目录和最小文件数阈值,低于阈值判失败。阈值不是拍脑袋定的,是拿已知正常的样本先跑一遍、记下实际文件数、再往下取一个安全值。>/dev/null屏蔽解压过程的冗长输出,只留验证结论。三个样本的阈值分别设 5、10、10,是因为自解压包通常文件少,NSIS 和 Inno 包带资源往往更多,具体数值按你手头样本调整。
除了数量,还要抽查内容。我一般对每个样本解出的主程序跑一次file,确认是PE32或PE32+,再挑一个资源文件确认类型匹配扩展名。数量对、类型对,基本可以判定解压链路完整。如果某个样本数量对但file结果异常,多半是解压时类型判断错了,回到第 3 章对应小节换方案。
这套验证流程我坚持了很多年,起因是有一次偷懒只测了自解压包就交付,结果同事拿 NSIS 包一跑就报错,回头查发现是工具版本太老、NSIS 支持不全。从那以后我每次换机器、升级工具、改脚本,都强制把三个样本跑一遍再收工,宁可多花十分钟,也不让问题流到下一环。希望这套流程帮到你,少走我当年那些回头路。
本文还有配套的精品资源,点击获取