2

特定のアプリケーション用の小さなメモリ スキャナーを開発しています。スキャンするプロセスを選択するとき、最初にしたいことは、プロセスが特定のアプリケーションのインスタンスであることを確認することです...そしてこれを行うには、そのメモリ内のどこかにある可能性のある署名を見つける必要があります。

これが私のコードです:

[DllImport("Kernel32.dll", CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Unicode, ExactSpelling = true, SetLastError = true)] 
[return: MarshalAs(UnmanagedType.Bool)] 
internal static extern Boolean ReadProcessMemory([In] IntPtr processHandle, [In] IntPtr processAddress, [Out] Byte[] buffer, [In] UInt32 bytesToRead, [Out] out IntPtr bytesRead); 

[DllImport("Kernel32.dll", CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Unicode, ExactSpelling = true, SetLastError = true)] 
internal static extern UInt32 VirtualQueryEx([In] IntPtr processHandle, [In, Optional] IntPtr processAddress, [Out] out MEMORY_BASIC_INFORMATION buffer, [In] UInt32 bufferSize); 



internal struct MEMORY_BASIC_INFORMATION 
{ 
    public static UInt32 Size = (UInt32)Marshal.SizeOf(typeof(MEMORY_BASIC_INFORMATION)); 

    public IntPtr BaseAddress; 
    public IntPtr AllocationBase; 
    public AllocationProtect AllocationProtect; 
    public IntPtr RegionSize; 
    public StateEnum State; 
    public AllocationProtect Protect; 
    public TypeEnum lType; 
} 



public void Open() 
{ 
    Byte[] toFind = new Byte[] { 31, 55, 78, 33, 00, 00, 00, 37 }; 
    UInt32 address = 0; 

    do 
    { 
        MEMORY_BASIC_INFORMATION info = new MEMORY_BASIC_INFORMATION();

        if (NativeMethods.VirtualQueryEx(m_Process.Handle, (IntPtr)address, out info, NativeMethods.MemoryBasicInformation.Size) == 0)
            break;

        Byte[] buffer = new Byte[(UInt32)info.RegionSize]; 
        IntPtr bytesRead; 

        if (NativeMethods.ReadProcessMemory(m_Process.Handle, info.BaseAddress, buffer, (UInt32)buffer.Length, out bytesRead)) 
        { 
            if (buffer.Contains(toFind)) // Extension Method 
            {
                m_IsValid = true;
                break;
            }
        }

        if (address == (UInt32)info.BaseAddress + (UInt32)info.RegionSize) 
            break; 

        address = (UInt32)info.BaseAddress + (UInt32)info.RegionSize; 
    } 
    while (address <= 0x7fffffff); 
}

このメソッドが決して完了に達せず、無限にループしているように見えるという最初の問題 (昨日、最後に到達することなく、デバッグ目的で 1 時間以上実行させました)。ERROR_PARTIAL_COPY (0x0000012B)ループ内で Marshal.GetLastWin32Error() をチェックすると、呼び出し後にエラーが発生することがあることに気付きましたReadProcessMemory...これは考えられる原因ですか?

次に、いくつか質問があります。

1)OpenProcessスキャン ループに進む前に電話する必要がありますか? そうは思いませんよね?

2) アプリケーションを x32 と x64 の両方に対応させたいと考えています。address両方のシステム (制限、値の型addressRegionSizeキャストなど)で適切に動作するようにするには、コード内で何を変更する必要がありますか?

3) ターゲットのバイト配列を見つけるためにプロセス メモリをスキャンしているときに、現在MEMORY_BASIC_INFORMATIONの のプロパティ ( AllocationProtectStateProtectおよび/または) をチェックして、現在の領域lTypeをスキップできるかどうかを確認する必要があります。ReadProcessMemory読まれる?

4) このメソッドの速度を最適化するために他にできることはありますか?これは非常に重要です。

4

1 に答える 1

0

うおおおおおお 解決しました。問題は、VirtualQueryEx を使用せずにメモリ領域の保護をチェックせずに読み取ろうとしていた方法でした!

于 2013-05-03T12:37:41.623 に答える