0

私は簡単な仕事をする Win32 の下で DLL を開発しています: それは部分文字列のためにホストの仮想メモリをスキャンします。しかし、何らかの理由で、Cheat Engine、ArtMoney、または単一スレッドを使用してスキャンする OllyDbg と比較して、非常に遅くなります。VirtualQuery() で取得した単一のメモリ セクションをスキャンする関数のコードを次に示します。ホスト (.exe アプリケーション) は約 300 ~ 400 MiB のメモリをコミットし、4KiB から 32MiB までのさまざまなサイズで約 170 のメモリ セクションをスキャンする必要があります。MEM_PRIVATE、MEM_COMMIT 領域のみをスキャンし、PAGE_GUARD、PAGE_NOACCESS、PAGE_READONLY はスキャンせず、DLL 自身のメモリをスキップします。

なんらかの理由でパフォーマンスがひどいです。単一の文字列を見つけるのに 10 ~ 12 秒かかります。たとえば、OllyDbg は 2 ~ 3 秒で文字列を見つけます。

UINT __stdcall ScanAndReplace(UCHAR* pStartAddress, UCHAR* pEndAddress, const char* csSearchFor, const char* csReplaceTo, UINT iLength)
{
    // This function runs inside the single memory section and looks for a specific substring

    // pStartAddress: UCHAR* - The begining of the memory section
    // pEndAddress: UCHAR* - The ending of the memory section
    // csSearchFor: const char* - The pointer to the substring to search for
    // csReplaceTo: const char* - The pointer to the substring to replace with
    // iLength: UINT - max length of csSearchFor substring

    // Total iterations
    UINT iHits = 0;

    // Scan from pStartAddress to (pEndAddress - iLength) and don't overrun memory section
    for (pStartAddress; pStartAddress < (pEndAddress - iLength); ++pStartAddress)
    {
        UINT iIterator = 0;

        // Scan for specific string that begins at current address (pStartAddress) until condition breaks
        for (iIterator; (iIterator < iLength) && (pStartAddress[iIterator] == csSearchFor[iIterator]); ++iIterator);

        // String matches if iIterator == iLength
        if (iIterator == iLength)
        {
            // Found, do something (edit/replace, etc), increment counter...
            ++iHits;
        }

        /*
        // Even if you search for single byte it's very slow
        if (*pStartAddress == 'A')
            ++iHits;
        */
    }

    return iHits;
}

MSVS2010を使用しています。

コンパイラ コマンド ライン:

/nologo /W3 /WX- /O2 /Os /Oy- /GL /D "WIN32" /D "NDEBUG" /D "_WINDOWS"
  /D "_USRDLL" /D "MYDLL_EXPORTS" /D "_WINDLL" /GF /Gm- /MD /GS- /Gy
  /fp:precise /Zc:wchar_t /Zc:forScope /Fp"Release\MyDll.pch" /FAcs
  /Fa"Release\" /Fo"Release\" /Fd"Release\vc100.pdb" /Gd /TC /analyze-
  /errorReport:queue

リンカー コマンド ライン:

/OUT:"D:\MyDll\Release\MyDll.dll" /INCREMENTAL:NO /NOLOGO /DLL "Dbghelp.lib"
  "msvcrt.lib" "kernel32.lib" "user32.lib" "gdi32.lib" "winspool.lib"
  "comdlg32.lib" "advapi32.lib" "shell32.lib" "ole32.lib" "oleaut32.lib"
  "uuid.lib" "odbc32.lib" "odbccp32.lib" /NODEFAULTLIB /MANIFEST:NO
  /ManifestFile:"Release\MyDll.dll.intermediate.manifest" /ALLOWISOLATION
  /MANIFESTUAC:"level='asInvoker' uiAccess='false'" /DEBUG
  /PDB:"D:\MyDll\Release\MyDll.pdb" /SUBSYSTEM:WINDOWS /OPT:REF /OPT:ICF
  /PGD:"D:\MyDll\Release\MyDll.pgd" /LTCG /TLBID:1 /ENTRY:"DllMain"
  /DYNAMICBASE /NXCOMPAT /MACHINE:X86 /ERRORREPORT:QUEUE

私は何を間違っていますか?私のアルゴリズムが悪いのでしょうか、それとも他のメモリスキャナが使用するある種の「魔法」がありますか?

4

1 に答える 1

0

他のメモリ スキャナは、 Boyer-Mooreなどのより優れた検索アルゴリズムの形で「魔法」を使用している可能性があります。彼らはまた、検索アルゴリズムで追加のマイクロ最適化を行っている可能性がありますが、アルゴリズムの選択が、あなたが見ている違いのほとんどを説明していると思います.

于 2015-09-15T22:44:47.740 に答える