如何在另一个进程的内存中写入数据?

10

我有一个地址需要修改,我已经拥有了处理过程和新的值,现在该怎么办?

// My Process
var p = Process.GetProcessesByName("ePSXe").FirstOrDefault();

// Address
var addr = 0x00A66E11;

// Value
var val = 0x63;

我如何将0x63(99)写入到另一个进程内存的这个地址?


1
不要使用 var addr... 它默认为 int。请改用 IntPtr - user541686
4个回答

14

从你的回答中,我找到了很多信息:

打开、关闭和写入的签名:

[DllImport("kernel32.dll")]
static extern IntPtr OpenProcess(ProcessAccessFlags dwDesiredAccess, [MarshalAs(UnmanagedType.Bool)] bool bInheritHandle, int dwProcessId);

[DllImport("kernel32.dll", SetLastError = true)]
static extern bool WriteProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, byte[] lpBuffer, uint nSize, out int lpNumberOfBytesWritten);

[DllImport("kernel32.dll")]
public static extern Int32 CloseHandle(IntPtr hProcess);

标志:

[Flags]
public enum ProcessAccessFlags : uint
{
    All = 0x001F0FFF,
    Terminate = 0x00000001,
    CreateThread = 0x00000002,
    VMOperation = 0x00000008,
    VMRead = 0x00000010,
    VMWrite = 0x00000020,
    DupHandle = 0x00000040,
    SetInformation = 0x00000200,
    QueryInformation = 0x00000400,
    Synchronize = 0x00100000
}

让我的生活更轻松的方法:

public static void WriteMem(Process p, int address, long v)
{
    var hProc = OpenProcess(ProcessAccessFlags.All, false, (int)p.Id);
    var val = new byte[] { (byte)v };

    int wtf = 0;
    WriteProcessMemory(hProc, new IntPtr(address), val, (UInt32)val.LongLength, out wtf);

    CloseHandle(hProc);
}

写入另一个进程的内存:

static void Main(string[] args)
{
    var p = Process.GetProcessesByName("ePSXe").FirstOrDefault();

    WriteMem(p, 0x00A66DB9, 99);
}

7
嗯......我可以提议您永远不要再使用“int”来表示内存地址吗?谢谢。 :) - user541686
我太懒了,不想打“IntPtr”,但我会记住的 :P - BrunoLM
2
你在WriteMem()中忘记了CloseHandle()。 - Harvey Kwok
2
你可能也想检查WriteProcessMemory()的返回值,正如TomTom所指出的那样,它确实需要特权才能执行。如果你没有足够的特权,你可能需要调用AdjustTokenPrivilege。 - Harvey Kwok

5
尽管 P/Invoke 本地函数,例如 WriteProcessMemory 可以完美地工作,但是存在专门用于内存编辑的库,使您可以更轻松地完成此任务。
使用库 MemorySharp,可以概括为:
using(var sharp = new MemorySharp(Process.GetProcessesByName("ePSXe").FirstOrDefault()))
{
   sharp[0x00A66E11, false].Write(0x63);
}

之前的代码假设写入值的地址没有被重新定位。


4

请注意实际文档和所需的高权限要求。即使是管理员帐户也不足够。http://msdn.microsoft.com/en-us/library/ms681674(v=vs.85).aspx 是一个起点。 - TomTom
谢谢,从这个参考中我找到了很多有用的信息 :) - BrunoLM

0
你可以使用WriteProcessMemory,但请注意需要开启调试权限,并且在Vista及以后的系统中无法处理许多受保护的进程。
而且你可能会不小心越界导致程序崩溃几次。我建议在操作时不要运行任何重要的程序。
祝你好运,你会需要它的。 :)

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