博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
C# Read/Write another Process' Memory z
阅读量:2236 次
发布时间:2019-05-09

本文共 5577 字,大约阅读时间需要 18 分钟。

http://www.codeproject.com/Articles/670373/Csharp-Read-Write-another-Process-Memory

 

This article aims to show you how to read/write a process' memory using C# and some methods found in kernel32.dll. This is a good way to learn a part of WinAPI and also understand the basics of memory allocation.

Before starting, we need a "target" - I choose notepad.exe but every native application is good for this.

1.Finding the Memory Address 

As you might probably know, applications store each variable's value at a specific memory address, we need to know that memory adress in order to edit anything. Since there's not other way around (or I'm not aware of it?) the only solution is to start searching, using a debugger.

To get that memory address, I used OllyDbg - don't worry, all the steps are written below.

First, open notepad.exe, type some text (like "hello world") and attach OllyDbg (File->Attach). Press F9 and then ALT+M to open the Memory Map.

It should look like this:

Memory Map

Press CTRL+B and it will open the Binary Search Window. Now, because the value is stored in memory as Unicode, you have to type the string you're looking for in the 2nd textbox:

Binary Search

Once you hit Ok another window will pop up - the Memory Dump. Here, look at the very first memory address (on the left) - from that address we'll start reading. In the image below, the highlighted part contains the message I typed in Notepad.

Note: don't use the memory address from the image - it's not the same memory address every time.

Memory Dump

We got the memory address, now...don't close/restart the application. If you restart it, the memory for the text will be reallocated, so the address will most likely be changed.

2.Read Process' Memory 

In order to read the value from that memory address, we need to import 2 functions into C#: OpenProcess() and ReadProcessMemory() from kernel32.dll.

[DllImport("kernel32.dll")]public static extern IntPtr OpenProcess(int dwDesiredAccess, bool bInheritHandle, int dwProcessId);[DllImport("kernel32.dll")]public static extern bool ReadProcessMemory(int hProcess,   int lpBaseAddress, byte[] lpBuffer, int dwSize, ref int lpNumberOfBytesRead);

When a process is opened, you must also specify the desired access (this time, you request access for reading the memory), so this constant is needed:

const int PROCESS_WM_READ = 0x0010;

Since the whole code is self explanatory, I'll just add short comments where they're needed:

using System;using System.Diagnostics;using System.Runtime.InteropServices;using System.Text;public class MemoryRead{    const int PROCESS_WM_READ = 0x0010;    [DllImport("kernel32.dll")]    public static extern IntPtr OpenProcess(int dwDesiredAccess, bool bInheritHandle, int dwProcessId);    [DllImport("kernel32.dll")]    public static extern bool ReadProcessMemory(int hProcess,       int lpBaseAddress, byte[] lpBuffer, int dwSize, ref int lpNumberOfBytesRead);    public static void Main()    {        Process process = Process.GetProcessesByName("notepad")[0];         IntPtr processHandle = OpenProcess(PROCESS_WM_READ, false, process.Id);         int bytesRead = 0;        byte[] buffer = new byte[24]; //'Hello World!' takes 12*2 bytes because of Unicode         // 0x0046A3B8 is the address where I found the string, replace it with what you found        ReadProcessMemory((int)processHandle, 0x0046A3B8, buffer, buffer.Length, ref bytesRead);        Console.WriteLine(Encoding.Unicode.GetString(buffer) +            " (" + bytesRead.ToString() + "bytes)");        Console.ReadLine();    }}

3.Write Process' Memory 

Writing to a memory address is a little bit different: you'll need OpenProcess() and WriteProcessMemory().

[DllImport("kernel32.dll")]public static extern IntPtr OpenProcess(int dwDesiredAccess, bool bInheritHandle, int dwProcessId);[DllImport("kernel32.dll", SetLastError = true)]static extern bool WriteProcessMemory(int hProcess, int lpBaseAddress,   byte[] lpBuffer, int dwSize, ref int lpNumberOfBytesWritten);

However, special permissions are required: while opening the process request the following access: PROCESS_VM_WRITE | PROCESS_VM_OPERATION.

const int PROCESS_VM_WRITE = 0x0020;const int PROCESS_VM_OPERATION = 0x0008;

Note: notepad's textbox is storing the number of bytes it has to read from the memory - that value is updated only when the text is changed by user. If you write to the memory address a longer string, it will be truncated.

The complete code is available below:

using System;using System.Diagnostics;using System.Runtime.InteropServices;using System.Text;public class MemoryRead{    const int PROCESS_VM_WRITE = 0x0020;    const int PROCESS_VM_OPERATION = 0x0008;    [DllImport("kernel32.dll")]    public static extern IntPtr OpenProcess(int dwDesiredAccess,            bool bInheritHandle, int dwProcessId);    [DllImport("kernel32.dll", SetLastError = true)]    static extern bool WriteProcessMemory(int hProcess, int lpBaseAddress,       byte[] lpBuffer, int dwSize, ref int lpNumberOfBytesWritten);    public static void Main()    {        Process process = Process.GetProcessesByName("notepad")[0];        IntPtr processHandle = OpenProcess(0x1F0FFF, false, process.Id);         int bytesWritten = 0;        byte[] buffer = Encoding.Unicode.GetBytes("It works!\0");        // '\0' marks the end of string        // replace 0x0046A3B8 with your address        WriteProcessMemory((int)processHandle, 0x0046A3B8, buffer, buffer.Length, ref bytesWritten);        Console.ReadLine();    }}

转载于:https://www.cnblogs.com/zeroone/p/3766240.html

你可能感兴趣的文章
Java网络编程与NIO详解10:深度解读Tomcat中的NIO模型
查看>>
Java网络编程与NIO详解11:Tomcat中的Connector源码分析(NIO)
查看>>
深入理解JVM虚拟机1:JVM内存的结构与消失的永久代
查看>>
深入理解JVM虚拟机3:垃圾回收器详解
查看>>
深入理解JVM虚拟机4:Java class介绍与解析实践
查看>>
深入理解JVM虚拟机5:虚拟机字节码执行引擎
查看>>
深入理解JVM虚拟机6:深入理解JVM类加载机制
查看>>
深入了解JVM虚拟机8:Java的编译期优化与运行期优化
查看>>
深入理解JVM虚拟机9:JVM监控工具与诊断实践
查看>>
深入理解JVM虚拟机10:JVM常用参数以及调优实践
查看>>
深入理解JVM虚拟机12:JVM性能管理神器VisualVM介绍与实战
查看>>
深入理解JVM虚拟机13:再谈四种引用及GC实践
查看>>
Spring源码剖析1:Spring概述
查看>>
Spring源码剖析2:初探Spring IOC核心流程
查看>>
Spring源码剖析5:JDK和cglib动态代理原理详解
查看>>
Spring源码剖析6:Spring AOP概述
查看>>
【LeetCode】无重复字符的最长子串
查看>>
【C++】动态内存管理 new和delete的理解
查看>>
【Linux】进程的理解(二)
查看>>
【C++】STL -- Vector容器的用法
查看>>