2013-07-02 44 views
1

我的目標是監視文件運動。我發現一個非常簡單的guide來創建一個全局鉤子,並讓它工作得很好(注意需要編譯64位和32位版本,並將它們放在不同的註冊表位置)。作爲一項個人練習,我想勾選CopyFile(從MoveFile,CreateFile和其他所有變體中隨機選擇)。遵循指南中的完全相同的程序,我找到了這個非常短的代碼。掛鉤的CopyFile Kernel32.dll中,使遞歸實例

#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遞歸調用自身時,我的計算機也會很快耗盡內存。 XD

+0

您是否禁用了Windows的頁面文件? –

+0

這會讓我的dll崩潰,當我耗盡內存,而不是讓我跑到開放控制檯看看誰更快,但我認爲這不會解決主要問題,並禁用它似乎是一個[壞主意] (HTTP:// Lifehacker的。COM/5426041 /瞭解-的窗口,頁面文件和 - 爲什麼 - 你 - 不應該 - 禁用 - 它)。 – Suedocode

+0

您正在爲'lpNumberOfCharsWritten'參數傳遞'WriteConsole'的空指針。我不知道這是否會導致您遇到的問題,但文檔沒有說這個參數可以爲空,所以我會先從這個開始。 –

回答

0

您的DLL可以遞歸調用。這是操作系統設計的一部分。那麼,他們是這麼設計的。他們從未答應任何人對面。你必須忍受這一點。

我會建議你分配TLS插槽(TlsAlloc()/ TlsFree等http://msdn.microsoft.com/en-us/library/windows/desktop/ms686801(v=vs.85).aspx)並標記你的dll是在那裏輸入的。使用這個標記你可以打破遞歸。

在掛鉤Windows功能我自己的經驗表明,這是一個棘手的過程。在這裏你可以調用這個和這個,但不是這個。從別的地方來看,圖片是不同的。這就是生活。

0

的CopyFile不使用資源管理器。它使用CopyFileEx,因爲它有一個進度回調例程來更新傳輸狀態。掛斷電話時正在發生掛機。在dllmain上創建一個線程&在線程例程上進行修補。 掛鉤是無證的&不可靠的方法來監視文件移動。 Windows有微過濾文件系統管理器,您可以在其中註冊回調&獲取有關文件事件的通知。通過這種方式,您可以擁有堅如磐石的生產代碼。