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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/781716/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-05 00:56:21  来源:igfitidea点击:

C#: Search a byte[] array in another process's memory

c#memoryprocess

提问by Ivan Prodanov

How is it possible to search for a byte[] array in the memory of another process and then get the address at the place where the byte[] array is located?

怎么可能在另一个进程的内存中搜索一个byte[]数组,然后得到byte[]数组所在位置的地址呢?

I want to write a byte array into the memory of another process(WriteProcessMemory()).One of the parameters of that call is uint Address.Well I want to get the address by searching a byte array into the process.

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

For example I search for {0xEB ,0x20,0x68,0x21,0x27,0x65, ??, 0x21,0x64,0xA1}

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

We assume that this array is placed only at one place in the memory of the process I'd like to write memory to.

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

To get that address,I have to search for that byte array.

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

Is it possible to be done in C#?

是否可以在 C# 中完成?

EDIT:This is for native applications,NOT .NET. No need to downvote my question,there are components for C++ that do this,I just want to do it in C#.

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

Thanks for understanding!

感谢您的理解!

采纳答案by Richard

Is it possible to be done in C#?

是否可以在 C# 中完成?

Yes. But very hard. It is hard from a native application where there is no impedance mismatched with the unmanaged view of processes and their memory maps you will need to use.

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

Considerations:

注意事项:

  • You will need permission to open the process to get a handle.
  • While the virtual memory space of a 32bit process is from two to four GB in size (depending on host OS and /3GB switch), much of this address range will not be allocated, and reading it will cause a page fault. You really need to find out what pages are allocated and for what to avoid lots of invalid page accesses.
  • 您需要获得权限才能打开该进程以获取句柄。
  • 虽然 32 位进程的虚拟内存空间大小为 2 到 4 GB(取决于主机操作系统和 /3GB 开关),但该地址范围的大部分将不会被分配,读取它会导致页面错误。您确实需要找出分配了哪些页面以及用于避免大量无效页面访问的内容。

Suggestions:

建议:

  • Do you really really need to do this? Seriously this will be hard.
  • Consider doing a native application, this will avoid working across the native/managed fence (this could include a native library with a managed driver application).
  • Do you really need to do this?
  • Consider doing the work inside the target process. This will require some cleverness (documented) to inject a thread, but should then be much faster.
  • Start by reading up on Windows how process memory works (start with Windows Internals and (can't recall its name in the latest edition) Jeffrey Richter's book on Win32 application development.
  • Do you really need to do this? There must be something simpler... could you automated a debugger?
  • 你真的需要这样做吗?说真的,这将很难。
  • 考虑做一个本机应用程序,这将避免跨本机/托管栅栏工作(这可能包括带有托管驱动程序应用程序的本机库)。
  • 你真的需要这样做吗?
  • 考虑在目标进程内部进行工作。这将需要一些聪明才智(已记录)来注入线程,但应该会更快。
  • 首先阅读 Windows 上的进程内存是如何工作的(从 Windows Internals 和(在最新版本中记不起它的名字)Jeffrey Richter 关于 Win32 应用程序开发的书开始。
  • 你真的需要这样做吗?一定有更简单的东西......你能自动化调试器吗?

回答by Tamas Czinege

I guess you could use the ReadProcessMemoryWindows API call. There's even a premade P/Invoke signaturefor it so you don't need to bother with manually crafting it. You page through the memory of the process, search through it for your pattern and you're done.

我猜您可以使用ReadProcessMemoryWindows API 调用。甚至还有一个预制的 P/Invoke 签名,因此您无需费心手动制作它。你翻阅这个过程的记忆,搜索你的模式,你就完成了。

回答by Richard

This may help you find the right way:

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

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

回答by Jason Goemaat

You'll want to use these APIs:

您需要使用这些 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.netis a great resource for Windows API calls. I wrote a trainer for GTA: Vice City that uses these calls if you want to check out the codeon sourceforge. The code isn't pretty, it was a long time ago and I just threw it together, but there are helper classes for enumerating memory regions for a process and searching for certain bytes or strings.

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

回答by Dani

Is it possible to be done in C#? Everithing is possible in c#(or any other languge), u just need to fiind how;

是否可以在 C# 中完成?在 c#(或任何其他语言)中,一切皆有可能,您只需要找到方法即可;

Hard coding here:

硬编码在这里:

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

}

}