首页
社区
课程
招聘
[求助]好想哭啊,HOOK api了两天都没成功
发表于: 2013-6-20 20:57 6744

[求助]好想哭啊,HOOK api了两天都没成功

2013-6-20 20:57
6744
1.首先,这个CAPIHook的类是Jeffrey Richter 写的,我本帖子的代码都来自人民邮电出版社《windows 系统编程》的源代码。
别人拿来直接就写成了程序
http://blog.csdn.net/jacklam200/article/details/4302652
我拿来源代码改了两天都没改对。。好想去shi。。。。
2.我想实现的是调用CAPIHook类,全局钩子,保护所有进程不被TerminateProcess()关闭。
  调试的时候提示GetProcAddress()函数出堆栈溢出,可是真心不会改啊啊啊
3.dll设计
(1)APIHook.h文件
////////////////////////////////////////////////////////  
// APIHook.h文件  
  
  
#ifndef __APIHOOK_H__  
#define __APIHOOK_H__  
  
#include <windows.h>  
  
class CAPIHook    
{  
public:  
    CAPIHook(LPSTR pszModName,   
        LPSTR pszFuncName, PROC pfnHook, BOOL bExcludeAPIHookMod = TRUE);  
    virtual ~CAPIHook();  
    operator PROC() { return m_pfnOrig; }  
  
// 实现  
private:  
    LPSTR m_pszModName;     // 要HOOK函数的模块的名字  
    LPSTR m_pszFuncName;    // 要HOOK的函数的名字  
    PROC m_pfnOrig;         // 原API函数地址  
    PROC m_pfnHook;         // HOOK后函数的地址  
    BOOL m_bExcludeAPIHookMod;  // 是否将HOOK API的模块排除在外  
  
private:  
    static void ReplaceIATEntryInAllMods(LPSTR pszExportMod, PROC pfnCurrent,   
                PROC pfnNew, BOOL bExcludeAPIHookMod);  
    static void ReplaceIATEntryInOneMod(LPSTR pszExportMod,   
                PROC pfnCurrent, PROC pfnNew, HMODULE hModCaller);  
  
  
// 下面的代码用来解决其它模块动态加载DLL的问题  
private:  
    // 这两个指针用来将所有的CAPIHook对象连在一起  
    static CAPIHook *sm_pHeader;  
    CAPIHook *m_pNext;  
  
private:  
    // 当一个新的DLL被加载时,调用此函数  
    static void WINAPI HookNewlyLoadedModule(HMODULE hModule, DWORD dwFlags);  
  
    // 用来跟踪当前进程加载新的DLL  
    static HMODULE WINAPI LoadLibraryA(PCSTR  pszModulePath);  
    static HMODULE WINAPI LoadLibraryW(PCWSTR pszModulePath);  
    static HMODULE WINAPI LoadLibraryExA(PCSTR  pszModulePath, HANDLE hFile, DWORD dwFlags);  
    static HMODULE WINAPI LoadLibraryExW(PCWSTR pszModulePath, HANDLE hFile, DWORD dwFlags);  
      
    // 如果请求已HOOK的API函数,则返回用户自定义函数的地址  
    static FARPROC WINAPI GetProcAddress(HMODULE hModule, PCSTR pszProcName);  
private:  
    // 自动对这些函数进行挂钩  
    static CAPIHook sm_LoadLibraryA;  
    static CAPIHook sm_LoadLibraryW;  
    static CAPIHook sm_LoadLibraryExA;  
    static CAPIHook sm_LoadLibraryExW;  
    static CAPIHook sm_GetProcAddress;  
};  
  
#endif // __APIHOOK_H__  


(2)APIHook.cpp文件
#include "StdAfx.h"
#include "APIHook.h"

//////////////////////////////////////////////////////////////  
// APIHook.cpp文件  
#include "stdafx.h"  
#include "APIHook.h"  
#include "Tlhelp32.h"  
  
#include <ImageHlp.h> // 为了调用ImageDirectoryEntryToData函数  
#pragma comment(lib, "ImageHlp")  
  
  
// CAPIHook对象链表的头指针  
CAPIHook* CAPIHook::sm_pHeader = NULL;  
  
CAPIHook::CAPIHook(LPSTR pszModName, LPSTR pszFuncName, PROC pfnHook, BOOL bExcludeAPIHookMod)  
{  
    // 保存这个Hook函数的信息  
    m_bExcludeAPIHookMod = bExcludeAPIHookMod;  
    m_pszModName = pszModName;  
    m_pszFuncName = pszFuncName;  
    m_pfnHook = pfnHook;  
    m_pfnOrig = ::GetProcAddress(::GetModuleHandle(pszModName), pszFuncName);  
  
    // 将此对象添加到链表中  
    m_pNext = sm_pHeader;  
    sm_pHeader = this;  
      
    // 在所有当前已加载的模块中HOOK这个函数  
    ReplaceIATEntryInAllMods(m_pszModName, m_pfnOrig, m_pfnHook, bExcludeAPIHookMod);   
}  
  
CAPIHook::~CAPIHook()  
{  
    // 取消对所有模块中函数的HOOK  
    ReplaceIATEntryInAllMods(m_pszModName, m_pfnHook, m_pfnOrig, m_bExcludeAPIHookMod);  
  
    CAPIHook *p = sm_pHeader;  
  
    // 从链表中移除此对象  
    if(p == this)  
    {  
        sm_pHeader = p->m_pNext;  
    }  
    else  
    {  
        while(p != NULL)  
        {  
            if(p->m_pNext == this)  
            {  
                p->m_pNext = this->m_pNext;  
                break;  
            }  
            p = p->m_pNext;  
        }  
    }  
  
}  
  
void CAPIHook::ReplaceIATEntryInOneMod(LPSTR pszExportMod,   
                   PROC pfnCurrent, PROC pfnNew, HMODULE hModCaller)  
{  
    // 取得模块的导入表(import descriptor)首地址。ImageDirectoryEntryToData函数可以直接返回导入表地址  
    ULONG ulSize;  
    PIMAGE_IMPORT_DESCRIPTOR pImportDesc = (PIMAGE_IMPORT_DESCRIPTOR)  
                ::ImageDirectoryEntryToData(hModCaller, TRUE,   
                    IMAGE_DIRECTORY_ENTRY_IMPORT, &ulSize);  
    if(pImportDesc == NULL) // 这个模块没有导入节表  
    {  
        return;  
    }  
  
    // 查找包含pszExportMod模块中函数导入信息的导入表项  
    while(pImportDesc->Name != 0)  
    {  
        LPSTR pszMod = (LPSTR)((DWORD)hModCaller + pImportDesc->Name);  
        if(lstrcmpiA(pszMod, pszExportMod) == 0) // 找到  
            break;  
  
        pImportDesc++;  
    }  
    if(pImportDesc->Name == 0) // hModCaller模块没有从pszExportMod模块导入任何函数  
    {  
        return;  
    }  
  
    // 取得调用者的导入地址表(import address table, IAT)  
    PIMAGE_THUNK_DATA pThunk = (PIMAGE_THUNK_DATA)(pImportDesc->FirstThunk + (DWORD)hModCaller);  
  
    // 查找我们要HOOK的函数,将它的地址用新函数的地址替换掉  
    while(pThunk->u1.Function)  
    {  
        // lpAddr指向的内存保存了函数的地址  
        PDWORD lpAddr = (PDWORD)&(pThunk->u1.Function);  
        if(*lpAddr == (DWORD)pfnCurrent)  
        {  
  
            ::WriteProcessMemory(::GetCurrentProcess(),   
                        lpAddr, &pfnNew, sizeof(DWORD), NULL);  
  
            //::VirtualProtect(lpAddr, sizeof(DWORD), dwOldProtect, 0);  
            break;  
        }  
        pThunk++;  
    }  
}  
  
void CAPIHook::ReplaceIATEntryInAllMods(LPSTR pszExportMod,   
                    PROC pfnCurrent, PROC pfnNew, BOOL bExcludeAPIHookMod)  
{  
    // 取得当前模块的句柄  
    HMODULE hModThis = NULL;  
    if(bExcludeAPIHookMod)  
    {  
        MEMORY_BASIC_INFORMATION mbi;  
        if(::VirtualQuery(ReplaceIATEntryInAllMods, &mbi, sizeof(mbi)) != 0)  
            hModThis = (HMODULE)mbi.AllocationBase;  
    }  
  
    // 取得本进程的模块列表  
    HANDLE hSnap = ::CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, ::GetCurrentProcessId());  
  
    // 遍历所有模块,分别对它们调用ReplaceIATEntryInOneMod函数,修改导入地址表  
    MODULEENTRY32 me = { sizeof(MODULEENTRY32) };  
    BOOL bOK = ::Module32First(hSnap, &me);  
    while(bOK)  
    {  
        // 注意:我们不HOOK当前模块的函数  
        if(me.hModule != hModThis)  
            ReplaceIATEntryInOneMod(pszExportMod, pfnCurrent, pfnNew, me.hModule);  
  
        bOK = ::Module32Next(hSnap, &me);  
    }  
    ::CloseHandle(hSnap);  
}  
  
  
// 挂钩LoadLibrary和GetProcAddress函数,以便在这些函数被调用以后,挂钩的函数也能够被正确的处理  
  
CAPIHook CAPIHook::sm_LoadLibraryA("Kernel32.dll", "LoadLibraryA",     
                    (PROC)CAPIHook::LoadLibraryA, TRUE);  
  
CAPIHook CAPIHook::sm_LoadLibraryW("Kernel32.dll", "LoadLibraryW",     
                    (PROC)CAPIHook::LoadLibraryW, TRUE);  
  
CAPIHook CAPIHook::sm_LoadLibraryExA("Kernel32.dll", "LoadLibraryExA",   
                    (PROC)CAPIHook::LoadLibraryExA, TRUE);  
  
CAPIHook CAPIHook::sm_LoadLibraryExW("Kernel32.dll", "LoadLibraryExW",   
                    (PROC)CAPIHook::LoadLibraryExW, TRUE);  
  
CAPIHook CAPIHook::sm_GetProcAddress("Kernel32.dll", "GetProcAddress",   
                    (PROC)CAPIHook::GetProcAddress, TRUE);  
  
  
  
void WINAPI CAPIHook::HookNewlyLoadedModule(HMODULE hModule, DWORD dwFlags)  
{  
    //// 如果一个新的模块被加载,挂钩各CAPIHook对象要求的API函数  
    if((hModule != NULL) && ((dwFlags&LOAD_LIBRARY_AS_DATAFILE) == 0))  
    {  
        CAPIHook *p = sm_pHeader;  
        while(p != NULL)  
        {  
            ReplaceIATEntryInOneMod(p->m_pszModName, p->m_pfnOrig, p->m_pfnHook, hModule);  
            p = p->m_pNext;  
        }  
    }  
}  
  
  
HMODULE WINAPI CAPIHook::LoadLibraryA(PCSTR pszModulePath)   
{  
    HMODULE hModule = ::LoadLibraryA(pszModulePath);  
    HookNewlyLoadedModule(hModule, 0);  
    return(hModule);  
}  
  
HMODULE WINAPI CAPIHook::LoadLibraryW(PCWSTR pszModulePath)   
{  
    HMODULE hModule = ::LoadLibraryW(pszModulePath);  
    HookNewlyLoadedModule(hModule, 0);  
    return(hModule);  
}  
  
HMODULE WINAPI CAPIHook::LoadLibraryExA(PCSTR pszModulePath, HANDLE hFile, DWORD dwFlags)   
{  
    HMODULE hModule = ::LoadLibraryExA(pszModulePath, hFile, dwFlags);  
    HookNewlyLoadedModule(hModule, dwFlags);  
    return(hModule);  
}  
  
HMODULE WINAPI CAPIHook::LoadLibraryExW(PCWSTR pszModulePath, HANDLE hFile, DWORD dwFlags)   
{  
    HMODULE hModule = ::LoadLibraryExW(pszModulePath, hFile, dwFlags);  
    HookNewlyLoadedModule(hModule, dwFlags);  
    return(hModule);  
}  
  
FARPROC WINAPI CAPIHook::GetProcAddress(HMODULE hModule, PCSTR pszProcName)  
{  
    // 得到这个函数的真实地址  
    FARPROC pfn = ::GetProcAddress(hModule, pszProcName);  
  
    // 看它是不是我们要hook的函数  
    CAPIHook *p = sm_pHeader;  
    while(p != NULL)  
    {  
        if(p->m_pfnOrig == pfn)  
        {  
            pfn = p->m_pfnHook;  
            break;  
        }  
  
        p = p->m_pNext;  
    }  
  
    return pfn;  
}  

(3)HookTerminateProcess.cpp文件
// HookTerminateProcess.cpp : 定义 DLL 应用程序的导出函数。
//

#include "stdafx.h"
#include "APIHook.h"
 #include "stdio.h" 

#define DllExport extern "C"__declspec(dllexport)

extern CAPIHook g_TerminateProcess;
#pragma data_seg("Shared")
HHOOK g_hHook = NULL;
#pragma data_seg()
#pragma comment(linker,"/SECTION:Shared,RWS")

bool WINAPI Hook_TerminateProcess(HANDLE hProcess, UINT nExitCode)
{
	//typedef bool (WINAPI *PFNTERMINATEPROCESS)(HANDLE, UINT);
	char szPathName[256];
	::GetModuleFileName(NULL, szPathName, 256);
	char sz[2048];
	wsprintf(sz, "进程号:%d   %s, 进程句柄: %X, 退出代码: %d\n", ::GetCurrentProcess(), szPathName, hProcess, nExitCode);
	MessageBox(NULL, "不允许杀掉进程", "提示", 0);

	FILE *fp;
	fp=fopen("c:\\terminateProcess.txt","a"); 
	fprintf(fp,"%s",sz);


		//return ((PFNTERMINATEPROCESS)(PROC)g_TerminateProcess)(hProcess, nExitCode);
	return true;
}
CAPIHook g_TerminateProcess("kernel32.dll", "TerminateProcess", (PROC)Hook_TerminateProcess );

DllExport int SetSysHook(bool bInstall, DWORD dwThreadId);
//extern "C" HMODULE __declspec(dllexport)ModuleFromAddress(void *pv);
DllExport LRESULT WINAPI GetMsgProc(int code, WPARAM wParam, LPARAM lParam);

static HMODULE ModuleFromAddress(void *pv)
{
	MEMORY_BASIC_INFORMATION mbi;
	if(::VirtualQuery(pv, &mbi, sizeof(mbi)) != 0)
	{
		return (HMODULE)mbi.AllocationBase;
	}
	return NULL;
}
 static LRESULT WINAPI GetMsgProc(int code, WPARAM wParam, LPARAM lParam)
{
	return ::CallNextHookEx(g_hHook, code, wParam, lParam);
}


int  SetSysHook(bool bInstall, DWORD dwThreadId)
{
	bool bOk;
	if(bInstall)
	{
		g_hHook = ::SetWindowsHookEx(WH_GETMESSAGE, GetMsgProc, ModuleFromAddress(GetMsgProc), dwThreadId);
		bOk = (g_hHook != NULL);
	}
	else
	{
		::UnhookWindowsHookEx(g_hHook);
		bOk = (g_hHook == NULL);
	}
	return bOk;

}

4.exe设计
就是基于对话框的mfc程序
(1)在OnInitDialog()函数的//to do下面加上代码
char szDll[] = ".\\lxh_hookapi.dll";  // 引用的DLL说文件名
    hModule = ::GetModuleHandle(szDll);    //  获取DLL文件的模块地址
	if(hModule == NULL)  
    {  
        hModule = ::LoadLibrary(szDll);		// 加载DLL 文件
        nNeedFree = true;						// 标识退出时应释放DLL句柄
    }  
    if(hModule == NULL)  
    {  
		
        return TRUE;  
    }  
	// 获取SetSysHook()函数的指针
	mSetSysHook = (PFNSETSYSHOOK)GetProcAddress(hModule, "SetSysHook");  
    
	if(mSetSysHook == NULL)  
    {  
        if(nNeedFree)  
            ::FreeLibrary(hModule);  
        return TRUE;  
    }  
    bool bRet = mSetSysHook(TRUE, 0);  // 安装钩子

	return TRUE;  // return TRUE  unless you set the focus to a control
}


需要说明的是,我在OnInitDialog()函数下断,该函数执行完的时候,钩子神马的都安上了
关进程的时候也提示 “不允许关闭”
但是继续走,就到了系统领空,f5一下,就报错“stack overflow”


(2)在Onclose()函数中加上如下代码
void CLxh_hookapi_testDlg::OnClose() 
{
	// TODO: Add your message handler code here and/or call default
	if(mSetSysHook == NULL)  
    {  
        if(nNeedFree)  
            ::FreeLibrary(hModule);		// 释放DSLL句柄
        return ;  
    }  
    bool bRet = mSetSysHook(FALSE, 0);  // 卸载钩子
	
	CDialog::OnClose();
}

[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)

上传的附件:
收藏
免费 0
支持
分享
最新回复 (8)
雪    币: 6
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
windbg跟踪一下就可以了..
2013-6-20 23:45
0
雪    币: 14
活跃值: (88)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
InLine还是SSDT?
2013-6-21 12:09
0
雪    币: 53
活跃值: (18)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
问题已解决,代码没问题,编译器问题。将debug编译器的link increment 选项勾去掉即可。
2013-6-21 12:15
0
雪    币: 6092
活跃值: (744)
能力值: ( LV4,RANK:45 )
在线值:
发帖
回帖
粉丝
5
才两天就哭。。我都快两个月了。。
2013-6-22 13:19
0
雪    币: 53
活跃值: (18)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6
我去。。。。
2013-6-23 19:22
0
雪    币: 297
活跃值: (120)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
7
哈哈哈哈哈,这都是某某集成IDE带来的苦果啊,最最基础的东西都被自动化完成了,结果总是被这些最最基础的东西浪费了更多的时间,还是自己写makefile吧,自写批处理编译链接这些问题根本就不会存在。
2013-6-23 19:35
0
雪    币: 371
活跃值: (72)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
8
什么都自己干,会累个半死的
2013-6-23 19:39
0
雪    币: 297
活跃值: (120)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
9
copy->patse->做少量修改就行了
2013-6-23 19:47
0
游客
登录 | 注册 方可回帖
返回
//