我的目标是弱监控文件移动。我找到了一个非常简单的指南来创建一个全局钩子并让它工作得很好(注意需要编译 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 并重新启动进程后(通常是 explorer.exe,因为它非常简单,只需要 64 位 dll),我的 dll 似乎递归地调用自己。
如前所述,我的代码与指南的代码之间的主要区别在于控制台窗口的使用。该指南确实指出:
由于挂钩是在 User32.dll 的 DllMain 中执行的,因此您只能从 Kernel32.dll 和 Ntdll.dll 调用函数(其他库尚未初始化)。
但是我已经验证AllocConsole()、WriteConsole()、FreeConsole()和GetStdHandle()都是 Kernel32.dll 的一部分。
为什么这个DLL递归调用自己?我将如何确保停止任何继续调用,或者我应该改变什么来停止递归?
另一方面,当全局挂钩的 DLL 递归调用自身时,我的计算机会很快耗尽 RAM,即使每个新控制台只消耗 2MB 内存。XD