2009-04-23 24 views
6

Làm thế nào để tìm kiếm mảng byte [] trong bộ nhớ của một tiến trình khác và lấy địa chỉ tại vị trí mảng byte []?C#: Tìm kiếm mảng byte [] trong bộ nhớ của một quá trình khác

Tôi muốn viết một mảng byte vào bộ nhớ của một tiến trình khác (WriteProcessMemory()) Một trong các tham số của cuộc gọi đó là uint Address.Well Tôi muốn lấy địa chỉ bằng cách tìm kiếm một mảng byte trong tiến trình.

Ví dụ tôi tìm kiếm {0xEB, 0x20,0x68,0x21,0x27,0x65, ??, 0x21,0x64,0xA1}

Chúng tôi cho rằng mảng này được đặt chỉ vào một chỗ trong bộ nhớ của quá trình tôi muốn viết bộ nhớ.

Để nhận địa chỉ đó, tôi phải tìm kiếm mảng byte đó.

Có thể thực hiện trong C# không?

EDIT:Đây là ứng dụng gốc, KHÔNG .NET. Không cần phải downvote câu hỏi của tôi, có những thành phần cho C + + mà làm điều này, tôi chỉ muốn làm điều đó trong C#.

Cảm ơn bạn đã thông cảm!

+0

Chỉ cần tò mò, tại sao? – Lazarus

+1

Tôi không muốn sử dụng bên ngoài C + + dll, bởi vì nó đòi hỏi thời gian chạy và tôi muốn làm việc với bộ nhớ trong NET là tốt. –

+1

John: không có thời gian chạy nào bạn cần cho một ứng dụng gốc không được bao gồm trong Windows và bạn sẽ phải làm việc với bộ nhớ thô. – Richard

Trả lời

0

Có thể thực hiện trong C# không?

Có. Nhưng rất khó. Nó là khó khăn từ một ứng dụng bản địa, nơi không có trở kháng không phù hợp với quan điểm không được quản lý của các quy trình và bản đồ bộ nhớ của họ, bạn sẽ cần phải sử dụng.

Lưu ý:

  • Bạn sẽ cần sự cho phép để mở quá trình này để có được một tay cầm.
  • Mặc dù không gian bộ nhớ ảo của quy trình 32 bit có kích thước từ 2 đến 4 GB (tùy thuộc vào hệ điều hành máy chủ và/3GB), phần lớn dải địa chỉ này sẽ không được cấp phát và đọc nó sẽ gây ra lỗi trang. Bạn thực sự cần phải tìm ra những trang được phân bổ và cho những gì để tránh rất nhiều truy cập trang không hợp lệ.

Gợi ý:

  • Bạn có thực sự thực sự cần phải làm điều này? Nghiêm túc điều này sẽ khó khăn.
  • Cân nhắc thực hiện một ứng dụng gốc, điều này sẽ tránh làm việc trên hàng rào gốc/được quản lý (điều này có thể bao gồm thư viện gốc với ứng dụng trình điều khiển được quản lý).
  • Bạn có thực sự cần thực hiện việc này không?
  • Cân nhắc thực hiện công việc trong quá trình nhắm mục tiêu. Điều này sẽ yêu cầu một số thông minh (tài liệu) để tiêm một sợi, nhưng sau đó sẽ nhanh hơn nhiều.
  • Bắt đầu bằng cách đọc trên Windows cách bộ nhớ xử lý hoạt động (bắt đầu với Windows Internals và (không thể nhớ tên của nó trong ấn bản mới nhất) sách của Jeffrey Richter về phát triển ứng dụng Win32. phải có một cái gì đó đơn giản hơn ... bạn có thể tự động một debugger
+0

Tôi có thể lấy địa chỉ trong trình gỡ rối, vấn đề là ứng dụng tôi đang thực hiện điều này là thương mại và đang được cập nhật mỗi tuần một lần. Tôi đoán tôi phải làm điều này. –

+0

@John: Trong trường hợp đó, cả VS và windbg đều có các mô hình mở rộng (VS là .NET), nên tránh mọi công việc khó khăn. – Richard

+0

Bạn có thể cho tôi biết thêm thông tin về nó không? –

-3

Nếu có thể, tôi không nghĩ vậy. Và tôi thực sự hy vọng không phải vì đó sẽ là một rủi ro an ninh nghiêm trọng.

+0

Điều đó có thể được thực hiện bằng C++, nó dành cho các ứng dụng gốc, chứ không phải NET. –

+3

Tại sao nó sẽ là một nguy cơ bảo mật? Bạn cho rằng các trình gỡ rối hoạt động như thế nào? :) –

+0

Nó không phải là một nguy cơ bảo mật, bạn phải mở quá trình và điều đó có nghĩa là đi qua ACL của quá trình khác. Không quản trị viên chỉ có thể mở quy trình của riêng họ, quản trị viên (với độ cao, bao gồm bất kỳ ai có đặc quyền gỡ lỗi) có thể mở bất kỳ quy trình nào – Richard

6

Tôi đoán bạn có thể sử dụng lệnh gọi ReadProcessMemory Windows API. Thậm chí còn có một premade P/Invoke signature cho nó, do đó bạn không cần phải bận tâm với việc tạo thủ công nó. Bạn trang qua bộ nhớ của quá trình, tìm kiếm thông qua nó cho mô hình của bạn và bạn đã hoàn tất.

+0

Tôi cần phải xác định địa chỉ mà tôi phải gọi đó (một trong các tham số của nó là địa chỉ) .Về câu hỏi của tôi là: Cách lấy địa chỉ bằng cách tìm kiếm trong bộ nhớ. Tôi nghĩ rằng tìm kiếm thông qua toàn bộ hình ảnh, nhưng điều đó sẽ mất nhiều thời gian. –

+2

Giả sử bạn đang làm điều đó trong môi trường 32 bit, bạn nên sử dụng các trang 4096 byte để tra cứu, tổng cộng là 1048576. ReadProcessMemory trả về false nếu địa chỉ không thể truy cập để tăng tốc vòng lặp đáng kể. Tôi không nghĩ rằng nó sẽ mất rất nhiều thời gian để hoàn thành đặc biệt là vì nó không chắc rằng mô hình của bạn sẽ được hơn 1GB. Và bạn cũng không có lựa chọn nào khác. –

+1

@John: bạn sẽ cần phải sử dụng các API bộ nhớ để chỉ đọc bộ nhớ có thể đọc được (thanh toán VMMap.exe với hiển thị bộ nhớ trống được bật ... hầu hết bản đồ bộ nhớ ảo không được sử dụng). – Richard

1

điều này có thể giúp bạn tìm được đúng cách:?

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

Tôi thích phương pháp này tốt hơn là tìm kiếm mẫu bằng ReadProcessMemory(). Tuy nhiên, điều này có vấn đề trong khi tìm kiếm mẫu trong vùng bộ nhớ không thể ghi. –

3

bạn sẽ muốn sử dụng các 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 là tài nguyên tuyệt vời cho các cuộc gọi API Windows. Tôi đã viết một huấn luyện viên cho GTA: Vice City sử dụng các cuộc gọi này nếu bạn muốn xem code trên sourceforge. Đoạn mã này không đẹp lắm, đã lâu lắm rồi và tôi chỉ ném nó lại với nhau, nhưng có những lớp trợ giúp để liệt kê các vùng bộ nhớ cho một tiến trình và tìm kiếm các byte hoặc chuỗi nhất định.

17

Có thể thực hiện trong C# không? Everithing là có thể trong C# (hoặc bất kỳ languge khác), u chỉ cần fiind như thế nào;

cứng mã hóa ở đây:

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

@Danie - Ví dụ có thể giúp những người khác - tốt đẹp – Leons

+2

+1 Để thực sự trả lời câu hỏi mà không cố gắng để ở lạ mắt và đạo đức. –

Các vấn đề liên quan