通过c#编辑内存地址

时间:2013-04-30 20:49:21

标签: c# inline-assembly

我想编辑一个活跃的应用程序(编辑一个内存地址),

地址00498D45上的

我想编辑其值

当前价值:

MOV BYTE PTR SS:[EBP-423],7

更新值:

 MOV BYTE PTR SS:[EBP-423],8

我到现在所知道的是这个(在网上搜索一遍,这到底有多远):

提前感谢!

using System.Runtime.InteropServices;

    [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
}

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

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

[DllImport("kernel32.dll", SetLastError = true)]
static extern bool ReadProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, [Out] byte[] lpBuffer, int dwSize, out int lpNumberOfBytesRead);

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

Process process = Process.GetProcessesByName("My Apps Name").FirstOrDefault();

public static bool WriteMemory(Process process, int address, long value, out int bytesWritten)
{
    IntPtr hProc = OpenProcess(ProcessAccessFlags.All, false, process.Id);

    byte[] val = BitConverter.GetBytes(value);

    bool worked = WriteProcessMemory(hProc, new IntPtr(address), val, (UInt32) val.LongLength, out bytesWritten);

    CloseHandle(hProc);

    return worked;
}

2 个答案:

答案 0 :(得分:2)

来自other question

WriteMemory(Process process,00498D45 , MOV BYTE PTR SS:[EBP-423],8)

这有很多问题,我不知道从哪里开始。首先,这不是正确的C#语法。

  1. 你正在调用一个函数,但是Process就像是签名一样。
  2. 00498D45在任何基础中都不是有效常量。如果你的意思是十六进制,(你可能在处理地址时可能会这样做),那么就像所有其他类C语言一样,应该表示为0x00498D45
  3. 这是ASCII中的x86汇编代码(但它不是字符串,你只是乱七八糟)。您不能只将ASCII汇编代码放入另一个进程的地址空间!
  4. 也许你应该多做一些关于编译和汇编在构建程序时如何工作的研究,以及CPU在执行程序时实际执行的操作的内容。另外,我建议您仔细阅读示例代码,这些代码很明显是从某个地方获取的,并尝试理解它。你会更好地了解正在发生的事情,而不是要求每个人帮助解决你拼凑在一起的东西。 </rant>

    无论如何,在汇编代码之后,它看起来像这样(重新组装):

    C68559FEFFFF08    mov byte [ebp-0x1a7],0x8
    

    这意味着您的指令实际上是字节串C6 85 59 FE FF FF 08。这就是您需要写入目标应用程序的内容。

    这是你要做的事情的基础:

    byte[] new_instr = new byte[] {0xC6, 0x85, 0x59, 0xFE, 0xFF, 0xFF, 0x08};
    IntPtr target_addr = (IntPtr)0x00498D45;
    
    int bytesWritten;
    WriteProcessMemory(hProcess, target_addr, new_instr, (UInt32)new_instr.Length, out bytesWritten);
    

    您复制并粘贴WriteMemory记忆功能不会帮助您。问题是,它只写了一个4 {1}的long。你需要写7个字节。因此,您必须修改该函数才能使用byte[]参数,或者自己动手。


    我很佩服你的抱负,但你应该真的开始降低一点。编写一些C#代码,让自己熟悉用C语言编程。然后写一些C来熟悉你不完美做事时的崩溃。然后尝试涉及汇编 - 也许在您的C代码中编写小的内联部分。最后,您将准备好了解其他正在运行的进程的指令。

答案 1 :(得分:1)

您可以使用像MemorySharp这样的注入库(我是作者)。所有这些函数都包含在一个方便的API中,集成了汇编程序(FASM语法)。因此,这段代码可以执行您想要的任务:

using (var m = new MemorySharp(ApplicationFinder.FromProcessName("My App").First()))
{
    m.Assembly.Inject("MOV BYTE [EBP-423],8", new IntPtr(0x00498D45));
}