如何在.NET程序运行时从内部向自身EXE追加数据,无需hack方案?
运行中的.NET EXE自身追加数据问题解答
核心限制机制
Windows操作系统对处于运行状态的PE文件(包括.NET EXE)默认持有独占读执行锁,这是内核层面的强制锁,任何进程(包括EXE自身)都无法获得该文件的写入/追加权限,这就是无法直接修改运行中自身EXE的根本原因,该限制与.NET框架无关。
.NET框架下的可行实现方案
不需要依赖文件复制/重命名等操作,可通过内存加载程序集的方式释放文件锁,实现运行时自身写入:
- 实现逻辑:程序首次启动时,先将自身EXE的全部字节读入内存,通过
Assembly.Load(byte[])方法加载内存中的程序集,此时磁盘上的原EXE文件的占用锁会被自动释放,后续即可直接对原EXE文件进行追加写入操作。 - 示例代码:
using System.Reflection; using System.Text; static void Main(string[] args) { // 避免重复加载的标记判断 if (args.Contains("--inmem")) { // 此处可正常对自身EXE执行写入操作 string selfPath = Assembly.GetExecutingAssembly().Location; byte[] customData = Encoding.UTF8.GetBytes("你的自定义二进制数据"); using (var fs = new FileStream(selfPath, FileMode.Append, FileAccess.Write)) { // 写入固定魔数+长度标记,方便后续读取解析 fs.Write(BitConverter.GetBytes(0xABCD1234), 0, 4); fs.Write(BitConverter.GetBytes(customData.Length), 0, 4); fs.Write(customData, 0, customData.Length); } // 你的正常业务逻辑 return; } // 首次启动的内存加载逻辑 string exePath = Assembly.GetExecutingAssembly().Location; byte[] exeBytes = File.ReadAllBytes(exePath); Assembly memAssembly = Assembly.Load(exeBytes); MethodInfo entryPoint = memAssembly.EntryPoint; // 传入标记参数,避免进入无限加载循环 entryPoint.Invoke(null, new object[] { args.Concat(new[] { "--inmem" }).ToArray() }); }
追加数据读取逻辑
后续程序启动时,可直接读取自身EXE末尾的自定义数据,无需依赖外部文件:
string selfPath = Assembly.GetExecutingAssembly().Location; byte[] exeAllBytes = File.ReadAllBytes(selfPath); // 从末尾倒查魔数定位自定义数据 int magic = BitConverter.ToInt32(exeAllBytes, exeAllBytes.Length - 8); if (magic == 0xABCD1234) { int dataLen = BitConverter.ToInt32(exeAllBytes, exeAllBytes.Length - 4); byte[] customData = exeAllBytes.Skip(exeAllBytes.Length - 8 - dataLen).Take(dataLen).ToArray(); // 解析使用自定义数据 }
该方案完全符合自包含要求,无需创建额外文件、修改注册表,额外追加的数据不会影响EXE的正常运行,PE加载器只会读取PE结构定义范围内的内容,末尾附加数据会被自动忽略。
内容的提问来源于stack exchange,提问作者8vtwo
相关产品推荐
相关产品推荐

