2009-04-23 10 views
6

他のプロセスのメモリ内のバイト[]配列を検索し、バイト[]配列が配置されている場所でアドレスを取得するにはどうすればよいですか?C#:別のプロセスのメモリ内のバイト[]配列を検索

別のプロセス(WriteProcessMemory())のメモリにバイト配列を書きたいと思います。その呼び出しのパラメータの1つはuintです。Address.Wellバイト配列をプロセスに検索してアドレスを取得したいとします。

Iは{0xEB、0x20,0x68,0x21,0x27,0x65、??、0x21,0x64,0xA1}を検索たとえば

我々は、この配列がメモリに一箇所のみに配置されていることを前提とプロセスを私はメモリを書きたいと思います。

そのアドレスを取得するには、そのバイト配列を検索する必要があります。

C#で行うことはできますか?

編集:これはネイティブアプリケーション用であり、.NET用ではありません。私の質問をd​​ownvoteする必要はありません、これを行うC + +のコンポーネントがあります、私はちょうどC#でそれをやりたいです。

ありがとうございます!

+0

興味があるだけ、なぜ? – Lazarus

+1

私は外部C++ dllを使用したくないのです。なぜなら、ランタイムが必要で、私もNETのメモリを使いたいからです。 –

+1

John:Windowsには含まれていないネイティブアプリケーションに必要なランタイムがないため、とにかにRAWメモリーで作業する必要があります。 – Richard

答えて

0

C#で行うことはできますか?

はい。しかし、非常に難しい。プロセスの管理されていないビューと、使用する必要があるメモリマップとのミスマッチがないネイティブアプリケーションは難しいです。

考慮事項:

  • あなたはハンドルを取得するプロセスを開く権限が必要になります。
  • 32ビットプロセスの仮想メモリ空​​間は2〜4 GB(ホストOSと/ 3GBスイッチによって異なる)ですが、このアドレス範囲の多くは割り当てられず、読み取りによってページフォールトが発生します。あなたは本当にどのページが割り振られているのか、多くの無効なページへのアクセスを避けるべきかを知る必要があります。

提案:

  • あなたが本当にこれを実行する必要がありますか?真剣にこれは難しいでしょう。
  • ネイティブアプリケーションを実行することを検討してください。ネイティブ/管理フェンス(これには、管理対象ドライバアプリケーションを使用したネイティブライブラリが含まれる可能性があります)を回避することができます。
  • 本当にこれが必要ですか?
  • ターゲットプロセス内で作業を行うことを検討してください。これはスレッドを注入するためにある程度の賢明さ(文書化されている)を必要とするが、はるかに速くすべきである。
  • Win32アプリケーション開発に関するJeffrey Richterの書籍
  • 本当にこれを行う必要がありますか?(Windows Internalsで始まり、その名前を最新版では思い出すことはできません) ...あなたは、デバッガを自動化された可能性が単純に何かがあるに違いありません
+0

私はデバッガでアドレスを取得することができます。問題は、私がこれをやっているアプリケーションが商用で週に1回更新されていることです。私はこれをやる必要があると思います。 –

+0

@ジョン:その場合、VSとwindbgの両方が拡張性モデルを持っています(VSは.NETです)。 – Richard

+0

あなたはそれについてもっと知りたいですか? –

-3

可能であれば、私はそうは思わない。それが深刻なセキュリティ上のリスクになるので、本当に本当に望んでいません。

+0

これはC++で行うことができます。これはNETではなく、ネイティブアプリケーション用です。 –

+3

なぜセキュリティリスクになるのですか?デバッガはどのように機能すると思いますか? :) –

+0

セキュリティリスクではないので、プロセスを開く必要があり、それは他のプロセスのACLを経由することを意味します。非管理者は自分のプロセスだけを開くことができ、管理者は(デバッグ特権を持つ人を含む)すべてのプロセスを開くことができます。 – Richard

6

ReadProcessMemory Windows API呼び出しを使用することができますね。 premade P/Invoke signatureもありますので、手動で作成する必要はありません。あなたはプロセスのメモリをページングし、パターンを検索して完了します。

+0

私はそれを呼び出す必要があるアドレスを指定する必要があります(そのパラメータの1つはアドレスです)。私の質問は次のとおりです。メモリを検索してアドレスを取得する方法。画像全体を検索していると思ったが、たくさんの時間。 –

+2

32ビット環境でこれを実行しているとすると、検索には4096バイトのページを使用するのが理にかなっており、合計は1048576です。 ReadProcessMemoryは、アドレスにアクセスできない場合にループを大幅に高速化する場合にfalseを返します。私はあなたのパターンが1GB以上になることはほとんどないので特に終えるのに時間がかかるとは思わない。あなたは本当に他の選択肢もありません。 –

+1

@ジョン:読み込み可能なメモリだけを読み取るためにメモリAPIを使用する必要があります(空きメモリが有効になっていることを示すチェックアウトVMMap.exe ...ほとんどの仮想メモリマップは使用されていません)。 – Richard

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

私はこのメソッドがReadProcessMemory()を使用してパターンを検索するよりも好きです。しかし、これは書き込み不可能なメモリ領域でパターンを検索する際に問題があります。 –

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のためのトレーナーを書いた:あなたがソースフォージのcodeをチェックしたいならば、これらのコールを使うVice City。コードはあまり古くはありませんでしたが、以前は一緒でしたが、プロセスのメモリ領域を列挙して特定のバイトや文字列を検索するためのヘルパークラスがあります。

17

C#で行うことはできますか? Everithingは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

@ダニー - この例は他の人を助けるかもしれません - nice – Leons

+2

+1実際に疑問に答えるために、空想的で道徳的であることを試みることなく。 –