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

发布于 2024-07-18 01:00:39 字数 441 浏览 4 评论 0原文

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

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

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

我们假设该数组仅放置在我想要写入的进程的内存中的一个位置记忆到.

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

可以用C#来完成吗?

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

感谢您的理解!

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?

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.

For example I search for {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#?

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#.

Thanks for understanding!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

拥醉 2024-07-25 01:00:39

可以用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;
    }
}

}

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

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

}

木有鱼丸 2024-07-25 01:00:39

我想你可以使用 ReadProcessMemory Windows API称呼。 甚至还有一个预制 P/Invoke 签名,这样您就不需要无需费心手动制作它。 您翻阅流程的内存,搜索您的模式,然后就完成了。

I guess you could use the ReadProcessMemory Windows API call. There's even a premade P/Invoke signature for 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.

暗喜 2024-07-25 01:00:39

您需要使用这些 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: Vice City 编写了一个训练器,如果您想查看 代码在sourceforge上。 代码并不漂亮,那是很久以前的事了,我只是把它放在一起,但是有一些帮助器类用于枚举进程的内存区域并搜索某些字节或字符串。

You'll want to use these APIs:

    [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 is 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 code on 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.

萌酱 2024-07-25 01:00:39

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

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

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;
}
抽个烟儿 2024-07-25 01:00:39

可以用C#实现吗?

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

注意事项:

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

建议:

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

Is it possible to be done in 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.

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?
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文