私の目標は、ファイルの動きを弱く監視することです。グローバル フックを作成するための非常に簡単なガイドを見つけて、問題なく動作するようにしました (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