Quantcast
Channel: 看雪安全论坛
Viewing all articles
Browse latest Browse all 9556

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

$
0
0
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”
附件 80020附件 80021附件 80022附件 80023附件 80024

(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();
}


上传的图像
文件类型: jpg hook1.jpg (45.2 KB)
文件类型: jpg hook2.jpg (156.7 KB)
文件类型: jpg hook3.jpg (13.7 KB)
文件类型: jpg hook4.jpg (22.8 KB)
文件类型: jpg hook5.jpg (179.3 KB)
上传的附件
文件类型: rar 帖子中的代码.rar (6.4 KB)

Viewing all articles
Browse latest Browse all 9556

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>