6

プロセスによって使用されるすべてのメモリ アドレス空間を知る必要があります。メモリ空間は後でスキャンされ、プロセス内の値が特定され、その場所/アドレスが特定されます。これに対する私の現在のプロセスは、各モジュールのベース アドレスを (ベース アドレス + メモリ サイズ) で取得することです。

既知のアドレスで既知の値を持つプロセスでこれをテストしています。その特定のアドレスを調べると、期待どおりの値が得られます。ただし、プロセスで使用されるすべてのアドレス空間をスキャンすると (私が信じているもの)、どこにも値が見つかりません。

0x0CF8DC380x0CF8DDDCに「4143000」という数値が存在することがわかっています。ReadMemoryBytes(module, module.BaseAddress, 4, (IntPtr)(0x0CF8DC38))を呼び出すと、バイト (152, 55, 63, 0) が返されます。BitConverter.GetBytes(4143000) を呼び出すと、同じバイト セットが返されます。そのプロセスで別のメモリ スキャナを使用すると、それらのアドレスでその値が見つかります。

ただし、「既知のアドレス」をスキャンすると、この値がどこにも見つかりません。私のコードは、プロセスで使用されているアドレスを見つけているようには見えません。

したがって、私の質問は 2 つあります。

  • このプロセス内でこれらのアドレスを見つけるにはどうすればよいですか?
  • システムメモリ内の絶対アドレスとプロセス内の相対アドレスを扱っているのではないかと心配しています。私はこれを正しく行っていますか?

.

// (in the calling method)
foreach (ProcessModule module in process.Modules) {
    ParameterizedThreadStart pst = new ParameterizedThreadStart(p => SearchModule(module, value));
    Thread t = new Thread(pst);
    t.Start(); }

private unsafe void SearchModule(ProcessModule module, string value)
{
Process process = getProcess;
int iVal;
double dVal;
int.TryParse(value, out iVal);
double.TryParse(value, out dVal);
for (Int64 addr = (Int64)module.BaseAddress; addr + value.Length < (Int64)module.BaseAddress + module.ModuleMemorySize; addr++)
{
    // Compare ints
    if (iVal > 0)
    {
        byte[] ExpectedBytes = BitConverter.GetBytes(iVal);
        byte[] ActualBytes = ReadMemoryBytes(module, (IntPtr)addr, (uint)ExpectedBytes.Length, (IntPtr)addr);

        bool isMatch = true;
        for (int i = 0; i < ExpectedBytes.Length; i++)
            if (ExpectedBytes[i] != ActualBytes[i])
                isMatch = false;
        if (isMatch)
            PossibleAddresses.Add((IntPtr)addr);
    }
}

private byte[] ReadMemoryBytes(ProcessModule mod, IntPtr memAddress, uint size, IntPtr BaseAddress)
{
    byte[] buffer = new byte[size];
    IntPtr bytesRead;
    unsafe
    {
        ReadProcessMemory(processPointer, BaseAddress, buffer, size, out bytesRead);
        return buffer;
    }
}

[DllImport("kernel32.dll")]
public static extern IntPtr OpenProcess(UInt32 dwDesiredAccess, Int32 bInheritHandle, UInt32 dwProcessId);
[DllImport("kernel32.dll")]
public static extern Int32 CloseHandle(IntPtr hObject);
[DllImport("kernel32.dll")]
public static extern Int32 ReadProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, [In, Out] byte[] buffer, UInt32 size, out IntPtr lpNumberOfBytesRead);
4

1 に答える 1

1

取得しているアドレスは、マネージド (CLR) ヒープへのポインターです。通常、これらは絶対メモリ アドレスにマップされず、GC の実行が決定されると、呼び出しから呼び出しへと移動できます。

「安全でない」コードを使用すると、相対ポインタを取得したり、独自のメモリ空間を管理したりできます。まだヒープ上にありますが、少なくとも GC がアドレス空間を変更しないことが保証されています。

大規模なラッピングなしで非 CLR コードからヒープ上のものにアクセスできるとは思わないでください。CLR で管理されるプロセス間で IPC を実行する方法はありますが、非 CLR プロセスがメモリにアクセスできるようにする場合は、アクセス プロキシを「外部の世界」に書き込む必要があります。

于 2011-08-26T14:01:21.607 に答える