1、新建名称为CServerHook的MFC动态库,选择MFC扩展DLL选项,点击完成。
2、系统自动生成ServerHook.cpp文件,但没有ServerHook.h文件,该文件需要手动添加。
3、建立导出类CServerHook,ServerHook.h文件内容如下:
BOOL _declspec(dllexport) CALLBACK EnumWindowsProc(HWND hwnd, LPARAM lParam);枚举窗口回调函数
void _declspec(dllexport) gKillProcessByPid( DWORD dwPid );//根据进程ID销毁该进程
void _declspec(dllexport) gGetProcessByWindowTitle();//枚举窗口名称,得到对应进程Id
void _declspec(dllexport) gSetFilePath(char* strPath); //向dll中传递路径
void _declspec(dllexport) gSetTimer(); //在dll中创建Timer
class __declspec(dllexport) CServerHook : public CObject
{
public:
CServerHook(); //钩子类的构造函数
virtual ~CServerHook(); //钩子类的析构函数
public:
BOOL StartHook(); //安装钩子函数
BOOL StopHook(); //卸载钩子函数
};
4、ServerHook.cpp文件内容如下:
#include "stdafx.h"
#include <afxdllx.h>
#include "ServerHook.h"
#define _WIN32_WINNT 0x0500
#include <windows.h>
#include <stdio.h>
#define _SECOND 10000000
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
#pragma data_seg("mydata")
HHOOK glhHook=NULL; //安装的键盘勾子句柄
HINSTANCE glhInstance=NULL; //DLL实例句柄
char last_char ='q';
char g_chArr[MAX_PATH] = {0}; //保存传递进来的程序相对路径
#pragma data_seg()
LRESULT CALLBACK KeyboardProc(int nCode,WPARAM wParam,LPARAM lParam);
static AFX_EXTENSION_MODULE ServerHookDLL = { NULL, NULL };
CString g_szCurPath = _T("");
CString g_strFlashMagazine = _T("");
CString g_strFlashDM = _T("");
DWORD wndTemp = 0;
int iFlag = 0;
HWND hwnd;
HWND m_hwndFind[100] = { NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,
NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,
NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,
NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,
NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,
NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,
NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,
NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,
NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,
NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL};
int m_num = 0 ;
TCHAR m_store[MAX_PATH];
typedef struct _MYTimer {
TCHAR *szText;
DWORD dwValue;
} MYTIMER;
VOID CALLBACK TimerAPCProc(
LPVOID lpArg, // Data value
DWORD dwTimerLowValue, // Timer low value
DWORD dwTimerHighValue ) // Timer high value
{
MYTIMER *pMyData = (MYTIMER *)lpArg;
printf( "Message: %s/nValue: %d/n/n", pMyData->szText,
pMyData->dwValue );
MessageBeep(0);
}
extern "C" int APIENTRY
DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved)
{
// Remove this if you use lpReserved
UNREFERENCED_PARAMETER(lpReserved);
if (dwReason == DLL_PROCESS_ATTACH)
{
TRACE0("SERVERHOOK.DLL Initializing!/n");
// Extension DLL one-time initialization
if (!AfxInitExtensionModule(ServerHookDLL, hInstance))
return 0;
// Insert this DLL into the resource chain
// NOTE: If this Extension DLL is being implicitly linked to by
// an MFC Regular DLL (such as an ActiveX Control)
// instead of an MFC application, then you will want to
// remove this line from DllMain and put it in a separate
// function exported from this Extension DLL. The Regular DLL
// that uses this Extension DLL should then explicitly call that
// function to initialize this Extension DLL. Otherwise,
// the CDynLinkLibrary object will not be attached to the
// Regular DLL's resource chain, and serious problems will
// result.
new CDynLinkLibrary(ServerHookDLL);
glhInstance=hInstance;
}
else if (dwReason == DLL_PROCESS_DETACH)
{
TRACE0("SERVERHOOK.DLL Terminating!/n");
// Terminate the library before destructors are called
AfxTermExtensionModule(ServerHookDLL);
}
return 1; // ok
}
CServerHook::CServerHook()
{
}
CServerHook::~CServerHook()
{
if (glhHook)
{
UnhookWindowsHookEx(glhHook);
}
}
BOOL CServerHook::StartHook()
{
BOOL bResult=FALSE;
glhHook=SetWindowsHookEx(WH_KEYBOARD,KeyboardProc,glhInstance,0);
/*============================================================
HHOOK SetWindowsHookEx( int idHook,HOOKPROC lpfn, INSTANCE hMod,DWORD dwThreadId )
参数idHook表示钩子类型,它是和钩子函数类型一一对应的。
比如,WH_KEYBOARD表示安装的是键盘钩子,WH_MOUSE表示是鼠标钩子等等。
Lpfn是钩子函数的地址。
HMod是钩子函数所在的实例的句柄。对于线程钩子,该参数为NULL;对于系统钩子,
该参数为钩子函数所在的DLL句柄。
dwThreadId 指定钩子所监视的线程的线程号。对于全局钩子,该参数为NULL。
SetWindowsHookEx返回所安装的钩子句柄。
值得注意的是线程钩子和系统钩子的钩子函数的位置有很大的差别。
线程钩子一般在当前线程或者当前线程派生的线程内,
而系统钩子必须放在独立的动态链接库中,实现起来要麻烦一些。
===========================================================*/
if(glhHook!=NULL)
bResult=TRUE;
return bResult;
}
//卸载钩子
BOOL CServerHook::StopHook()
{
BOOL bResult=FALSE;
if(glhHook)
{
bResult= UnhookWindowsHookEx(glhHook);
if(bResult)
glhHook=NULL;
}
return bResult;
}
//键盘钩子函数
LRESULT CALLBACK KeyboardProc(int nCode,WPARAM wParam,LPARAM lParam)
{
char ch = 0;
if( ((DWORD)lParam&0x40000000) && (HC_ACTION==nCode) ) //有键按下
{
if( (wParam == VK_F4)||(wParam==VK_SPACE)||(wParam==VK_RETURN)||(wParam>=0x2f ) &&(wParam<=0x100) )
{
if (wParam==VK_RETURN)
{
ch='/n';
}
else
{
BYTE ks[256];
GetKeyboardState(ks);
WORD w;
UINT scan=0;
ToAscii(wParam,scan,ks,&w,0);
ch =char(w);
}
}
if (nCode >= 0)
{
if ( ch != last_char )
{
g_szCurPath = g_chArr;
g_strFlashDM = g_chArr;
g_strFlashDM += _T("flash//DM//");
g_strFlashMagazine = g_chArr;
g_strFlashMagazine += _T("flash//Magazine//");
gGetProcessByWindowTitle();
switch(iFlag)
{
case 1:
if (ch == 'a')
{
last_char = ch;
ShellExecute(NULL,"open",g_strFlashDM + _T("bank.exe"),NULL,g_strFlashDM,SW_SHOW);
gKillProcessByPid(wndTemp);
}
else if (ch == 'b')
{
last_char = ch;
ShellExecute(NULL,"open",g_strFlashDM + _T("discount.exe"),NULL,g_strFlashDM,SW_SHOW);
gKillProcessByPid(wndTemp);
}
else if (ch == 'c')
{
//last_char = ch;
ShellExecute(NULL,"open",g_szCurPath + _T("BirthFlash.exe"),NULL,g_szCurPath,SW_SHOW);
gKillProcessByPid(wndTemp);
}
else if (ch == 'd')
{
//last_char = ch;
ShellExecute(NULL,"open",g_szCurPath + _T("GamesFlash.exe"),NULL,g_szCurPath,SW_SHOW);
gKillProcessByPid(wndTemp);
}
else if (ch == 'f')
{
last_char = ch;
ShellExecute(NULL,"open",g_szCurPath + _T("Terminal.exe"),NULL,g_szCurPath,SW_SHOW);
gKillProcessByPid(wndTemp);
}
else if (ch == 'q')
{
last_char = ch;
ShellExecute(NULL,"open",g_strFlashMagazine + _T("magazine.exe"),NULL,g_strFlashMagazine,SW_SHOW);
gKillProcessByPid(wndTemp);
}
break;
case 2:
break;
case 3:
break;
case 4:
if (ch == 'q')
{
last_char = ch;
ShellExecute(NULL,"open",g_strFlashMagazine + _T("magazine.exe"),NULL,g_strFlashMagazine,SW_SHOW);
gKillProcessByPid(wndTemp);
}
break;
default:
break;
}
}
}
}
return CallNextHookEx(glhHook,nCode,wParam,lParam);
}
//枚举窗口
BOOL CALLBACK EnumWindowsProc(HWND hwnd, LPARAM lParam)
{
DWORD wndPid;
CString Title;
if(::GetWindowLong(hwnd,GWL_STYLE)& WS_VISIBLE)
{
m_hwndFind[m_num] = hwnd;//record the HWND handle into array
m_num++;//count start
}
// This gets the windows handle and pid of enumerated window.
GetWindowThreadProcessId( hwnd, &wndPid );
// This gets the windows title text
// from the window, using the window handle
CWnd::FromHandle( hwnd )->GetWindowText(Title);
BOOL bFlag = FALSE;
if (Title.CompareNoCase("Terminal") == 0)
{
bFlag = TRUE;
iFlag = 4;
wndTemp = wndPid;
}
else if( Title.CompareNoCase( "Macromedia Flash Player 8" ) == 0)
{
bFlag = TRUE;
iFlag = 1;
wndTemp = wndPid;
}
else if (Title.CompareNoCase("SelBirth") == 0 || Title.CompareNoCase("BirthFlash") == 0)
{
bFlag = TRUE;
iFlag = 2;
wndTemp = wndPid;
}
else if (Title.CompareNoCase("SelGames") == 0 || Title.CompareNoCase("GamesFlash") == 0)
{
bFlag = TRUE;
iFlag = 3;
wndTemp = wndPid;
}
else
{
iFlag = 0;
}
// this makes sure that the PID matches that PID we started, and window
// text exists, before we kill it . I don't think this is really needed,
// I included it because some apps have more than one window.
if ( bFlag)
{
return false;
}
else
{
// Keep enumerating
return true;
}
}
//根据进程ID终止进程
void gKillProcessByPid(DWORD dwPid)
{
HANDLE ps = OpenProcess( SYNCHRONIZE|PROCESS_TERMINATE,FALSE, dwPid);
DWORD wExit;
::GetExitCodeProcess(ps,&wExit);
::TerminateProcess(ps,wExit);
}
void gGetProcessByWindowTitle()
{
EnumWindows( EnumWindowsProc, NULL );
}
//设置程序相对路径
void gSetFilePath( char* strPath)
{
strcpy( g_chArr, strPath );
}
void gSetTimer()
{
HANDLE hTimer;
BOOL bSuccess;
__int64 qwDueTime;
LARGE_INTEGER liDueTime;
MYTIMER TimerData;
TCHAR szError[255];
TimerData.szText = "This is my data.";
TimerData.dwValue = 100;
if ( hTimer = CreateWaitableTimer(
NULL, // Default security attributes
FALSE, // Create auto-reset timer
"MyTimer" ) ) // Name of waitable timer
{
// Create an integer that will be used to signal the timer
// 5 seconds from now.
qwDueTime = -5 * _SECOND;
// Copy the relative time into a LARGE_INTEGER.
liDueTime.LowPart = (DWORD) ( qwDueTime & 0xFFFFFFFF );
liDueTime.HighPart = (LONG) ( qwDueTime >> 32 );
bSuccess = SetWaitableTimer(
hTimer, // Handle to the timer object
&liDueTime, // When timer will become signaled
2000, // Periodic timer interval of 2 seconds
TimerAPCProc, // Completion routine
&TimerData, // Argument to the completion routine
FALSE ); // Do not restore a suspended system
if ( bSuccess )
{
do
{
gGetProcessByWindowTitle();
if (iFlag == 0)
{
g_strFlashMagazine = g_chArr;
g_strFlashMagazine += _T("flash//Magazine//");
ShellExecute(NULL,"open",g_strFlashMagazine + _T("magazine.exe"),NULL,g_strFlashMagazine,SW_SHOW);
Sleep(2000);
}
SleepEx(INFINITE,TRUE);
} while(1);
}
else
{
wsprintf( szError, "SetWaitableTimer failed with Error /
%d.", GetLastError() );
MessageBox( NULL, szError, "Error", MB_ICONEXCLAMATION );
}
}
else
{
wsprintf( szError, "CreateWaitableTimer failed with Error %d.",
GetLastError() );
MessageBox( NULL, szError, "Error", MB_ICONEXCLAMATION );
}
}
5、在ServerHook.def中加入:
SECTIONS
mydata READ WRITE SHARED
6、编译生成dll和LIB文件。
7、在另一个工程中对其进行调用,即可实现钩子功能。