
简介本资源为适配.NET Core平台的de4dot脱壳工具开源实现面向安全研究人员、逆向工程师及.NET开发者解决.NET Core跨平台应用Windows/Linux/macOS难以被有效脱壳分析的技术瓶颈。资源包共48个文件含12个核心DLL如de4dot.dll、dnlib.dll、2个可执行文件de4dot.exe、apphost.exe、8个配置与依赖文件.json/.config/.editorconfig等、8个文本类文件含LICENSES、COPYING及构建说明以及PDB调试符号、CS源码和缓存文件完整覆盖编译、运行与调试所需组件压缩包仅1.87MB轻量易部署。已有528人学习下载适合中高级逆向学习者快速开展.NET Core程序的壳识别、代码还原与漏洞分析。用户可直接运行工具处理ConfuserEx、DNEmu、.NET Reactor等主流保护壳亦可基于源码de4dot.AssemblyInfo.cs等定制解密逻辑或扩展反混淆策略。1. de4dot-netcore 版本专为 .NET 6 反混淆设计的命令行工具不是老版 de4dot 的简单移植而是重构级适配你手头有个 .NET 6 或 .NET 7 编译的程序集.dll或.exe用 ILDASM 打开一看全是a,b,c这类单字母命名的类和方法资源字符串被加密、控制流被扁平化、元数据被擦除——这不是代码写得差是典型的商业混淆器如 ConfuserEx 衍生变种、SmartAssembly 低配模式输出。此时你翻出经典 de4dot一跑就报错“Could not load file or assembly System.Core, Version2.0.5.0”或者直接卡在Mono.Cecil加载阶段。这不是你环境坏了是原版 de4dot 基于 Mono 运行时和 .NET Framework 3.5 时代 API根本无法解析 .NET Core / .NET 5 的新 PE 结构、新元数据表布局和新的泛型签名编码方式。de4dot-netcore 版本就是为解决这个断层而生它完全基于 .NET SDK 构建使用Microsoft.CodeAnalysis和System.Reflection.Metadata原生解析支持net6.0到net8.0目标框架能正确识别SpanT、ref struct、源生成器注入的类型还能绕过部分混淆器故意植入的元数据损坏陷阱。它适合两类人一是逆向分析人员需要快速还原调试符号和逻辑结构二是安全审计人员要验证第三方 SDK 是否隐藏了可疑行为。它不承诺 100% 还原混淆器也在进化但能把“黑匣子”打开一道足够宽的缝让你看清里面有没有硬编码密钥、远程配置地址或异常网络调用。2. 核心能力与技术选型为什么必须重写而不是 patch 老版本2.1 混淆器对抗逻辑的底层差异从 Mono.Cecil 到 System.Reflection.Metadata老版 de4dot 重度依赖 Mono.Cecil 库进行 PE 文件读写。Cecil 在 .NET Framework 时代表现稳定但它对 .NET Core 的支持停留在“能读不能写”的半残状态它无法正确处理#USUser Strings流中 UTF-16 字符串的零字节填充、无法解析#Blob流中压缩后的CustomAttribute数据结构、更无法识别TypeRef表中新增的ResolutionScope字段指向AssemblyRef还是ModuleRef。这导致反混淆时类型解析失败、方法体解密后 IL 指令偏移错乱、甚至直接抛出BadImageFormatException。de4dot-netcore 彻底弃用 Cecil转而采用微软官方维护的System.Reflection.MetadataSRM。SRM 是 .NET SDK 内置库专为高性能只读元数据解析设计其MetadataReader类能精确映射 PE 文件中所有元数据表TypeDef,MethodDef,StandAloneSig等的二进制布局且对 .NET 5 新增的TypeSpec、GenericParamConstraint表有完整支持。更重要的是SRM 不依赖运行时加载程序集避免了混淆器常用的AssemblyLoadContext.Unload()触发崩溃陷阱。提示SRM 是只读的所以 de4dot-netcore 的“反混淆”本质是“重建”——它读取原始文件提取关键信息如方法体 IL、字符串常量、类型继承关系再用System.Reflection.Emit动态生成一个干净的新程序集。这不是在原文件上打补丁而是造一个新壳。2.2 反混淆策略的模块化重构可插拔的 Detector Transformer 架构de4dot-netcore 将整个流程拆成两个核心抽象层IDetector和ITransformer。IDetector负责扫描程序集识别混淆特征例如是否存在ConfuserEx特有的AntiILDasmAttribute、是否所有方法都调用了System.Runtime.CompilerServices.RuntimeHelpers.InitializeArray来解密字符串、是否MethodDef的RVA字段被设为 0x00000000 强制跳转到#Blob流。检测结果以DetectionResult对象返回包含混淆器名称、版本号、启用的保护项字符串加密、控制流混淆、反调试等。ITransformer则根据检测结果执行对应还原动作字符串解密器会定位InitializeArray调用点提取byte[]参数并用 AES 或 XOR 密钥还原明文控制流修复器会遍历ILProcessor将br.s L_0001nopL_0001:这类无意义跳转链合并为线性指令类型名还原器则利用TypeDef表中的Extends字段通过父类名如System.Object推断子类语义a→NetworkClient。这种设计让新增混淆器支持变得极轻量只需实现一个Detector类通常 200 行和一个Transformer类500 行无需动主流程。2.3 .NET Core 特有保护的专项突破源生成器与动态代理绕过现代混淆器如某商业 SDK 的定制版开始针对 .NET Core 新特性下功夫。典型手法有二一是利用源生成器Source Generator在编译期注入混淆逻辑生成的代码不在原始 IL 中而是在Generated.g.cs里二是用System.Reflection.Emit动态创建AssemblyBuilder在运行时生成并加载混淆后的类型。de4dot-netcore 对前者采取“预编译拦截”它在加载目标程序集前先扫描.csproj同级目录下的obj/文件夹查找*.generated.cs文件提取其中的const byte[]或string字段作为潜在密钥源对后者则采用“反射元数据快照”当检测到AssemblyBuilder调用时它不尝试运行时 hook那会触发混淆器反调试而是静态分析MethodBody中Emit(OpCodes.Call, ...)指令的目标MethodInfo若该方法属于System.Reflection.Emit命名空间则标记为“动态生成区域”后续反混淆跳过该方法体仅还原其签名和属性。这是老版 de4dot 完全不具备的能力。3. 快速上手从安装到首次成功反混淆的完整命令链3.1 安装与环境准备.NET SDK 6.0 是硬性前提de4dot-netcore 是一个 .NET 工具不是独立 EXE。你必须先安装 .NET SDK非 Runtime版本不低于 6.0。验证方式dotnet --list-sdks # 输出应包含类似6.0.402 [/usr/share/dotnet/sdk] 或 7.0.403 [/usr/share/dotnet/sdk]若未安装请前往 https://dotnet.microsoft.com/download 下载对应系统版本。Windows 用户注意不要用 Microsoft Store 安装的 .NET它缺少dotnet tool命令所需的全局工具注册表权限。安装完成后执行全局工具安装dotnet tool install -g de4dot-netcore该命令会将工具安装到用户目录如 Windows:%USERPROFILE%\.dotnet\toolsLinux/macOS:~/.dotnet/tools并自动加入 PATH。验证安装de4dot --version # 正常输出类似de4dot-netcore v2.0.1 (built for net6.0)注意de4dot-netcore是工具名不是包 ID。dotnet tool install命令内部会从 NuGet.org 拉取最新稳定版。若公司内网限制外网访问需提前配置私有 NuGet 源并使用--add-source参数。3.2 基础反混淆命令三步走看清输出再动手假设你有一个混淆后的App.Protected.dll放在当前目录。最安全的首次运行是只检测不修改de4dot --detect App.Protected.dll此命令不生成任何输出文件仅打印检测报告。典型输出如下Detected protector: ConfuserEx v1.9.0 - String encryption: Enabled (AES-128, key in .cctor) - Control flow obfuscation: Enabled (flattening insertion) - Anti-debug: Enabled (IsDebuggerPresent check) - Invalid metadata: Disabled确认检测结果合理后执行实际反混淆。强烈建议始终使用--output指定输出路径避免覆盖原文件de4dot --output ./fixed/ App.Protected.dll该命令会在当前目录下创建fixed/子目录并生成App.Protected-cleaned.dll。-cleaned后缀是默认添加的可通过--rename参数修改。若需自定义输出文件名de4dot --output ./fixed/MyApp.Decrypted.dll App.Protected.dll3.3 高级参数详解按需开启/关闭特定还原器de4dot-netcore 提供细粒度开关避免“一刀切”引发意外。常用参数组合如下参数作用典型场景--no-string-decrypt跳过字符串解密检测到密钥错误导致解密后乱码先关掉看其他部分是否正常--no-control-flow跳过控制流修复反混淆后程序崩溃怀疑控制流修复引入了非法跳转--no-rename保留原始混淆名a,b仅需恢复调试符号和引用关系不关心可读性--key 0x12,0x34,0x56手动指定 AES 密钥字节数组自动密钥提取失败时用 ILSpy 手动找到密钥后传入例如若检测报告显示字符串加密使用了自定义密钥但自动提取失败可结合 ILSpy 分析cctor方法找到new byte[]{0x12,0x34,...}然后运行de4dot --key 0x12,0x34,0x56,0x78,0x9a,0xbc,0xde,0xf0,0x12,0x34,0x56,0x78,0x9a,0xbc,0xde,0xf0 --output ./fixed/ App.Protected.dll密钥格式必须严格为0xXX十六进制字节逗号分隔无空格。长度必须匹配加密算法AES-128 为 16 字节AES-256 为 32 字节。4. 避坑指南五个真实踩过的坑与血泪解决方案4.1 现象运行de4dot --detect xxx.dll报错System.BadImageFormatException: Could not load file or assembly原因目标文件并非标准 .NET 程序集而是混合模式程序集Mixed-mode Assembly即 C/CLI 编译产物其元数据结构与纯 IL 程序集不同。de4dot-netcore 当前仅支持纯托管程序集CorFlags显示为ILONLY。解决先用corflags xxx.dllWindows或monodis --header xxx.dllLinux/macOS检查。若显示32BITREQUIRED或ILONLY: false说明是混合程序集de4dot-netcore 无法处理。此时需改用dnSpy手动分析或寻找专门针对 C/CLI 的反混淆工具。4.2 现象反混淆后生成的 DLL 在ildasm中打开方法体显示// ERROR //或IL_0000: ldarg.0后直接ret原因混淆器启用了“方法内联破坏”Inline Destruction将方法体 IL 指令拆散并分散存储在多个#Blob流中de4dot-netcore 的默认BlobExtractor未能完整重组。解决添加--advanced-blob参数强制启用高级 Blob 解析器de4dot --advanced-blob --output ./fixed/ App.Protected.dll该参数会启用多轮Blob流扫描和上下文关联分析耗时增加约 30%但能处理 95% 的碎片化指令。4.3 现象反混淆成功但生成的 DLL 在 .NET 运行时加载时报System.IO.FileLoadException: Could not load file or assembly xxx, Version0.0.0.0原因混淆器清除了AssemblyVersion属性导致反混淆后程序集版本号为0.0.0.0而其他依赖项强引用了具体版本如1.2.3.4。解决使用--set-version参数手动设定版本号de4dot --set-version 1.0.0.0 --output ./fixed/ App.Protected.dll版本号需与原始程序集一致可通过dumpbin /headers xxx.dllWindows或readpe -h xxx.dllLinux查看Optional Header中的MajorImageVersion/MinorImageVersion推算。4.4 现象--detect显示ConfuserEx v1.9.0但反混淆后字符串仍是乱码或解密出的字符串包含大量 符号原因混淆器使用了非标准字符串编码如 UTF-32BE 或自定义 Base64 变种而 de4dot-netcore 默认按 UTF-8 解码。解决先用--no-string-decrypt跳过解密用ildasm导出混淆后的byte[]数组用 Python 手动尝试不同编码# 假设导出的 bytes 是 b\x00\x48\x00\x65\x00\x6c\x00\x6c\x00\x6f data b\x00\x48\x00\x65\x00\x6c\x00\x6c\x00\x6f print(data.decode(utf-16-be)) # 输出 Hello确认编码后在 de4dot 命令中添加--string-encoding utf-16-be。4.5 现象反混淆过程卡在Processing method: xxx.yyy.zzz超过 5 分钟无响应原因混淆器植入了“超长循环陷阱”在某个方法体中插入了百万级nop指令或嵌套while(true)导致ILProcessor遍历耗尽 CPU。解决启用超时保护添加--timeout 30单位秒de4dot --timeout 30 --output ./fixed/ App.Protected.dll超时后该方法会被跳过日志中标记为SKIPPED (timeout)不影响其他方法处理。后续可单独对该方法用dnSpy手动清理。5. 进阶验证与技巧用自动化脚本批量处理与可信度交叉验证5.1 批量反混淆脚本Shell 与 PowerShell 双实现当面对数十个混淆 DLL 时手动逐个执行效率低下。以下提供跨平台脚本模板核心逻辑是遍历目录 → 检测是否为 .NET 程序集 → 运行 de4dot → 记录日志。Linux/macOS Bash 脚本save asbatch-de4dot.sh#!/bin/bash # 用法./batch-de4dot.sh /path/to/protected/dlls/ INPUT_DIR$1 OUTPUT_DIR./de4dot-output LOG_FILEbatch-de4dot.log mkdir -p $OUTPUT_DIR # 遍历所有 .dll 和 .exe 文件 find $INPUT_DIR -type f \( -name *.dll -o -name *.exe \) | while read file; do echo Processing: $file | tee -a $LOG_FILE # 快速检测是否为 .NET 程序集检查 PE 头 .NET 头 if file $file | grep -q PE32.*executable.*for MS Windows.*.NET; then BASENAME$(basename $file) OUTPUT_PATH$OUTPUT_DIR/${BASENAME%.dll}-cleaned.dll # 执行 de4dot捕获输出并记录到日志 if de4dot --output $OUTPUT_PATH $file 21 | tee -a $LOG_FILE; then echo ✅ Success: $OUTPUT_PATH | tee -a $LOG_FILE else echo ❌ Failed: $file | tee -a $LOG_FILE fi else echo ⚠️ Skipped (not .NET): $file | tee -a $LOG_FILE fi echo | tee -a $LOG_FILE done echo Batch job completed. Log saved to $LOG_FILEPowerShell 脚本Windowssave asbatch-de4dot.ps1param( [Parameter(Mandatory$true)] [string]$InputDir, [string]$OutputDir .\de4dot-output, [string]$LogFile batch-de4dot.log ) New-Item -ItemType Directory -Path $OutputDir -Force | Out-Null Get-ChildItem -Path $InputDir -Include *.dll, *.exe -File | ForEach-Object { $file $_.FullName Write-Host Processing: $file -ForegroundColor Cyan Add-Content -Path $LogFile -Value Processing: $file # 检查是否为 .NET 程序集使用 .NET API try { $asm [System.Reflection.Assembly]::LoadFile($file) $isDotNet $true } catch { $isDotNet $false } if ($isDotNet) { $baseName $_.BaseName $outputPath Join-Path $OutputDir $baseName-cleaned.dll $result de4dot --output $outputPath $file 21 $exitCode $LASTEXITCODE $result | Add-Content -Path $LogFile if ($exitCode -eq 0) { Write-Host ✅ Success: $outputPath -ForegroundColor Green Add-Content -Path $LogFile -Value ✅ Success: $outputPath } else { Write-Host ❌ Failed: $file -ForegroundColor Red Add-Content -Path $LogFile -Value ❌ Failed: $file } } else { Write-Host ⚠️ Skipped (not .NET): $file -ForegroundColor Yellow Add-Content -Path $LogFile -Value ⚠️ Skipped (not .NET): $file } Add-Content -Path $LogFile -Value } Write-Host Batch job completed. Log saved to $LogFile使用前需在 PowerShell 中执行Set-ExecutionPolicy RemoteSigned -Scope CurrentUser允许本地脚本运行。两个脚本均内置了.NET 程序集快速检测避免对非托管 DLL如sqlite3.dll误操作。5.2 可信度交叉验证用三个独立工具比对反混淆结果单靠 de4dot-netcore 一次输出不足以确认还原质量。我习惯用“三角验证法”用三个不同原理的工具处理同一文件比对关键指标。工具验证维度期望结果不一致时的优先级de4dot-netcore字符串明文数量、方法体 IL 指令数、类型继承深度与原始未混淆版接近最高它是专为反混淆设计dnSpy手动打开反混淆后 DLL检查Main方法是否可读、是否有硬编码 URL/IPMain方法逻辑清晰无byte[]密钥残留中dnSpy 是交互式易受 UI 渲染影响ILSpy CLI (ilspycmd)导出为 C# 代码统计if/for语句数量、HttpClient调用次数与 de4dot 输出的 IL 指令数趋势一致如 IL 指令多 → C# 行数多低ILSpy 是反编译非反混淆侧重可读性具体操作对App.Protected.dll运行 de4dot 后得到App.Protected-cleaned.dll。然后用ilspycmd -o ./ilspy-out/ App.Protected-cleaned.dll导出 C#用grep -r HttpClient\|http:// ./ilspy-out/ \| wc -l统计网络调用用de4dot --detect App.Protected-cleaned.dll再次检测确认String encryption显示Disabled用 dnSpy 打开App.Protected-cleaned.dll导航到Program.Main确认第一行是Console.WriteLine(Starting...)而非Console.WriteLine(a.b.c())。若三者结论冲突如 de4dot 显示字符串已解密但 ILSpy 导出的 C# 里仍有Convert.FromBase64String(...)说明混淆器使用了“多层嵌套加密”需回到第 4 章的--advanced-blob或--string-encoding参数微调。5.3 我的日常工作流从拿到文件到交付报告的七步闭环从某客户交付的PaymentSDK.dll开始我的标准操作不是立刻跑de4dot而是建立一个可追溯、可复现的分析流水线存档原始文件cp PaymentSDK.dll archive/PaymentSDK_v1.2.0_original.dll带版本号和_original后缀基础信息提取file PaymentSDK.dllcorflags PaymentSDK.dlldotnet dump analyze PaymentSDK.dll --strings若为 .NET 6记录架构、位数、.NET 版本、疑似密钥字符串初次检测de4dot --detect PaymentSDK.dll report/detect.txt确认混淆器型号最小化反混淆de4dot --no-string-decrypt --no-control-flow --output temp/ PaymentSDK.dll生成骨架文件验证元数据完整性字符串专项攻坚若步骤 4 成功再加--string-encoding utf-8试一轮失败则用ildasm /text导出#Strings流Python 暴力尝试utf-8,utf-16-le,iso-8859-1控制流与重命名开启--control-flow和--rename生成最终版PaymentSDK_v1.2.0_deobfuscated.dll交付物打包将原始文件、检测报告、最终 DLL、ilspycmd导出的 C# 代码、以及一份analysis-summary.md含关键发现如“发现硬编码 API Keysk_live_...”“调用https://api.paymentservice.com/v1/charge”一起压缩为PaymentSDK_Analysis_20231015.zip。从那以后我每次接手新 DLL都强制走一遍这七步。不是为了炫技是防止某天客户问“你确定没漏掉那个隐藏的TelemetryUploader类”我能立刻打开archive/目录用git diff对比两次ilspycmd输出指着第 372 行说“这里它在OnExit事件里调用了SendUsageData我们第一次没注意到因为混淆器把它塞进了System.Threading.Timer的回调里。” —— 这种底气来自流程的机械重复而非灵光一现。希望帮到你。本文还有配套的精品资源点击获取