C#:在另一个进程的内存中搜索byte 数组

如何在另一个进程的内存中搜索byte []数组,然后在byte []数组所在的位置获取地址?

我想将一个字节数组写入另一个进程的内存(WriteProcessMemory())。该调用的一个参数是uint Address.Well我想通过在进程中搜索一个字节数组来获取地址。

例如,我搜索{0xEB,0x20,0x68,0x21,0x27,0x65,??,0x21,0x64,0xA1}

我们假设这个数组只放在我想写内存的进程的内存中的一个位置。

要获得该地址,我必须搜索该字节数组。

是否可以在C#中完成?

编辑: 这适用于本机应用程序,而不是.NET。 没有必要低估我的问题,有C ++的组件可以做到这一点,我只想在C#中做到这一点。

感谢您的理解!

是否可以在C#中完成?

是。 但很难。 从本机应用程序来看很困难,因为没有阻抗与进程的非托管视图和它们需要使用的内存映射不匹配。

注意事项:

  • 您需要获得许可才能打开流程以获取处理权限。
  • 虽然32位进程的虚拟内存空间大小为2到4 GB(取决于主机操作系统和/ 3GB交换机),但大部分地址范围都不会被分配,读取它会导致页面错误。 您确实需要找出分配的页面以及避免大量无效页面访问的内容。

建议:

  • 你真的需要这样做吗? 说真的,这很难。
  • 考虑使用本机应用程序,这将避免跨本机/托管围栏工作(这可能包括具有托管驱动程序应用程序的本机库)。
  • 你真的需要这样做吗?
  • 考虑在目标流程中进行工作。 这将需要一些聪明(记录)来注入一个线程,但应该更快。
  • 首先阅读Windows上的进程内存是如何工作的(从Windows Internals开始,并且(在最新版本中不记得它的名字)Jeffrey Richter关于Win32应用程序开发的书。
  • 你真的需要这样做吗? 必须有一些更简单的东西……你能自动调试器吗?

是否可以在C#中完成? 在c#(或任何其他语言)中可以使用Everithing,你只需要弄清楚如何;

硬编码在这里:

using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Diagnostics; using System.Runtime.InteropServices; namespace ConsoleApplication1 { class Program { [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 IntPtr OpenProcess(int dwDesiredAccess, bool bInheritHandle, int dwProcessId); [DllImport("kernel32.dll", SetLastError = true)] [return: MarshalAs(UnmanagedType.Bool)] static extern bool CloseHandle(IntPtr hObject); static void Main(string[] args) { Process[] procs = Process.GetProcessesByName("explorer"); if (procs.Length <= 0) //proces not found return; //can replace with exit nag(message)+exit; IntPtr p = OpenProcess(0x10 | 0x20, true, procs[0].Id); //0x10-read 0x20-write uint PTR = 0x0; //begin of memory byte[] bit2search1 = {0xEB ,0x20,0x68,0x21,0x27,0x65}; //your bit array until ?? int k = 1; //numer of missing array (??) byte[] bit2search2 = {0x21,0x64,0xA1};//your bit array after ?? byte[] buff = new byte[bit2search1.Length+1+bit2search2.Length]; //your array lenght; int bytesReaded; bool finded = false; while (PTR != 0xFF000000) //end of memory // u can specify to read less if u know he does not fill it all { ReadProcessMemory(p, (IntPtr)PTR, buff, buff.Length, out bytesReaded); if (SpecialByteCompare(buff, bit2search1,bit2search2,k)) { //do your stuff finded = true; break; } PTR += 0x1; } if (!finded) Console.WriteLine("sry no byte array found"); } private static bool SpecialByteCompare(byte[] b1, byte[] b2, byte[] b3, int k) //readed memory, first byte array, second byte array, number of missing byte's { if (b1.Length != (b2.Length + k + b3.Length)) return false; for (int i = 0; i < b2.Length; i++) { if (b1[i] != b2[i]) return false; } for (int i = 0; i < b3.Length; i++) { if (b1[b2.Length + k + i] != b3[i]) return false; } return true; } } 

}

我想你可以使用ReadProcessMemory Windows API调用。 甚至还有一个预制的P / Invoke签名 ,所以你不必费心手工制作它。 您翻阅整个过程的内存,在其中搜索您的模式,然后您就完成了。

您将要使用这些API:

  [DllImport("Kernel32.Dll")] public static extern uint VirtualQueryEx(IntPtr ProcessHandle, uint Address, ref MEMORY_BASIC_INFORMATION MemInfo, int MemInfoLength); [DllImport("Kernel32.Dll")] public static extern bool ReadProcessMemory(IntPtr ProcessHandle, uint Address, byte[] Buffer, uint Size, ref uint BytesRead); [DllImport("Kernel32.Dll")] public static extern bool WriteProcessMemory(IntPtr ProcessHandle, uint Address, byte[] Buffer, uint Size, ref uint BytesRead); 

pinvoke.net是Windows API调用的绝佳资源。 我为GTA编写了一个培训师:如果要查看sourceforge上的代码 ,可以使用这些调用的Vice City。 代码并不漂亮,很久以前我只是把它放在一起,但是有一些辅助类用于枚举进程的内存区域并搜索某些字节或字符串。

这可能有助于您找到正确的方法:

 private static int GetMemoryAddressOfString(byte[] searchedBytes, Process p) { //List addrList = new List(); int addr = 0; int speed = 1024*64; for (int j = 0x400000; j < 0x7FFFFFFF; j+= speed) { ManagedWinapi.ProcessMemoryChunk mem = new ProcessMemoryChunk(p, (IntPtr)j, speed + searchedBytes.Length); byte[] bigMem = mem.Read(); for (int k = 0; k < bigMem.Length - searchedBytes.Length; k++) { bool found = true; for (int l = 0; l < searchedBytes.Length; l++) { if(bigMem[k+l] != searchedBytes[l]) { found = false; break; } } if(found) { addr = k+j; break; } } if (addr != 0) { //addrList.Add(addr); //addr = 0; break; } } //return addrList; return addr; }