Hook Com IFileOperation中的复制,剪切函数

这是我Hook Com IFileOperation口的DLL代码:
//IFileOPHook.h
#ifndef _H_IFILEOP_HOOK
#define _H_IFILEOP_HOOK
#ifdef __cplusplus
extern "C"
{
#endif
#include <windows.h>
typedef WCHAR WPATH[MAX_PATH];
enum OPTYPE
{
UNDEF = 0,
MOVE_FILE,
COPY_FILE,
DELETE_FILE,
NEW_FILE
};
typedef struct _FileOPItem
{
OPTYPE opType;
unsigned int srcCount;
WPATH* srcList;
WPATH dstFolder;
} FileOPItem, *PFileOPItem;
BOOL WINAPI HookIFileOp();
BOOL WINAPI UnhookIFileOp();
void WriteLog(char *fmt, ...);
#ifdef __cplusplus
}
#endif
#endif
// IFileOPHook.cpp
#include <shlwapi.h>
#include <shobjidl.h>
#include <stdio.h>
#include "IFileOPHook.h"
#pragma comment(lib, "shlwapi.lib")
#pragma warning(disable:4996)
static const IID CLSID_FileOperation = {0x3ad05575, 0x8857, 0x4850, {0x92, 0x77, 0x11, 0xb8, 0x5b, 0xdb, 0x8e, 0x09}};
static const IID IID_IFileOperation = {0x947aab5f, 0x0a5c, 0x4c13, {0xb4, 0xd6, 0x4b, 0xf7, 0x83, 0x6f, 0xc9, 0xf8}};
struct IFileOperation;
#define QueryInterface_Index 0
#define AddRef_Index (QueryInterface_Index + 1)
#define Release_Index (AddRef_Index + 1)
#define Advice_Index (Release_Index + 1)
#define Unadvise_Index (Advice_Index + 1)
#define SetOperationFlags_Index (Unadvise_Index + 1)
#define SetProgressMessage_Index (SetOperationFlags_Index + 1)
#define SetProgressDialog_Index (SetProgressMessage_Index + 1)
#define SetProperties_Index (SetProgressDialog_Index + 1)
#define SetOwnerWindow_Index (SetProperties_Index + 1)
#define ApplyPropertiesToItem_Index (SetOwnerWindow_Index + 1)
#define ApplyPropertiesToItems_Index (ApplyPropertiesToItem_Index + 1)
#define RenameItem_Index (ApplyPropertiesToItems_Index + 1)
#define RenameItems_Index (RenameItem_Index + 1)
#define MoveItem_Index (RenameItems_Index + 1)
#define MoveItems_Index (MoveItem_Index + 1)
#define CopyItem_Index (MoveItems_Index + 1)
#define CopyItems_Index (CopyItem_Index + 1)
#define DeleteItem_Index (CopyItems_Index + 1)
#define DeleteItems_Index (DeleteItem_Index + 1)
#define NewItem_Index (DeleteItems_Index + 1)
#define PerformOperations_Index (NewItem_Index + 1)
#define GetAnyOperationAborted_Index (PerformOperations_Index + 1)
typedef HRESULT (__stdcall* PCopyItems)(IFileOperation*, IUnknown*, IShellItem*);
typedef HRESULT (__stdcall* PMoveItems)(IFileOperation*, IUnknown*, IShellItem*);
typedef HRESULT (__stdcall* PPerformOperations)(IFileOperation*);
static PCopyItems CopyItems_old = NULL;
static PMoveItems MoveItems_old = NULL;
static PPerformOperations PerformOperations_old = NULL;
static BOOL gs_bHooked = FALSE;
static DWORD gs_opSlot = TLS_OUT_OF_INDEXES;
void WriteLog(char *fmt, ...)
{
FILE *fp;
va_list args;
if((fp = fopen("C:\\CopyAndMoveFile.log", "a+")) != NULL)
{
va_start(args,fmt);
vfprintf(fp, fmt, args);
fprintf(fp, "\n");
fclose(fp);
va_end(args);
}
}
static size_t WINAPI HookVtbl(void* pObject, size_t classIdx, size_t methodIdx, size_t newMethod)
{
size_t** vtbl = (size_t**)pObject;
DWORD oldProtect = 0;
size_t oldMethod = vtbl[classIdx][methodIdx];
VirtualProtect(vtbl[classIdx] + sizeof(size_t*) * methodIdx, sizeof(size_t*), PAGE_READWRITE, &oldProtect);
vtbl[classIdx][methodIdx] = newMethod;
VirtualProtect(vtbl[classIdx] + sizeof(size_t*) * methodIdx, sizeof(size_t*), oldProtect, &oldProtect);
return oldMethod;
}
static PFileOPItem GetOPItem()
{
if(!TlsGetValue(gs_opSlot))
{
PFileOPItem pfoi = new FileOPItem();
memset(pfoi->dstFolder, 0, MAX_PATH * sizeof(WCHAR));
pfoi->srcCount = 0;
pfoi->srcList = NULL;
pfoi->opType = UNDEF;
TlsSetValue(gs_opSlot, pfoi);
}
return (PFileOPItem)TlsGetValue(gs_opSlot);
}
static OPTYPE GetOPType()
{
return GetOPItem()->opType;
}
static void SetOPType(OPTYPE type)
{
GetOPItem()->opType = type;
}
// 获取一次文件操作中所有文件名
static UINT GetFilesFromDataObject(IUnknown *iUnknown, WPATH **ppPath)
{
UINT uFileCount = 0;
IDataObject *iDataObject = NULL;
HRESULT hr = iUnknown->QueryInterface(IID_IDataObject, (void **)&iDataObject);
do
{
if(!SUCCEEDED(hr))
{
break;
}
FORMATETC fmt = { CF_HDROP, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL };
STGMEDIUM stg = { TYMED_HGLOBAL };
if(!SUCCEEDED(iDataObject->GetData(&fmt, &stg)))
{
break;
}
HDROP hDrop = (HDROP)GlobalLock(stg.hGlobal);
if(hDrop == NULL)
{
break;
}
uFileCount = DragQueryFile(hDrop, 0xFFFFFFFF, NULL, 0);
if(uFileCount <= 0)
{
break;
}
*ppPath = new WPATH[uFileCount];
if(*ppPath != NULL)
{
for(UINT uIndex = 0; uIndex < uFileCount; uIndex++)
{
DragQueryFile(hDrop, uIndex, (*ppPath)[uIndex], MAX_PATH);
WriteLog("(*ppPath)[uIndex]=%s", (*ppPath)[uIndex]);
}
}
else
{
uFileCount = 0;
}
GlobalUnlock(stg.hGlobal);
ReleaseStgMedium(&stg);
} while (FALSE);
return uFileCount;
}
// 释放本线程的文件操作分配的内存
static void FreeOPItem()
{
PFileOPItem pfoi = GetOPItem();
if(pfoi->srcList)
{
delete[] pfoi->srcList;
pfoi->srcList = NULL;
}
pfoi->opType = UNDEF;
pfoi->srcCount = 0;
memset(pfoi->dstFolder, 0, MAX_PATH * sizeof(WCHAR));
}
static HRESULT __stdcall CopyItems_new(IFileOperation* pThis,
IUnknown* punkItems,
IShellItem* psiDestinationFolder)
{
LPWSTR lpDst = NULL;
psiDestinationFolder->GetDisplayName(SIGDN_FILESYSPATH, &lpDst);
HRESULT hr = S_FALSE;
PFileOPItem pfoi = GetOPItem();
do
{
OutputDebugStringA("COPY文件,从:");
OutputDebugStringW(lpDst);
char chDstFileName[256] = {0};
WideCharToMultiByte(CP_ACP, 0, lpDst, wcslen(lpDst) + 1, chDstFileName, 256, NULL, NULL);
WriteLog("CopyItems_new->lpDst:%s", chDstFileName);
pfoi->srcCount = GetFilesFromDataObject(punkItems, &(pfoi->srcList));
SetOPType(MOVE_FILE);
wcscpy(pfoi->dstFolder, lpDst);
hr = CopyItems_old(pThis, punkItems, psiDestinationFolder);
} while (FALSE);
if(!SUCCEEDED(hr))
{
FreeOPItem();
}
CoTaskMemFree(lpDst);
return hr;
}
static HRESULT __stdcall MoveItems_new(IFileOperation* pThis,
IUnknown* punkItems,
IShellItem* psiDestinationFolder)
{
LPWSTR lpDst = NULL;
psiDestinationFolder->GetDisplayName(SIGDN_FILESYSPATH, &lpDst);
HRESULT hr = S_FALSE;
PFileOPItem pfoi = GetOPItem();
do
{
OutputDebugStringA("MOVE文件,从:");
OutputDebugStringW(lpDst);
char chDstFileName[256] = {0};
WideCharToMultiByte(CP_ACP, 0, lpDst, wcslen(lpDst) + 1, chDstFileName, 256, NULL, NULL);
WriteLog("MoveItems_new->lpDst:%s", chDstFileName);
pfoi->srcCount = GetFilesFromDataObject(punkItems, &(pfoi->srcList));
SetOPType(MOVE_FILE);
wcscpy(pfoi->dstFolder, lpDst);
hr = MoveItems_old(pThis, punkItems, psiDestinationFolder);
} while (FALSE);
if(!SUCCEEDED(hr))
{
FreeOPItem();
}
CoTaskMemFree(lpDst);
return hr;
}
static HRESULT __stdcall PerformOperations_new(IFileOperation* pThis)
{
HRESULT hr = PerformOperations_old(pThis);
do
{
if(!SUCCEEDED(hr))
{
break;
}
OPTYPE type = GetOPType();
if(COPY_FILE != type && MOVE_FILE != type)
{
break;
}
OutputDebugStringA("确认文件操作。");
PFileOPItem pfoi = GetOPItem();
for(unsigned int i = 0; i < pfoi->srcCount; ++i)
{
WPATH dstPath;
wcscpy(dstPath, pfoi->dstFolder);
PathAddBackslashW(dstPath);
LPCWSTR tmp = (LPCWSTR)wcsrchr(pfoi->srcList[i], '\\');
wcscat(dstPath, ++tmp);
DWORD attrib = GetFileAttributesW(dstPath);
if(INVALID_FILE_ATTRIBUTES == attrib)
{
continue;
}
}
} while (FALSE);
FreeOPItem();
return hr;
}
BOOL WINAPI HookIFileOp()
{
WriteLog("Enter HookIFileOp");
void* pInterface = NULL;
CoInitialize(NULL);
HRESULT hr = CoCreateInstance(CLSID_FileOperation, NULL, CLSCTX_SERVER, IID_IFileOperation, &pInterface);
if(FAILED(hr))
{
return FALSE;
}
gs_opSlot = TlsAlloc();
if(TLS_OUT_OF_INDEXES == gs_opSlot)
{
return FALSE;
}
#define HOOK(a) \
a##_old = (P##a)HookVtbl(pInterface, 0, a##_Index, (size_t)a##_new); \
WriteLog("Before Hook CopyItems");
HOOK(CopyItems);
HOOK(MoveItems);
HOOK(PerformOperations);
WriteLog("Behind Hook PerformOperations");
#undef HOOK
return TRUE;
}
BOOL WINAPI UnhookIFileOp()
{
void* pInterface = NULL;
if(FAILED(CoCreateInstance(CLSID_FileOperation, NULL, CLSCTX_SERVER, IID_IFileOperation, &pInterface)))
{
return FALSE;
}
#define UNHOOK(a) \
if(a##_old) \
{ \
HookVtbl(pInterface, 0, a##_Index, (size_t)a##_old); \
} \
OutputDebugStringA("解HOOK");
UNHOOK(CopyItems);
UNHOOK(MoveItems);
UNHOOK(PerformOperations);
WriteLog("Behind unHook PerformOperations");
#undef UNHOOK
if(TLS_OUT_OF_INDEXES != gs_opSlot)
{
TlsFree(gs_opSlot);
gs_opSlot = TLS_OUT_OF_INDEXES;
}
return TRUE;
}

DLL模块还有一个文件,我接下来会上传

问题点数:2分

0 0

引用 ・ 举报 ・ 管理

CSDN推荐

CSDN今日推荐

文科升

Bbs1

回复于 2012-08-08 16:34:26 #1 得分:0

这是我DLL模块中的另外一个源文件:
//main.cpp
#include <windows.h>
#include "ifileophook.h"
#define IEQUALW(str1, str2) (str1 && str2 && (0 == wcsicmp(str1, str2)))
#pragma warning(disable:4996)
#pragma comment(linker, "/Section:.shared,RWS")
#pragma data_seg(".shared")
HHOOK g_oldHook = NULL; // CallNextHook
#pragma data_seg()
HMODULE g_hThisModule = 0; // 本模块句柄
static BOOL gs_bHooked = FALSE; // 是否HOOK
BOOL WINAPI IsProcessW(LPCWSTR procName)
{
wchar_t path[MAX_PATH] = {0};
GetModuleFileNameW(0, path, MAX_PATH);
wchar_t* tmp = (wchar_t*)wcsrchr(path, L'\\');
if(!tmp)
{
WriteLog("tmp is null and path:%s", path);
return FALSE;
}
tmp++;
return IEQUALW(tmp, procName);
}
void OnLoadDll()
{
if(IsProcessW(L"explorer.exe"))
{
WriteLog("IsProcessW(explorer.exe) success");
OutputDebugStringA("HOOK explorer.exe 的 IFileOperation");
gs_bHooked = HookIFileOp();
}
}
void OnFreeDll()
{
if(gs_bHooked)
{
OutputDebugStringA("解 explorer.exe 的HOOK");
UnhookIFileOp();
}
}
BOOL APIENTRY DllMain(HANDLE handle, DWORD dwReason, LPVOID reserved)
{
g_hThisModule = (HMODULE)handle;
switch(dwReason)
{
case DLL_PROCESS_ATTACH:
{
DisableThreadLibraryCalls(g_hThisModule);
OnLoadDll();
break;
}
case DLL_PROCESS_DETACH:
{
OnFreeDll();
break;
}
}
return TRUE;
}
LRESULT CALLBACK GlobalCBTHook(int nCode, WPARAM w, LPARAM l)
{
if(g_oldHook)
{
return CallNextHookEx(g_oldHook, nCode, w, l);
}
return 0;
}
BOOL WINAPI InstallGlobalHook()
{
g_oldHook = SetWindowsHookEx(WH_CBT, GlobalCBTHook, g_hThisModule, 0);
return TRUE;
}
void WINAPI UninstallGlobalHook()
{
if(g_oldHook)
{
UnhookWindowsHookEx(g_oldHook);
}
}
LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM w, LPARAM l)
{
if(WM_DESTROY == msg)
{
PostQuitMessage(0);
}
return DefWindowProcA(hWnd, msg, w, l);
}
void WINAPI EnterMessageLoop()
{
do
{
WNDCLASSEXA wcex = {sizeof(wcex)};
wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = (WNDPROC)WndProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = g_hThisModule;
wcex.hIcon = LoadIcon(NULL, IDI_INFORMATION);
wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
wcex.lpszClassName = "proclimitwnd";
if(!RegisterClassExA(&wcex))
{
break;
}
HWND hWnd = CreateWindowExA(0, "proclimitwnd", NULL, WS_OVERLAPPEDWINDOW,
0, 0, 50, 50, NULL, NULL, g_hThisModule, NULL);
if(!IsWindow(hWnd))
{
break;
}
UpdateWindow(hWnd);
MSG msg;
while(GetMessage(&msg, hWnd, 0, 0))
{
TranslateMessage(&msg);
DispatchMessageA(&msg);
}
} while (FALSE);
}
// 进入注入模式
__declspec(dllexport) void WINAPI EnterInjectMode()
{
if(!InstallGlobalHook())
{
return;
}
if(IsProcessW(L"rundll32.exe"))
{
EnterMessageLoop();
}
}

0 0

引用 ・ 举报 ・ 管理

文科升

Bbs1

回复于 2012-08-08 16:36:11 #2 得分:0

上面的DLL程序,编译一切正常,最后生成了fotracker.dll文件 。

这是我的EXE程序的代码:
#include "stdafx.h"
#include <Windows.h>
#include <atlstr.h>
typedef void (WINAPI *HOOKAPI)();
HINSTANCE hHookDllL;
HOOKAPI  m_hookProc;
int _tmain(int argc, _TCHAR* argv[])
{
//安装钩子
hHookDllL = LoadLibraryA("fotracker.dll");
m_hookProc = (HOOKAPI)GetProcAddress(hHookDllL,"EnterInjectMode"); //get pointer of proc
if (!m_hookProc)
{
CString str;
str.Format(_T("GetProcAddress(InstallHookProc) FAILED! ErrorCode: %d"),GetLastError());
OutputDebugString(str);
}
else
{
m_hookProc();
MessageBox(NULL, _T("安装钩子成功!"), _T("操作提示"), 0);
//卸载钩子
if(hHookDllL)
{
FreeLibrary(hHookDllL);
hHookDllL = NULL;
}
}
return 0;
}

0 0

引用 ・ 举报 ・ 管理

文科升

Bbs1

回复于 2012-08-08 16:42:06 #3 得分:0

现在我遇到的问题是,当我的EXE执行
m_hookProc();
MessageBox(NULL, _T("安装钩子成功!"), _T("操作提示"), 0);
执行这代码后,设置断点,这是我在电脑中,做些复制,剪切的操作,可是我的日志文件里没有这些相关日志,只有OnLoadDll();执行后的几条日志,


if(IsProcessW(L"explorer.exe"))
{
   WriteLog("IsProcessW(explorer.exe) success");
   OutputDebugStringA("HOOK explorer.exe 的 IFileOperation");
   gs_bHooked = HookIFileOp();
}

也就是执行到IsProcessW(L"explorer.exe"),执行该函数后,条件不成立,程序就退出了,而且该函数只执行了3次。

猜你喜欢

转载自blog.csdn.net/bruce135lee/article/details/81388536