我的目标是弱监控文件移动。我找到了一个非常简单的guide来创建一个全局钩子并让它工作得很好(注意需要编译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以递归方式调用自身?我如何确保停止任何继续通话,或者我应该改变什么以阻止递归?
另一方面,即使每个新控制台仅消耗2MB内存,当全局挂钩的DLL递归调用自身时,我的计算机也会很快耗尽RAM。 XD
答案 0 :(得分:0)
你的dll可以递归调用。这是OS设计的一部分。好吧,他们设计了它。他们从来没有向任何人承诺。你必须忍受这个。
我建议你分配TLS插槽(TlsAlloc()/ TlsFree等http://msdn.microsoft.com/en-us/library/windows/desktop/ms686801(v=vs.85).aspx)并标记你的dll是在那里输入的。使用此标记可以打破递归。
我自己在挂钩Windows功能方面的经验表明,这是一个棘手的过程。在这里形成你可以打电话给这个,但不是这个。从其他地方看,情况就不同了。这就是生活。
答案 1 :(得分:0)
资源管理器未使用Copyfile。它使用CopyFileEx,因为它有一个进度回调例程来更新传输状态。在修补呼叫时发生挂起。在dllmain&创建一个线程。对线程例程进行修补。 挂钩是无证的&监视文件移动的不可靠方法。 Windows有minifilter文件系统管理器,您可以在其中注册回调&获取有关文件事件的通知。通过这种方式,您可以拥有坚如磐石的生产代码。