// dllmain.cpp : DllMain 的实现。 CFileWatchDllModule _AtlModule; //保存原函数的地址,对于不需要保护的程序,调用原函数 PVOID g_pOldSHFileOperationW=NULL; PVOID g_pOldSHFileOperationA=NULL; // SHFileOperation 函数 win7以前系统删除文件均通过该函数 typedef int (WINAPI *PfuncOldSHFileOperationA)(LPSHFILEOPSTRUCTA lpFileOp); typedef int (WINAPI *PfuncOldSHFileOperationW)(LPSHFILEOPSTRUCTW lpFileOp); // 需要挂钩的程序 int WINAPI ZwNewSHFileOperationA(LPSHFILEOPSTRUCTA lpFileOp); int WINAPI ZwNewSHFileOperationW(LPSHFILEOPSTRUCTW lpFileOp); int WINAPI ZwNewSHFileOperationW(LPSHFILEOPSTRUCTW lpFileOp) { //自己的拦截逻辑,直接拦截返回false ,否则返回原函数调用 return ((PfuncOldSHFileOperationW)g_pOldSHFileOperationW)(lpFileOp);//不是需要保护的文件 放行 } int WINAPI ZwNewSHFileOperationA(LPSHFILEOPSTRUCTA lpFileOp) { //自己的拦截逻辑,直接拦截返回false ,否则返回原函数调用 return ((PfuncOldSHFileOperationA)g_pOldSHFileOperationA)(lpFileOp); } //安装Hook BOOL WINAPI SetHookOnSHFileOperation() { DetourTransactionBegin(); DetourUpdateThread(GetCurrentThread());//得到当前线程 g_pOldSHFileOperationW=DetourFindFunction("shell32.dll","SHFileOperationW");//查询函数地址 g_pOldSHFileOperationA=DetourFindFunction("shell32.dll","SHFileOperationA"); DetourAttach(&g_pOldSHFileOperationW, ZwNewSHFileOperationW);//挂钩函数 DetourAttach(&g_pOldSHFileOperationA, ZwNewSHFileOperationA); LONG ret=DetourTransactionCommit();//提交更改 return ret==NO_ERROR; } //卸载Hook BOOL WINAPI DropHookOnSHFileOperation() { DetourTransactionBegin(); DetourUpdateThread(GetCurrentThread()); DetourDetach(&g_pOldSHFileOperationW, ZwNewSHFileOperationW); DetourDetach(&g_pOldSHFileOperationA, ZwNewSHFileOperationA); LONG ret=DetourTransactionCommit(); return ret==NO_ERROR; } static HMODULE s_hDll; HMODULE WINAPI Detoured() { return s_hDll; } // DLL 入口点 extern "C" BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved) { (void)lpReserved; switch(dwReason) { case DLL_PROCESS_ATTACH: s_hDll = hInstance; DisableThreadLibraryCalls(hInstance); SetHookOnSHFileOperation();//HOOK break; case DLL_THREAD_ATTACH: break; case DLL_PROCESS_DETACH: DropHookOnSHFileOperation();//UNHOOK break; case DLL_THREAD_DETACH: break; } return _AtlModule.DllMain(dwReason, lpReserved); }
下面以2003的服务器来实验
将原程序编译为dll文件 我的编译出来是FileWatchDll.dll
cmd 运行regedit
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Windows
AppInit_DLLs=改为(dll文件所在路径)\FileWatchDll.dll,所有进程加载时预先加载这个dll
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Windows
LoadAppInit_DLLs=1 是否(1/0)加载AppInit_DLLs中设置的dll
重新器动后,当删除受监控的文件时弹出警告框,然后无法删除该文件