1

私の目標は、ファイルの動きを弱く監視することです。グローバル フックを作成するための非常に簡単なガイドを見つけて、問題なく動作するようにしました (64 ビット バージョンと 32 ビット バージョンの両方をコンパイルし、それらを異なるレジストリの場所に配置する必要があることに注意してください)。個人的な演習として、CopyFile (MoveFile、CreateFile、およびそれらの素晴らしいバリアントすべてからランダムに選択) をフックしてみました。ガイドとまったく同じ手順に従って、この非常に短いコードにたどり着きました。

#include "stdafx.h"
#include "mhook/mhook-lib/mhook.h"

//////////////////////////////////////////////////////////////////////////
// Defines and typedefs

typedef BOOL (WINAPI *CopyFileFP)(
    _In_  LPCTSTR lpExistingFileName,
    _In_  LPCTSTR lpNewFileName,
    _In_  BOOL bFailIfExists
    );

//////////////////////////////////////////////////////////////////////////
// Original function

CopyFileFP OriginalCopyFile = (CopyFileFP)::GetProcAddress(::GetModuleHandle(L"kernel32"), "CopyFileW");

//////////////////////////////////////////////////////////////////////////
// Hooked function

BOOL WINAPI HookedCopyFile(
    _In_  LPCTSTR lpExistingFileName,
    _In_  LPCTSTR lpNewFileName,
    _In_  BOOL bFailIfExists
    )
{
    BOOL out = OriginalCopyFile(
                lpExistingFileName,
                lpNewFileName,
                bFailIfExists);

     char hello[] = "Hello\n";
     DWORD charsWritten = 0;

     WriteConsole(
         GetStdHandle(STD_OUTPUT_HANDLE),
         hello,
         6,
         &charsWritten,
         NULL);

    return out;
}

//////////////////////////////////////////////////////////////////////////
// Entry point

BOOL WINAPI DllMain(
    __in HINSTANCE  hInstance,
    __in DWORD      Reason,
    __in LPVOID     Reserved
    )
{        
    switch (Reason)
    {
    case DLL_PROCESS_ATTACH:
        AllocConsole();
        Mhook_SetHook((PVOID*)&OriginalCopyFile, HookedCopyFile);
        break;

    case DLL_PROCESS_DETACH:
        FreeConsole();
        Mhook_Unhook((PVOID*)&OriginalCopyFile);
        break;
    }

    return TRUE;
}

DLL がどのように動作しているかを確認したかったので、なんらかの形式の出力が必要でした。いくつかのコンソール コマンドを追加しましたが、どれも目を見張るような機能を使用していません (ソース ファイルパスと宛先ファイルパスを出力するための文字列処理は行っていません)。dll を登録してプロセスを再起動した後 (通常は、非常に簡単で 64 ビット dll しか必要ないため、explorer.exe を使用します)、dll が再帰的に自分自身を呼び出しているようです。

前述のように、私のコードとガイドのコードの主な違いは、コンソール ウィンドウの使用です。ガイドには次のように記載されています。

フックは User32.dll の DllMain で実行されるため、Kernel32.dll と Ntdll.dll からのみ関数を呼び出すことができます (他のライブラリはまだ初期化されていません)。

ただし、AllocConsole()WriteConsole()FreeConsole()、およびGetStdHandle()がすべて Kernel32.dll の一部であることを確認しました。

この DLL が自分自身を再帰的に呼び出すのはなぜですか? 継続的な呼び出しを確実に停止するにはどうすればよいですか、または再帰性を停止するには何を変更する必要がありますか?

別のメモとして、グローバルにフックされた DLL が再帰的に自分自身を呼び出すと、新しいコンソールがそれぞれ 2MB のメモリしか消費しない場合でも、私のコンピューターは RAM をすぐに使い果たします。XD

4

2 に答える 2

0

dll は再帰的に呼び出すことができます。これは OS 設計の一部です。まあ、彼らはそれをそのように設計しました。彼らは反対の誰かを約束したことはありません。あなたはこれと一緒に暮らす必要があります。

TLS スロット (TlsAlloc()/TlsFree などhttp://msdn.microsoft.com/en-us/library/windows/desktop/ms686801(v=vs.85).aspx ) を割り当て、それをマークすることをお勧めします。あなたのdllがそこに入力されます。このマークを使用すると、再帰を中断できます。

Windows 関数をフックした私自身の経験から、これがトリッキーなプロセスであることがわかります。ここでフォームを呼び出すと、これとこれを呼び出すことができますが、これは呼び出すことができません。どこから見ても絵が違います。これが人生です。

于 2013-07-14T07:02:01.487 に答える