如何实现让dnSpy、ILSpy无法反编译C#代码?
实现.NET方法IL隐藏(让反编译工具失效)的技术方案
你遇到的这种情况,是典型的IL代码替换+原生代码预编译的代码保护手段,核心思路是让反编译工具看到无效的IL(大部分为nop),但CLR执行时用预先准备好的原生ASM代码运行。下面是具体的实现方式:
方式一:编译后修改IL+Native Image生成
这是最容易实现的静态修改方案:
- 先正常编译你的C#代码为DLL,确保目标方法能正常运行
- 用ILDasm导出DLL的IL代码:执行命令
ildasm target.dll /out:target.il - 打开导出的IL文件,找到目标方法,把除第一条IL指令外的所有代码替换成
nop。比如原方法IL是:
修改后变成:.method public hidebysig instance void TestMethod() cil managed { ldarg.0 call instance void [mscorlib]System.Console::WriteLine() ret }.method public hidebysig instance void TestMethod() cil managed { ldarg.0 nop nop ret } - 用ILAsm重新编译修改后的IL为DLL:
ilasm target.il /dll /output:modified.dll - 用Ngen工具为修改后的DLL生成原生镜像:
ngen install modified.dll。此时CLR会优先加载原生镜像执行,反编译工具看到的却是满是nop的无效IL,自然无法反编译出正确代码。
方式二:自定义JIT钩子动态替换IL
这种是动态运行时修改的方案,适合需要更灵活保护的场景:
- 利用CLR提供的
ICorProfilerCallback2接口实现JIT钩子,重写JITCompileStarted回调方法 - 在回调中,获取目标方法的IL字节流,把除首条指令外的所有字节替换为
0x00(nop对应的IL操作码) - 通过
SetILFunctionBody方法把修改后的IL设置回方法,或者直接通过钩子把CLR的JIT编译逻辑替换成你预先准备好的原生ASM代码入口 - 注册Profiler并启动程序,此时CLR加载方法时读取的是nop IL,但执行的是你提供的原生代码,反编译工具拿到的只是无效的IL内容
关键注意点
- 静态修改的方案依赖Ngen生成的原生镜像,一旦镜像被卸载(比如执行
ngen uninstall modified.dll),修改后的方法会执行nop逻辑直接失效 - 强签名的程序集修改IL后必须重新签名,否则CLR会拒绝加载
- 这种手段属于代码保护技术,使用时要遵守相关法律法规
内容的提问来源于stack exchange,提问作者ken
相关产品推荐
相关产品推荐

