//////////////////ActiveKey.cpp#include <afxsock.h>typedef struct tag_HOOKAPI 

LPCSTR szFunc;//被HOOK的API函数名称。
PROC pNewProc;//替代函数地址。
PROC pOldProc;//原API函数地址。
}HOOKAPI, *LPHOOKAPI;extern "C" __declspec(dllexport)PIMAGE_IMPORT_DESCRIPTOR 
LocationIAT(HMODULE hModule, LPCSTR szImportMod) 
//其中,hModule为进程模块句柄;szImportMod为输入库名称。

//检查是否为DOS程序,如是返回NULL,因DOS程序没有IAT。
PIMAGE_DOS_HEADER pDOSHeader = (PIMAGE_DOS_HEADER) hModule; 
if(pDOSHeader->e_magic != IMAGE_DOS_SIGNATURE) return NULL; 
//检查是否为NT标志,否则返回NULL。
PIMAGE_NT_HEADERS pNTHeader = (PIMAGE_NT_HEADERS)((DWORD)pDOSHeader+ (DWORD)(pDOSHeader->e_lfanew)); 
if(pNTHeader->Signature != IMAGE_NT_SIGNATURE) return NULL; 
//没有IAT表则返回NULL。
if(pNTHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress == 0) return NULL; 
//定位第一个IAT位置。 
PIMAGE_IMPORT_DESCRIPTOR pImportDesc = (PIMAGE_IMPORT_DESCRIPTOR)((DWORD)pDOSHeader + (DWORD)(pNTHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress)); 
//根据输入库名称循环检查所有的IAT,如匹配则返回该IAT地址,否则检测下一个IAT。
while (pImportDesc->Name) 

//获取该IAT描述的输入库名称。
PSTR szCurrMod = (PSTR)((DWORD)pDOSHeader + (DWORD)(pImportDesc->Name)); 
if (stricmp(szCurrMod, szImportMod) == 0)
break; 
pImportDesc++; 

if(pImportDesc->Name == NULL) return NULL; 
return pImportDesc; 
}
extern "C" __declspec(dllexport) HookAPIByName( HMODULE hModule, LPCSTR szImportMod, LPHOOKAPI pHookApi) 
//其中,hModule为进程模块句柄;szImportMod为输入库名称;pHookAPI为HOOKAPI结构指针。

//定位szImportMod输入库在输入数据段中的IAT地址。
PIMAGE_IMPORT_DESCRIPTOR pImportDesc = LocationIAT(hModule, szImportMod); 
if (pImportDesc == NULL) return FALSE; 
//第一个Thunk地址。
PIMAGE_THUNK_DATA pOrigThunk = (PIMAGE_THUNK_DATA)((DWORD)hModule + (DWORD)(pImportDesc->OriginalFirstThunk)); 
//第一个IAT项的Thunk地址。
PIMAGE_THUNK_DATA pRealThunk = (PIMAGE_THUNK_DATA)((DWORD)hModule + (DWORD)(pImportDesc->FirstThunk)); 
//循环查找被截API函数的IAT项,并使用替代函数地址修改其值。
while(pOrigThunk->u1.Function) 

//检测此Thunk是否为IAT项。
if((pOrigThunk->u1.Ordinal & IMAGE_ORDINAL_FLAG) != IMAGE_ORDINAL_FLAG) 
{
//获取此IAT项所描述的函数名称。
PIMAGE_IMPORT_BY_NAME pByName =(PIMAGE_IMPORT_BY_NAME)((DWORD)hModule+(DWORD)(pOrigThunk->u1.AddressOfData)); 
if(pByName->Name[0] == '\0') return FALSE; 
//检测是否为挡截函数。
if(strcmpi(pHookApi->szFunc, (char*)pByName->Name) == 0) 

MEMORY_BASIC_INFORMATION mbi_thunk;
//查询修改页的信息。
VirtualQuery(pRealThunk, &mbi_thunk, sizeof(MEMORY_BASIC_INFORMATION)); 
//改变修改页保护属性为PAGE_READWRITE。
VirtualProtect(mbi_thunk.BaseAddress,mbi_thunk.RegionSize, PAGE_READWRITE, &mbi_thunk.Protect); 
//保存原来的API函数地址。
if(pHookApi->pOldProc == NULL) 
pHookApi->pOldProc = (PROC)pRealThunk->u1.Function; 
//修改API函数IAT项内容为替代函数地址。
pRealThunk->u1.Function = (PDWORD)pHookApi->pNewProc; 
//恢复修改页保护属性。
DWORD dwOldProtect; 
VirtualProtect(mbi_thunk.BaseAddress, mbi_thunk.RegionSize, mbi_thunk.Protect, &dwOldProtect); 


pOrigThunk++; 
pRealThunk++; 

SetLastError(ERROR_SUCCESS); //设置错误为ERROR_SUCCESS,表示成功。
return TRUE; 
}  
static int WINAPI MessageBoxA1 (HWND hWnd , LPCTSTR lpText, LPCTSTR lpCaption, UINT uType)
{
//过滤掉原MessageBoxA的正文和标题内容,只显示如下内容。
return MessageBox(hWnd, "Hook API OK!", "Hook API", uType); 

static int WINAPI recv1(SOCKET s, char FAR *buf, int len, int flags )
{
//此处可以挡截游戏服务器发送来的网络数据包,可以加入分析和处理数据代码。
MessageBeep(1);
return recv(s,buf,len,flags);

BOOL __declspec(dllexport)__stdcall installhook()
{
hkb=SetWindowsHookEx(WH_KEYBOARD,(HOOKPROC)KeyboardProc,hins,0);
HOOKAPI api[2];
api[0].szFunc ="MessageBoxA";//设置被挡截函数的名称。
api[0].pNewProc = (PROC)MessageBoxA1;//设置替代函数的地址。
api[1].szFunc ="recv";//设置被挡截函数的名称。
api[1].pNewProc = (PROC)recv1; //设置替代函数的地址。
//设置挡截User32.dll库中的MessageBoxA函数。
HookAPIByName(GetModuleHandle(NULL),"User32.dll",&api[0]);
HookAPIByName(GetModuleHandle(NULL),"WSOCK32.dll",&api[1]);

return TRUE;
}
//我在另一个程序中如下来调用,但不成功。
BOOL CCallHookDlg::OnInitDialog()
{
CDialog::OnInitDialog(); // Add "About..." menu item to system menu. // IDM_ABOUTBOX must be in the system command range.
ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
ASSERT(IDM_ABOUTBOX < 0xF000); CMenu* pSysMenu = GetSystemMenu(FALSE);
if (pSysMenu != NULL)
{
CString strAboutMenu;
strAboutMenu.LoadString(IDS_ABOUTBOX);
if (!strAboutMenu.IsEmpty())
{
pSysMenu->AppendMenu(MF_SEPARATOR);
pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
}
} // Set the icon for this dialog.  The framework does this automatically
//  when the application's main window is not a dialog
SetIcon(m_hIcon, TRUE); // Set big icon
SetIcon(m_hIcon, FALSE); // Set small icon

// TODO: Add extra initialization here
static HINSTANCE hinstDLL; 
typedef BOOL (CALLBACK *inshook)(); 
inshook instkbhook;
if(hinstDLL=LoadLibrary((LPCTSTR)"hodll.dll"))
{
   instkbhook=(inshook)GetProcAddress(hinstDLL, "installhook"); 
   instkbhook();
}
return TRUE;  // return TRUE  unless you set the focus to a control
}进行调试后发现,它并没有找到我要拦截的MessageBox()入口地址,在LocationIAT函数中,它确实定位到了User32.dll,但并未定位到wsock32.dll,但我那时在上网,应该有程序装载了wsock32.dll。在HookAPIByName函数中,它没有找到MessageBox()入口地址,它的IAT表只有GetSystemMetrics一项,再下去pOrigThunk就是空的了,因此HookAPIByName返回了FALSE,但我那时也开着含有MessageBox()程序,为什么它找不到呢。问题1:
  按照作者的意思,它应该会拦截所有程序的MessageBox(),那意思是user32.dll在系统中只有一个实例?不然它应该寻找每个程序中调用user32.dll实例中的IAT表。
问题2:
  user32.dll的IAT表怎么会只找到GetSystemMetrics一项?它的网址是http://www.weste.net/InfoShow.asp?id=659,其实我用baidu搜索到的都是这一篇。
它原文中是要#include "wsock32.h",这应该是它在前面的拦截winsock中的文件,我觉得不对,改成了#include <afxsock.h>我就50分可用分了,请哪位大侠给点可用分,我好给大家。谢谢啦,谢谢大家关注我的问题。

解决方案 »

  1.   

    试试拦截Unicode版本的MessageBox函数MessageBoxW
      

  2.   

    没有用的,它是没有在user32.dll的IAT表中找到MessageBox()项,它只找到了GetSystemMetrics一项,就是问题2 ,IAT表怎么会只有一项?
      

  3.   

    我认为user32.dll对于每一个调用它的程序都会有一个实例,所以我用下面的程序遍历所有的模块,结果证明是对的.它第一次调用HookAPIByName还是只找到了GetSystemMetrics 一项,但后来就找到了我需要的MessageBoxA,并且在好几个模块中都找到了MessageBoxA,但问题是它只能拦截到我编的调用了ActiveKey.dll的程序中的MessageBox,在其它有MessageBox中的程序中却没有拦截到.我觉得它既然修改了其它程序中MessageBox的地址内容,它就应该能拦截到啊?为什么?我是先启动其它有MessageBox程序的.奇怪的是调用user32.dll的模块数目并没有随着增加,也就是无论我启动还是不启动其它有MessageBox程序,调用user32.dll的模块数目总是那么多.为什么?
    HOOKAPI api[2];
    api[0].szFunc ="MessageBoxA";//设置被挡截函数的名称。
    api[0].pNewProc = (PROC)MessageBoxA1;//设置替代函数的地址。
    api[1].szFunc ="recv";//设置被挡截函数的名称。
    api[1].pNewProc = (PROC)recv1; //设置替代函数的地址。
    //设置挡截User32.dll库中的MessageBoxA函数。
    HANDLE hSnapshot;
    MODULEENTRY32 me = {sizeof(MODULEENTRY32)};
    hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE,0);
    BOOL bOk = Module32First(hSnapshot,&me);
    while (bOk)
    {
    HookAPIByName(me.hModule,"User32.dll",&api[0]);
    //设置挡截Wsock32.dll库中的recv函数。
    HookAPIByName(me.hModule,"Wsock32.dll",&api[1]);
    bOk = Module32Next(hSnapshot,&me);
    }
      

  4.   

    在<<WINDOWS核心编程>>这本书上有这一例子的详细实现。