C#如何从进程中检索代码并运行它?

4

由于进程是计算机程序的实例,包含程序代码和它当前的活动状态,因此我尝试了以下操作:

  • 解析我的进程并检索一个字节数组。
  • 执行这些字节。

我的问题是,我检索到了程序代码和它当前的活动状态,而我只对第一部分感兴趣。

以下是如何检索进程“foo”的字节:

 public static byte[] retrieveProcessBytes(String processName) {
        Process process = ApplicationFinder.FromProcessName(processName).First();
        var sharp = new MemorySharp(process);

        List<byte> bytes = new List<byte>();
        IntPtr ptr = IntPtr.Zero;
        try
        {
            while (true) {
                bytes.Add(sharp.Read<byte>(ptr, 1)[0]);
                ptr = IntPtr.Add(ptr, 1);
            }
        }
        catch (Exception e) {
            Console.Write("Exception caught : " + e);
        }
        return bytes.ToArray();
    }

以下是我试图执行它的方法:

byte[] bytes = retrieveProcessBytes("foo");
Assembly asm = Assembly.Load(bytes);
Object[] Args = new Object[0];
asm.EntryPoint.Invoke(null, Args);

执行时出现以下错误:

'mscorlib.dll' 中发生了类型为 'System.BadImageFormatException' 的未经处理的异常

与此同时,如果我从我的“foo.exe”程序中检索字节并执行它们,则可以正常工作,如下所示。

Byte[] bytes = File.ReadAllBytes(pathToFooExe);
Assembly asm = Assembly.Load(bytes);

我从进程中检索到的字节数组比我从“foo.exe”文件中检索到的字节数组要大得多。因为我认为我还检索了当前进程的活动。

如何仅检索我的进程的代码部分?

它是否从IntPtr.Zero开始,还是稍后?什么时候停止?

非常感谢您的帮助!


2
这只是一种非常简化的视角。但是您不能像那样从正在运行的进程中提取程序。首先,内存不是一个线性块,其次,在进程的内存中还加载了其他加载的模块(程序集/DLL等),第三,EXE文件没有1:1加载到内存中。了解有关EXE文件格式以及如何将其加载到内存中的更多详细信息,请查看此处。 - CherryDT
1
你这个操作的目标是什么?也许有更好的解决方案来实现你想要的。 - CherryDT
1
我想比较一下我的进程中的代码是否与exe文件中的代码相同。如果程序在运行时有所不同,例如带有DRM或保护的程序,那么这种情况是否很常见? - Guerin Guillaume
1
在你自己的进程中还是在另一个进程中?无论哪种情况,你都可以具体检查代码部分和/或数据部分,并将它们与EXE文件中的相应部分进行比较(请再次参见我上面发布的文件格式链接)。但要注意,可能会有第三方软件(如杀毒软件)在运行时修补你的代码(例如COMODO就这样做了,我过去曾因此遇到问题)。 - CherryDT
1个回答

0
如果您阅读有关函数Assembly.Load的资料,您会发现您正在错误使用它。仅因为它允许以字节数组作为输入,并不意味着您正在提供适当的字节数组。

Assembly.Load(Byte[])

加载包含已发出程序集的基于通用对象文件格式(COFF)的映像的程序集。该程序集被加载到调用方的应用程序域中。

COFF 文件格式

很明显,这不是你正在做的事情。基本上,你所做的是无法完成的。CherryDT 在他的评论中已经给出了充分的理由。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接