C# 如何将代码附加到 运行 .NET .EXE 的末尾,最好是从该 .EXE 内部附加代码?

C# How do I append code to the end of a running .NET .EXE, preferably from inside that .EXE?

运行 .NET .EXE 可以将数据附加到自身吗?是什么阻止了它?

我可以启动一个单独的进程来完成它。

但我不知道如何在它 运行 时给自己写信。有没有办法做到这一点? 在 .NET 中

编辑:最好不要像把它写在其他地方那样的骇人听闻的解决方案 copy/rename

EDIT2:阐明可执行文件的类型

EDIT3:目的:将二进制流写入我的 运行 EXE 文件允许我然后 解析 .EXE 文件在磁盘上存储这些字节并在程序中使用它们。无需创建任何新文件或注册表项或类似的东西。它是独立的。这非常方便。

EDIT4:对于那些反对这个文件的人,请考虑以下功能:FILE ZIPPINGDLL LINKING便携式应用程序 在试图诋毁这个想法之前,

如评论中所述,以这种方式存储数据会带来很多不良后果,但还有一个更大的问题:“是什么阻止了它?”的答案。题。 Windows PE 加载器 锁定 图像文件以在执行时写入,因此您无法使用 HANDLE 获取文件写权限,因为带有 FILE_WRITE_DATA 选项的 NtCreateFileNtOpenFile 系统调用以及任何删除文件的尝试都会失败。此块在内核级别实现并在 NtCreateProcess 系统调用期间设置,在实际调用进程及其模块入口点之前。

在没有将数据写入磁盘、将数据发送到远程服务器且没有内核权限的情况下,唯一可能的肮脏伎俩是通过辅助可执行文件、代码注入或命令行参数脚本(例如使用 PowerShell)使用另一个进程这可以杀死你释放锁的进程,将数据附加到文件末尾并重新启动它。当然这些选项会带来更糟糕的后果,我写它只是为了弄清楚 OS 限制(有目的的)以及为什么没有专业软件使用这种技术来存储数据。

编辑:由于您下定决心要完成此行为,我 post 通过辅助可执行文件(文件复制)附加数据的概念证明,该方法依赖于在 TEMP 中执行图像的新副本文件夹,将路径传递给原始可执行文件,以便它可以被“写入”,因为它不是 运行 并且被锁定。 对于读者,我建议不要在生产中使用它

using System;
using System.IO;
using System.Reflection;
using System.Diagnostics;

namespace BadStorage
{
    class Program
    {
        static void Main(string[] args)
        {
            var temp = Path.GetTempPath();
            var exePath = Assembly.GetExecutingAssembly().Location;
            if (exePath.IndexOf(temp, StringComparison.OrdinalIgnoreCase) >= 0 && args.Length > 0)
            {
                // "Real" main
                var originalExe = args[0];
                if (File.Exists(originalExe))
                {
                    // Your program code...

                    byte[] data = { 0xFF, 0xEE, 0xDD, 0xCC };
                    // Write
                    using (var fs = new FileStream(originalExe, FileMode.Append, FileAccess.Write, FileShare.None))
                        fs.Write(data, 0, data.Length);

                    // Read
                    using (var fs = new FileStream(originalExe, FileMode.Open, FileAccess.Read, FileShare.Read))
                    {
                        fs.Seek(-data.Length, SeekOrigin.End);
                        fs.Read(data, 0, data.Length);
                    }
                }
            }
            else
            {
                // Self-copy
                var exeCopy = Path.Combine(temp, Path.GetFileName(exePath));
                File.Copy(exePath, exeCopy, true);
                var p = new Process()
                {
                    StartInfo = new ProcessStartInfo()
                    {
                        FileName = exeCopy,
                        Arguments = $"\"{exePath}\"",
                        UseShellExecute = false
                    }
                };
                p.Start();
            }
        }
    }
}

尽管存在所有负面因素,但有一种干净的方法可以做到这一点:

我找到的方法只需要程序在NTFS驱动器上执行。

诀窍是让您的应用程序在启动后立即将自身复制到备用流,然后执行该图像并立即自行关闭。这可以通过以下命令轻松完成:

type myapp.exe > myapp.exe:image
forfiles /m myapp.exe /c myapp.exe:image

一旦您的应用程序 运行 来自备用流 (myapp.exe:image),就可以自由修改原始文件 (myapp.exe) 并读取存储在其中的数据它。下次程序启动时,修改后的应用程序将被复制到备用流并执行。

这允许您在 运行 时获得可执行文件写入自身的效果,而无需处理任何额外的文件,并允许您将所有设置存储在一个 .exe 文件中。

该文件必须在 NTFS 分区上执行,但这没什么大不了的,因为所有 Windows 安装都使用这种格式。您仍然可以将文件复制到其他文件系统,只是无法在那里执行。