首页
论坛
课程
招聘
[原创]用VC SDK实现的ICopyHook和IShellExecuteHook接口
2013-1-17 14:34 15121

[原创]用VC SDK实现的ICopyHook和IShellExecuteHook接口

2013-1-17 14:34
15121
反正代码不多,就直接贴出来算了,有不对的大家请多多指教
该程序是个Shell扩展,使用regsvr32注册,使用regsvr32 /u取消注册
ICopyHook就是监视目录复制的,IShellExecuteHook就是监视程序执行,在这个程序里面我把他们两个都实现了

/********************CopyHook.def********************/
LIBRARY "CopyHook.dll"
EXPORTS
	DllGetClassObject PRIVATE
	DllRegisterServer PRIVATE
	DllUnregisterServer PRIVATE
	DllCanUnloadNow PRIVATE


/********************DllMain.cpp********************/
#include <Windows.h>
#include <Stdio.h>
#include <Tchar.h>
#include <Shlobj.h>
#include <InitGuid.h>

#include "ShellHook.h"
#include "ShellHookFactory.h"

HMODULE 		g_hinst;
ULONG			g_lLockNumber;
ULONG			g_lRefThisDll;

HRESULT ClsidToString(REFCLSID clsid, LPTSTR lpszClsid, int cchClsid)
{
	HRESULT				result;
	LPWSTR				lpszStr;

	if((result = StringFromCLSID(clsid, &lpszStr)) == S_OK)
	{
#ifdef UNICODE
		lstrcpyn(lpszClsid, lpszStr, cchClsid);
#else
		WideCharToMultiByte(CP_OEMCP, 0, lpszStr, -1, lpszClsid, cchClsid, 0, 0);
#endif

		CoTaskMemFree(lpszStr);	
	}

	return result;
}

HRESULT RegisterClsid(LPTSTR lpszClsid, LPTSTR lpszModule)
{
	HKEY				hKey;
	HKEY				hSubKey;
	TCHAR				szSubKey[1024];
	TCHAR				szModel[] = _T("Apartment");
	LSTATUS				status;
	
	lstrcpy(szSubKey, _T("CLSID\\"));
	lstrcat(szSubKey, lpszClsid);
	status = RegCreateKey(HKEY_CLASSES_ROOT, szSubKey, &hKey);
	if(status == ERROR_SUCCESS)
	{
		status = RegCreateKey(hKey, _T("InProcServer32"), &hSubKey);
		if(status == ERROR_SUCCESS)
		{
			RegSetValue(hSubKey, NULL, REG_SZ, lpszModule, 0);
			RegSetValueEx(hSubKey, _T("ThreadingModel"), 0, REG_SZ, (BYTE*)szModel, sizeof(szModel));
			RegCloseKey(hSubKey);
		}
		RegCloseKey(hKey);
	}

	return HRESULT_FROM_WIN32(status);
}

HRESULT UnRegisterClsid(LPTSTR lpszClsid)
{
	TCHAR				szSubKey[1024];
	LSTATUS				status;
	
	lstrcpy(szSubKey, _T("CLSID\\"));
	lstrcat(szSubKey, lpszClsid);
	lstrcat(szSubKey, _T("\\InProcServer32"));
	status = RegDeleteKey(HKEY_CLASSES_ROOT, szSubKey);

	lstrcpy(szSubKey, _T("CLSID\\"));
	lstrcat(szSubKey, lpszClsid);
	status = RegDeleteKey(HKEY_CLASSES_ROOT, szSubKey);

	return HRESULT_FROM_WIN32(status);
}

STDAPI DllGetClassObject (const CLSID &rclsid, const IID &riid, void **ppv)
{
	if (rclsid == CLSID_MyShellHook) 
	{		
		CMyShellHookFactory *pFactory = new CMyShellHookFactory;

		if (pFactory == NULL)
			return E_OUTOFMEMORY ;
		
		return pFactory->QueryInterface(riid, ppv);
	}

	return CLASS_E_CLASSNOTAVAILABLE;
}

STDAPI DllCanUnloadNow (void)
{
	if (g_lRefThisDll == 0 && g_lLockNumber == 0)
		return S_OK;
	else
		return S_FALSE;
}

STDAPI DllRegisterServer ()
{
	TCHAR				szClsid[64];
	TCHAR				szModule[MAX_PATH];
	HKEY				hKey;
	
	ClsidToString(CLSID_MyShellHook, szClsid, 64);
		
	if(RegCreateKey(HKEY_CLASSES_ROOT, _T("Directory\\shellex\\CopyHookHandlers\\zCopyHook"), &hKey) == ERROR_SUCCESS)
	{
		RegSetValue(hKey, NULL, REG_SZ, szClsid, 0);
		RegCloseKey(hKey);		
	}	
	if(RegOpenKey(HKEY_LOCAL_MACHINE, _T("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\ShellExecuteHooks"), &hKey) == ERROR_SUCCESS)
	{
		RegSetValueEx(hKey, szClsid, 0, REG_SZ, NULL, 0);
		RegCloseKey(hKey);		
	}
	if(RegOpenKey(HKEY_LOCAL_MACHINE, _T("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Policies\\Explorer"), &hKey) == ERROR_SUCCESS)
	{
		DWORD		dwVal = 1;
		RegSetValueEx(hKey, _T("EnableShellExecuteHooks"), 0, REG_DWORD, (LPBYTE)&dwVal, sizeof(DWORD));
		RegCloseKey(hKey);		
	}
	
	GetModuleFileName(g_hinst, szModule, MAX_PATH);
	return RegisterClsid(szClsid, szModule);
}

STDAPI DllUnregisterServer ()
{
	TCHAR				szClsid[64];
	HKEY				hKey;
	
	ClsidToString(CLSID_MyShellHook, szClsid, 64);

	RegDeleteKey(HKEY_CLASSES_ROOT, _T("Directory\\shellex\\CopyHookHandlers\\zCopyHook"));
	if(RegOpenKey(HKEY_LOCAL_MACHINE, _T("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\ShellExecuteHooks"), &hKey) == ERROR_SUCCESS)
	{
		RegDeleteValue(hKey, szClsid);
		RegCloseKey(hKey);		
	}
	if(RegOpenKey(HKEY_LOCAL_MACHINE, _T("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Policies\\Explorer"), &hKey) == ERROR_SUCCESS)
	{
		RegDeleteValue(hKey, _T("EnableShellExecuteHooks"));
		RegCloseKey(hKey);		
	}

	return UnRegisterClsid(szClsid);
}

BOOL WINAPI DllMain (HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
{
	switch(fdwReason)
	{
	case DLL_PROCESS_ATTACH://加载dll;
		{
			g_hinst = hinstDLL;
			
		}
		break;
	case DLL_PROCESS_DETACH://释放dll
		{
		}
		break;
	case DLL_THREAD_ATTACH://新建线程
		{
		}
		break;
	case DLL_THREAD_DETACH://线程退出
		{
		}
		break;
	}

	return TRUE;
}



/********************ShellHookFactory.h********************/

class CMyShellHookFactory : public IClassFactory
{
public:
	CMyShellHookFactory();
	~CMyShellHookFactory();
	
	HRESULT STDMETHODCALLTYPE QueryInterface (REFIID iid, void **ppvObject);
	ULONG STDMETHODCALLTYPE AddRef ();
	ULONG STDMETHODCALLTYPE Release ();

	HRESULT STDMETHODCALLTYPE CreateInstance (IUnknown *pUnkOuter, REFIID riid, void **ppvObject);
	HRESULT STDMETHODCALLTYPE LockServer (BOOL fLock);
private:
	ULONG			m_lRefCount;
};



/********************ShellHookFactory.cpp********************/
#include <Windows.h>
#include <Stdio.h>
#include <Tchar.h>
#include <Shlobj.h>
#include <InitGuid.h>

#include "ShellHook.h"
#include "ShellHookFactory.h"

extern ULONG			g_lLockNumber;
extern ULONG			g_lRefThisDll;

CMyShellHookFactory::CMyShellHookFactory() : m_lRefCount(0)
{
}

CMyShellHookFactory::~CMyShellHookFactory()
{
}


HRESULT STDMETHODCALLTYPE CMyShellHookFactory::QueryInterface (REFIID iid, void **ppvObject)
{
	if(iid == IID_IUnknown)
	{
		m_lRefCount++;
		*ppvObject = this;
	}
	else if(iid == IID_IClassFactory)
	{
		m_lRefCount++;
		*ppvObject = this;
	}
	else
	{
		*ppvObject = NULL;
		return E_NOINTERFACE;
	}

	return S_OK;
}

ULONG STDMETHODCALLTYPE CMyShellHookFactory::AddRef ()
{
	m_lRefCount++;
	return m_lRefCount;
}

ULONG STDMETHODCALLTYPE CMyShellHookFactory::Release ()
{
	m_lRefCount--;

	if(m_lRefCount == 0)
		delete this;

	return m_lRefCount;
}


HRESULT STDMETHODCALLTYPE CMyShellHookFactory::CreateInstance(IUnknown *pUnkOuter, REFIID riid, void **ppvObject)
{
	CMyShellHook		*pObj;

	*ppvObject = NULL;	
	if(pUnkOuter)
		return CLASS_E_NOAGGREGATION;

	pObj = new CMyShellHook();

	if (pObj == NULL)
		return E_OUTOFMEMORY ;

	return pObj->QueryInterface(riid, ppvObject);
}

HRESULT STDMETHODCALLTYPE CMyShellHookFactory::LockServer(BOOL fLock)
{
	if(fLock)
		g_lLockNumber++;
	else
		g_lLockNumber--;

	return NOERROR;
}


/********************ShellHook.h********************/

//{24c7f2bb-3f48-42eb-9d6f-81b756ea15ba}
DEFINE_GUID(CLSID_MyShellHook, 0x24c7f2bb, 0x3f48, 0x42eb, 0x9d, 0x6f, 0x81, 0xb7, 0x56, 0xea, 0x15, 0xba);

class CMyShellHook : public ICopyHook, public IShellExecuteHook
{
public:
	CMyShellHook();
	~CMyShellHook();
	
	HRESULT STDMETHODCALLTYPE QueryInterface (REFIID iid, void **ppvObject);
	ULONG STDMETHODCALLTYPE AddRef ();
	ULONG STDMETHODCALLTYPE Release ();

	UINT STDMETHODCALLTYPE CopyCallback (HWND hwnd, UINT wFunc, UINT wFlags, LPCTSTR pszSrcFile, DWORD dwSrcAttribs,
		LPCTSTR pszDestFile, DWORD dwDestAttribs);

	HRESULT STDMETHODCALLTYPE Execute (LPSHELLEXECUTEINFO pei);
private:
	ULONG			m_lRefCount;
};



/********************ShellHook.cpp********************/
#include <Windows.h>
#include <Stdio.h>
#include <Tchar.h>
#include <Shlobj.h>
#include <InitGuid.h>

#include "ShellHook.h"

extern ULONG			g_lLockNumber;
extern ULONG			g_lRefThisDll;

CMyShellHook::CMyShellHook() : m_lRefCount(0)
{
	g_lRefThisDll++;
}

CMyShellHook::~CMyShellHook()
{
	g_lRefThisDll--;
}


HRESULT STDMETHODCALLTYPE CMyShellHook::QueryInterface (REFIID iid, void **ppvObject)
{
	if(iid == IID_IUnknown)
	{
		m_lRefCount++;
		*ppvObject = this;
	}
	else if(iid == IID_IShellCopyHook)
	{
		m_lRefCount++;
		*ppvObject = (ICopyHook *)this;
	}
	else if(iid == IID_IShellExecuteHook)
	{
		m_lRefCount++;
		*ppvObject = (IShellExecuteHook *)this;
	}
	else
	{
		*ppvObject = NULL;
		return E_NOINTERFACE;
	}

	return S_OK;
}

ULONG STDMETHODCALLTYPE CMyShellHook::AddRef ()
{
	m_lRefCount++;
	return m_lRefCount;
}

ULONG STDMETHODCALLTYPE CMyShellHook::Release ()
{
	m_lRefCount--;

	if(m_lRefCount == 0)
		delete this;

	return m_lRefCount;
}


UINT STDMETHODCALLTYPE CMyShellHook::CopyCallback (HWND hwnd, UINT wFunc, UINT wFlags, LPCTSTR pszSrcFile, DWORD dwSrcAttribs,
		LPCTSTR pszDestFile, DWORD dwDestAttribs)
{
	TCHAR				szMsg[1024];
	
	wsprintf(szMsg, _T("是否允许将目录从 %s 复制文件到 %s ?"), pszSrcFile, pszDestFile);
	return MessageBox(NULL, szMsg, _T("提示"), MB_YESNO | MB_ICONQUESTION| MB_SETFOREGROUND);
}


HRESULT STDMETHODCALLTYPE CMyShellHook::Execute (LPSHELLEXECUTEINFO pei)
{
	TCHAR				szMsg[1024];
	
	wsprintf(szMsg, _T("是否允许执行 %s %s ?"), pei->lpFile, pei->lpParameters);
	return (MessageBox(NULL, szMsg, _T("提示"), MB_YESNO | MB_ICONQUESTION | MB_SETFOREGROUND) == IDYES) ? S_FALSE : S_OK;
}


顺便附上源码,我是64位win7的,在我的电脑上正常运行

[注意] 欢迎加入看雪团队!base上海,招聘安全工程师、逆向工程师多个坑位等你投递!

上传的附件:
收藏
点赞0
打赏
分享
最新回复 (14)
雪    币: 266
活跃值: 活跃值 (47)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
Captains 活跃值 2013-1-17 23:44
2
0
如果是文件监控的话 ReadDirectoryChangesW 也不错
雪    币: 142
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
xiejienet 活跃值 2013-1-18 01:28
3
0
第一次看到用sdk做这个,试着新建一个工程,结果发现编译出来的怎么都不对,导出函数都看不到.
我不知道哪里做错了,楼主能把工程也打个包上来不?
雪    币: 142
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
xiejienet 活跃值 2013-1-18 10:13
4
0
早上又试了下,原来是def文件没设置对,只是简单的添加def文件是不行的,还得在工程设置里指定这个def文件.
附上可编译的工程
上传的附件:
雪    币: 123
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
woaixj 活跃值 2013-1-27 13:34
5
0
谢谢分享,学习了,同样喜欢SDK
雪    币: 2039
活跃值: 活跃值 (1081)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
caolinkai 活跃值 2013-1-28 13:08
6
0
thanks..........
雪    币: 78
活跃值: 活跃值 (10)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
ronging 活跃值 2013-1-28 17:01
7
0
ICopyHook这个接口是干嘛用的?资源管理器会加载到?
雪    币: 731
活跃值: 活跃值 (11)
能力值: ( LV9,RANK:260 )
在线值:
发帖
回帖
粉丝
wertyuyuyu 活跃值 4 2013-4-11 15:36
8
0
嗯,就是监视目录复制的
雪    币: 33
能力值: (RANK:10 )
在线值:
发帖
回帖
粉丝
xwfz 活跃值 2013-4-12 10:47
9
0
前端时间还有人利用这个注入EXP添加启动呢!
雪    币: 203
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
小吴 活跃值 2013-8-20 09:00
10
0
楼主是用vs2010建的工程,我用vs2008新建工程编译后,出现如下错误:
error C2504: “IShellExecuteHook”: 未定义基类
error C2061: 语法错误 : 标识符“LPSHELLEXECUTEINFO”
有人知道为什么吗
雪    币: 199
活跃值: 活跃值 (748)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
appview 活跃值 2014-4-28 14:40
11
0
感谢分享!
雪    币: 199
活跃值: 活跃值 (748)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
appview 活跃值 2014-4-28 14:54
12
0
32位 Win7 SP1为什么没效果呢
雪    币: 1
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
kan看code 活跃值 2017-7-1 15:08
13
0
楼主,为什么我注册了你的dll,文件夹复制没有反应的(已重启explorer.exe,电脑也重启过,确认注册信息已写到注册表中);请告知如何操作(或者是我忘记了哪些操作)才会使文件复制弹出提示对话框,感激不尽!
雪    币: 2
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
wx_周围 活跃值 2017-9-7 16:20
14
0
下面的问题,是MS的一个BUG。可以手工修改ShlObj.h文件,在“#include  <shobjidl.h>”后面加一行“#include  <shellapi.h>”
  “IShellExecuteHook”:  未定义基类
雪    币: 2
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
wx_周围 活跃值 2017-9-7 17:08
15
0
没有反应的,建议注意一下32位和64位。软件在不同的OS里运行要编译不同的版本
游客
登录 | 注册 方可回帖
返回