別のプログラムのメモリを追跡する必要があり、そこに表示される一連のバイトを常に探しています。それらが表示された場合、その場所を覚えておく必要があるため、後でどこに書き込むかがわかります。
次の投稿を使用して、別のプロセスのメモリで byte[] を探す方法を学びました: C#: 別のプロセスのメモリで byte[] 配列を検索する
私のプログラムは非常に単純です: プロセスを起動し (Process.Start を使用)、リンクされたスレッドの回答の 1 つから関数を繰り返し実行します。
private static int GetMemoryAddressOfString(byte[] searchedBytes)
{
IntPtr hProcess = OpenProcess(ProcessAccessFlags.VMOperation | ProcessAccessFlags.VMRead | ProcessAccessFlags.VMWrite, false, Program.ArtemisProcess.Id);
if (hProcess == IntPtr.Zero)
throw new Win32Exception(Marshal.GetLastWin32Error());
int addr = 0;
int speed = 1024 * 64;
for (int j = 0x00400000; j < 0x11000000; j += speed)
{
byte[] bigMem = new byte[speed + searchedBytes.Length];
IntPtr unmanagedPointer = Marshal.AllocHGlobal(4);
ReadProcessMemory(hProcess, (IntPtr)j, bigMem, new UIntPtr((uint)(speed + searchedBytes.Length)), unmanagedPointer);
int result = Marshal.ReadInt32(unmanagedPointer);
Marshal.DestroyStructure(unmanagedPointer, typeof(int));
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)
break;
}
return addr;
}
ArtemisProcess は、.Start() で実行したプロセスです
ほとんどの場合、問題なく動作します。監視対象のプロセスで、検索された一連のバイトをメモリに格納するアクションを実行するとすぐに、次の検索でそれが見つかります。ただし、時々、そうではありません。
私が正しいかどうか疑問に思っていたので、Cheat Engine を使用して、検索されたデータがそこにあることを確認しました。
次に、読み取られたバイト数を知るためにアンマネージ ポインターを作成する部分を追加しました。検索されたバイトが表示されるメモリ内の正確な場所 (チート エンジンが正しく識別する) が 0 を返すことがわかりました。そこのメモリを読み取らせません。この「ロックアウト」は約 1 ~ 2 分間発生し、そのときだけメモリを読み取ることができます (突然、その場所でメモリを読み取ろうとする次の試みは成功し、バイトのシーケンスは問題なく検出されます)。 )。
今、私はmsdnで「要求された読み取り操作がアクセスできないプロセスの領域にまたがると関数が失敗する」と読みましたが、プロセスメモリのどの部分がアクセス可能で、どの部分がそうでないかをどのように知ることができますか?
Cheat Engine がそのメモリを読み取ることができるのに、私のプログラムが読み取れないのはなぜですか?
突然、プロセス メモリを再び読み取れるようになったのはなぜですか?
私はここで途方に暮れています...