shooan 发表于 2020-8-5 11:22

C#简单的跨线程内存读写库

实现x86 环境下的C#跨线程内存读写
最低依赖 .net framework 2.0

使用方法和简单功能: 创建MemoryHelper的实例,然后可以读写某个内存,并且可以通过基址和偏移计算地址


```charp
using System;
using System.Diagnostics;
using System.Runtime.InteropServices;

namespace Shooan.Tools
{

    #region 内存操作相关的权限 枚举
   
    enum ProcessAccessFlags : uint
    {
      All = 0x001F0FFF,
      Terminate = 0x00000001,
      CreateThread = 0x00000002,
      VirtualMemoryOperation = 0x00000008,
      VirtualMemoryRead = 0x00000010,
      VirtualMemoryWrite = 0x00000020,
      DuplicateHandle = 0x00000040,
      CreateProcess = 0x000000080,
      SetQuota = 0x00000100,
      SetInformation = 0x00000200,
      QueryInformation = 0x00000400,
      QueryLimitedInformation = 0x00001000,
      Synchronize = 0x00100000
    }
    #endregion


    public class MemoryHelper
    {
      #region 内存操纵相关的库和方法
      
      static extern IntPtr OpenProcess(int dwDesiredAccess, bool bInheritHandle, int dwProcessId);

      
      static extern bool WriteProcessMemory(int hProcess, int lpBaseAddress,
          byte[] lpBuffer, int dwSize, ref int lpNumberOfBytesWritten);

      
      static extern bool ReadProcessMemory(int hProcess,
         int lpBaseAddress, byte[] lpBuffer, int dwSize, ref int lpNumberOfBytesRead);


      public void Write(int location, byte[] buffer)
      {
            if (IsProcessExitedOrNoExist)
            {
                throw new InvalidOperationException("尝试向已经关闭了的或者不存在的线程写入数据");
            }

            IntPtr processWriteHandle = OpenProcess((int)ProcessAccessFlags.All, false, _process.Id);
            int bytesWritten = 0;
            WriteProcessMemory((int)processWriteHandle, location, buffer, buffer.Length, ref bytesWritten);
      }

      public byte[] Read(int location, int size)
      {
            if (IsProcessExitedOrNoExist)
            {
                throw new InvalidOperationException("尝试从已经关闭了的或者不存在的线程读取数据");
            }

            IntPtr processReadHandle = OpenProcess((int)ProcessAccessFlags.VirtualMemoryRead, false, _process.Id);
            int bytesRead = 0;
            byte[] buffer = new byte;
            ReadProcessMemory((int)processReadHandle, location, buffer, size, ref bytesRead);
            return buffer;
      }


      /// <summary>
      /// 传入基址和偏移,计算出最终的内存地址
      /// </summary>
      /// <returns>地址</returns>
      public int GetLocation(int basePtr, params int[] offsets)
      {

            // x86 环境,一个指针大小为4个字节
            const int size = 4;

            byte[] buffer;
            buffer = Read(basePtr, size);
            int temp = BitConverter.ToInt32(buffer, 0);

            for (int i = 0; i < offsets.Length-1; i++)
            {
                buffer = Read(temp + offsets, size);
                temp = BitConverter.ToInt32(buffer, 0);
            }
            int finalLocation = temp + offsets;

            return finalLocation;
      }
      #endregion


      public MemoryHelper(string processName)
      {
            _processName = processName;
            _process = null;
            SetUpTimer();
      }

      // 用来检测线程是否退出或者不合法
      public bool IsProcessExitedOrNoExist { get { return _process == null || _process.HasExited; } }


      #region 内部
      private string _processName;
      private Process _process;

      private Process GetProcess()
      {
            Process process = null;
            try
            {
                process = Process.GetProcessesByName(_processName);
            }
            catch (IndexOutOfRangeException) { }

            return process;
      }

      private void SetUpTimer()
      {
            System.Timers.Timer timer = new System.Timers.Timer();
            timer.Elapsed += MonitorProcess;
            timer.Interval = 300;
            timer.Start();
      }


      private readonly object lockObj = new object();

      private void MonitorProcess(object sender, System.Timers.ElapsedEventArgs e)
      {
            lock (lockObj)
            {
                // 检测进程是否退出,如果退出的话触发ProcessExited 事件
                if (_process != null && _process.HasExited)
                {
                  ProcessExited?.Invoke(this, new EventArgs());
                  _process = null;
                }

                Process process = GetProcess();
                if (process == null)
                {
                  return;
                }

                // 如果 "之前的" Process已经关闭了或者不存在,
                // 并且当前获得的线程是可用的
                if (IsProcessExitedOrNoExist)
                {
                  EventArgs eventArgs = new EventArgs();
                  // 触发进程启动事件
                  ProcessStarted?.Invoke(this, eventArgs);

                  // 更新对象
                  _process = process;
                }
            }
      }
      #endregion

      #region 事件
      public event EventHandler ProcessStarted;
      public event EventHandler ProcessExited;
      #endregion

    }
}

```

火龙果之 发表于 2020-8-5 15:37

马一下,内存辅助走起~~~:lol:lol

偶尔平凡 发表于 2020-8-5 12:08

Hsm162636 发表于 2020-8-5 12:34

内存读写库还不错,刚刚自己试了一下,给力哈

新手而已 发表于 2020-8-5 12:32

学废了学废了(doge);www

shooan 发表于 2020-8-5 12:49

Hsm162636 发表于 2020-8-5 12:34
内存读写库还不错,刚刚自己试了一下,给力哈

谢谢支持

flypds 发表于 2020-8-5 12:50

内存读写库还不错,刚刚自己试了一下,给力哈

terry8288 发表于 2020-8-5 13:26

受教了,学习下

lin326326 发表于 2020-8-5 13:43

是不是就可以写外挂了:Dweeqw

shooan 发表于 2020-8-5 14:05

lin326326 发表于 2020-8-5 13:43
是不是就可以写外挂了

可以实现内存挂

imcuer 发表于 2020-8-5 14:25

谢谢分享!
页: [1] 2
查看完整版本: C#简单的跨线程内存读写库