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

时间:2009-04-23 13:31:37

标签: c# memory process

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

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

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

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

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

是否可以在C#中完成?

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

感谢您的理解!

5 个答案:

答案 0 :(得分:16)

是否可以在C#中完成? 在c#(或任何其他语言)中,一切皆有可能,你只需要弄清楚如何;

这里的硬编码:

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

}

答案 1 :(得分:6)

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

答案 2 :(得分:3)

您需要使用这些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上的code,可以使用这些电话的Vice City。代码并不漂亮,很久以前我只是把它放在一起,但是有一些辅助类来枚举进程的内存区域并搜索某些字节或字符串。

答案 3 :(得分:1)

这可以帮助您找到正确的方法:

private static int GetMemoryAddressOfString(byte[] searchedBytes, Process p)
{
    //List<int> addrList = new List<int>();
    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;
}

答案 4 :(得分:-1)

  

是否可以在C#中完成?

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

考虑:

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

建议:

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