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

Iva*_*nov 5 c# memory process

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

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

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

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

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

是否可以在C#中完成?

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

感谢您的理解!

小智 16

是否可以在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;
    }
}
Run Code Online (Sandbox Code Playgroud)

}

  • +1实际上回答问题而不试图保持幻想和道德. (3认同)

Tam*_*ege 6

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

  • 假设您在32位环境中执行此操作,则使用4096字节的页面进行查找是有意义的,总共为1048576.如果地址不可访问,则ReadProcessMemory返回false,这大大加快了循环速度.我不认为这需要花费很多时间才能完成,因为你的模式不太可能超过1GB.你也没有其他任何选择. (2认同)

Ric*_*ard -2

可以用C#来完成吗?

是的。但非常难。对于本机应用程序来说,这很困难,因为没有与您需要使用的进程的非托管视图及其内存映射不匹配的阻抗。

注意事项:

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

建议:

  • 你真的需要这样做吗?说真的,这会很难。
  • 考虑做一个本机应用程序,这将避免跨本机/托管围栏工作(这可能包括带有托管驱动程序应用程序的本机库)。
  • 你真的需要这样做吗?
  • 考虑在目标进程内进行工作。这将需要一些技巧(已记录)来注入线程,但应该会快得多。
  • 首先阅读 Windows 进程内存的工作原理(从 Windows Internals 开始,以及(不记得最新版本中的名称)Jeffrey Richter 的有关 Win32 应用程序开发的书。
  • 你真的需要这样做吗?一定有更简单的东西......你可以自动化调试器吗?