C HOOK学习笔记

http://www.cnblogs.com/muchme/p/4388885.html

参考 http://9200cs.blog.163.com/blog/static/134577369201041111656659/

 

环境:VS2008

 

一、新建一个dll程序add,程序非常简单,其功能就是实现简单的a+b。

1、新建一个项目名为add

选择dll

 然后打开dllmain.cpp,代码:

// dllmain.cpp : 定义 DLL 应用程序的入口点。
#include "stdafx.h"

int WINAPI add(int a, int b)
{
  return a + b;
}

BOOL APIENTRY DllMain(HANDLE hModule,
  DWORD  ul_reason_for_call,
  LPVOID lpReserved
  )
{
  return TRUE;
}

右键项目添加一个新建项名为add.def的文件

打开编写代码:

LIBRARY  Add
DESCRIPTION "ADD LA"
EXPORTS
 add  @1;

 

 编译后我们就能在Debug目录下获取add.dll了。

二、编写主程序,新建一个基于对话框的MFC应用程序One

在向导中选择基于对话框

双击确定进入,代码为

    HINSTANCE hAddDll = NULL;

void COneDlg::OnBnClickedOk()
{ 
       
    typedef int (WINAPI*AddProc)(int a, int b);//函数原型定义  
    AddProc add;

    if (hAddDll == NULL)
    {
      hAddDll = ::LoadLibrary(_T("add.dll"));//加载dll  
    }
    add = (AddProc)::GetProcAddress(hAddDll, "add");//获取函数add地址  

    int a = 1;
    int b = 2;
    int c = add(a, b); 
    CString tem;
    tem.Format(_T("%d+%d=%d"), a, b, c);
    AfxMessageBox(tem);

}

编译一下再将之前获取到的add.dll拷贝到项目One下有exe文件的Debug目录下
运行结果出现

就说明我们的One已经成功调用了add.dll里的add()方法了。

三、至此,我们的小程序已经完成了,接下来该到我们的主角HOOK登场了!

新建一个MFC DLL项目

Hook.cpp里的代码

// Hook.cpp : Defines the initialization routines for the DLL.
#include "stdafx.h"
#include "Hook.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#endif
//变量定义  

#pragma data_seg("SHARED") //不同Instance共享的该变量   
static HHOOK  hhk = NULL; //鼠标钩子句柄  
static HINSTANCE hinst = NULL; //本dll的实例句柄 (hook.dll)  
#pragma data_seg()  
#pragma comment(linker, "/section:SHARED,rws")  
//以上的变量为共享  

CString temp; //用于显示错误的临时变量  
bool bHook = false; //是否Hook了函数  
bool m_bInjected = false; //是否对API进行了Hook  
BYTE OldCode[5]; //原程序API入口代码  
BYTE NewCode[5]; //新跳转的API代码 (jmp xxxx)  
typedef int (WINAPI*AddProc)(int a, int b);//add.dll中的add函数定义  
AddProc add; //add.dll中的add函数  
HANDLE hProcess = NULL; //所处进程的句柄  
FARPROC pfadd;  //指向add函数的远指针  
DWORD dwPid;  //所处进程ID  
//end of 变量定义  
// CHookApp

BEGIN_MESSAGE_MAP(CHookApp, CWinApp)
END_MESSAGE_MAP()

//鼠标钩子过程,什么事情也不做,目的是注入dll到程序中  
LRESULT CALLBACK MouseProc(int nCode, WPARAM wParam, LPARAM lParam)
{
    return CallNextHookEx(hhk, nCode, wParam, lParam);
}
//开启钩子的函数  
void HookOn()
{
    ASSERT(hProcess != NULL);

    DWORD dwTemp = 0;
    DWORD dwOldProtect;

    //将内存保护模式改为可写,老模式保存入dwOldProtect  
    VirtualProtectEx(hProcess, pfadd, 5, PAGE_READWRITE, &dwOldProtect);
    //将所属进程中add()的前5个字节改为Jmp Myadd   
    WriteProcessMemory(hProcess, pfadd, NewCode, 5, 0);
    //将内存保护模式改回为dwOldProtect  
    VirtualProtectEx(hProcess, pfadd, 5, dwOldProtect, &dwTemp);

    bHook = true;
}
//关闭钩子的函数  
void HookOff()//将所属进程中add()的入口代码恢复  
{
    ASSERT(hProcess != NULL);

    DWORD dwTemp = 0;
    DWORD dwOldProtect;

    VirtualProtectEx(hProcess, pfadd, 5, PAGE_READWRITE, &dwOldProtect);
    WriteProcessMemory(hProcess, pfadd, OldCode, 5, 0);
    VirtualProtectEx(hProcess, pfadd, 5, dwOldProtect, &dwTemp);
    bHook = false;
}
//然后,写我们自己的Myadd()函数  
int WINAPI Myadd(int a, int b)
{
    //截获了对add()的调用,我们给a,b都加上一定的数
    a = a + 1;
    b = b + 1;

    HookOff();//关掉Myadd()钩子防止死循环  

    int ret;
    ret = add(a, b);

    HookOn();//开启Myadd()钩子  

    return ret;
}
//好,最重要的HOOK函数: 
void Inject()
{

    if (m_bInjected == false)
    { //保证只调用1次  
        m_bInjected = true;

        //获取add.dll中的add()函数  
        HMODULE hmod = ::LoadLibrary(_T("add.dll"));
        add = (AddProc)::GetProcAddress(hmod, "add");
        pfadd = (FARPROC)add;

        if (pfadd == NULL)
        {
            AfxMessageBox(L"cannot locate add()");
        }

        // 将add()中的入口代码保存入OldCode[]  
        _asm
        {
            lea edi, OldCode
                mov esi, pfadd
                cld
                movsd
                movsb
        }

        NewCode[0] = 0xe9;//实际上0xe9就相当于jmp指令  
        //获取Myadd()的相对地址  
        _asm
        {
            lea eax, Myadd
                mov ebx, pfadd
                sub eax, ebx
                sub eax, 5
                mov dword ptr[NewCode + 1], eax
        }
        //填充完毕,现在NewCode[]里的指令相当于Jmp Myadd  
        HookOn(); //可以开启钩子了  
    }
}


CHookApp::CHookApp()
{

}
CHookApp theapp;


//鼠标钩子安装函数:  
BOOL InstallHook()
{

    hhk = ::SetWindowsHookEx(WH_MOUSE, MouseProc, hinst, 0);

    return true;
}

//卸载鼠标钩子函数  
void UninstallHook()
{
    ::UnhookWindowsHookEx(hhk);
}



//在dll实例化中获得一些参数  
BOOL CHookApp::InitInstance()
{
    CWinApp::InitInstance();

    //获得dll 实例,进程句柄  
    hinst = ::AfxGetInstanceHandle();
    DWORD dwPid = ::GetCurrentProcessId();
    hProcess = OpenProcess(PROCESS_ALL_ACCESS, 0, dwPid);
    //调用注射函数  
    Inject();
    return TRUE;
}

接着别忘了Hook.def下的配置

LIBRARY      "Hook"
DESCRIPTION  'Hook Windows Dynamic Link Library'

EXPORTS
    ; Explicit exports can go here
 InstallHook  
 MouseProc
 Myadd
 UninstallHook

 

 编译一下,再将之前获得的add.dll丢一份到Hook的Debug目录下

这样,我们的Hook完成了

四、接下来我们就可以修改前面的One的测试程序了

添加一个按钮,双击进入相应事件 代码:

HINSTANCE hinst;

void COneDlg::OnBnClickedButton1()
{
    hinst=LoadLibrary(_T("hook.dll"));
    if(hinst==NULL)
    {
        AfxMessageBox(_T("no hook.dll!"));
        return;
    }
    typedef BOOL (CALLBACK *inshook)(); 
    inshook insthook;

    insthook=::GetProcAddress(hinst,"InstallHook");
    if(insthook==NULL)
    {
        AfxMessageBox(_T("func not found!"));
        return;
    }

    DWORD pid=::GetCurrentProcessId();
    BOOL ret=insthook();
}

别忘了退出时卸掉钩子

再加个按钮

void COneDlg::OnBnClickedButton2()
{
    // TODO: 在此添加控件通知处理程序代码s
    typedef BOOL (CALLBACK *UnhookProc)(); 
    UnhookProc UninstallHook;
    UninstallHook=::GetProcAddress(hinst,"UninstallHook");
    if(UninstallHook==NULL) UninstallHook();
    if (hinst!=NULL)
    {
        ::FreeLibrary(hinst);
    }
    if (hAddDll!=NULL)
    {
        ::FreeLibrary(hAddDll);
    }
    CDialog::OnCancel();
}

再将Hook目录下的Hook.dll也丢到One的Debug目录下

至此,整个HOOK的例子就结束了。

最后的效果:正常为1+2=3,点击button1后再点击确定,就变成1+1=5了

最后需要注意的是项目里面有2个Debug目录,要放在这个

 

 里面有

 

 不要 放错了哦,这个Debug目录是需要编译过后才生成的~~!

实例 http://download.csdn.net/detail/muchme2005/8559693

posted on 2015-04-03 00:07  Xiao灬明b  阅读(2273)  评论(0编辑  收藏  举报

导航