C HOOK学习笔记

参考 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目录是需要编译过后才生成的~~!

时间: 2024-08-04 18:17:06

C HOOK学习笔记的相关文章

我的Hook学习笔记

关于Hook 一.基本概念: 钩子(Hook),是Windows消息处理机制的一个平台,应用程序能够在上面设置子程以监视指定窗体的某种消息,并且所监视的窗体能够是其它进程所创建的.当消息到达后,在目标窗体处理函数之前处理它.钩子机制同意应用程序截获处理window消息或特定事件. 钩子实际上是一个处理消息的程序段,通过系统调用,把它挂入系统.每当特定的消息发出,在没有到达目的窗体前,钩子程序就先捕获该消息,亦即钩子函数先得到控制权.这时钩子函数即能够加工处理(改变)该消息,也能够不作处理而继续传

《iOS应用逆向工程》学习笔记(二)iOS系统目录结构(部分)

首先下载个iFile,可以用来直观地查看iOS系统的目录结构. 下面记录一些关键的iOS目录结构: /var:"variable"的简写,存放一些经常更改的文件,例如日志.用户数据.临时文件等.其中/var/mobile/Applications下存放了所有App Store App. /Applications:存放所有的系统App和来自Cydia的App,不包括App Store App.越狱的过程把/Applications变成了一个符号链接,实际指向/var/stash/App

Linux netfilter 学习笔记 之十二 ip层netfilter的NAT模块代码分析

本节主要是分析NAT模块相关的hook函数与target函数,主要是理清NAT模块实现的原理等. 1.NAT相关的hook函数分析 NAT模块主要是在NF_IP_PREROUTING.NF_IP_POSTROUTING.NF_IP_LOCAL_OUT.NF_IP_LOCAL_IN四个节点上进行NAT操作,在上一节中我们知道nat表中只有PREROUTING.POSTROUTING.LOCAL_OUT三条链,而没有NF_IP_LOCAL_IN链,所以不能创建在LOCAL_IN hook点的SNAT

boost asio io_service学习笔记

构造函数 构造函数的主要动作就是调用CreateIoCompletionPort创建了一个初始iocp. Dispatch和post的区别 Post一定是PostQueuedCompletionStatus并且在GetQueuedCompletionStatus 之后执行. Dispatch会首先检查当前thread是不是io_service.run/runonce/poll/poll_once线程,如果是,则直接运行. poll和run的区别 两者代码几乎一样,都是首先检查是否有outstan

孙鑫视频VC++深入详解学习笔记

Lesson1: Windows程序运行原理及程序编写流程 Lesson2: 掌握C++基本语法 Lesson3: MFC框架程序剖析 Lesson4: 简单绘图 Lesson5: 文本编程 Lesson6: 菜单编程 Lesson7: 对话框编程 Lesson9: 定制应用程序的外观 Lesson10: 绘图控制 Lesson11 图形的保存和重绘 Lesson12 文件操作 Lesson 13: 文档串行化 Lesson14 网络编程 Lesson 15 多线程 Lesson 16 线程同步

AM335x(TQ335x)学习笔记——挂载Ramdisk

上篇文章中我们已经可以通过u-boot启动内核了.可是没有可以启动成功,从内核的log中可以看出.内核启动失败的原因是没有挂载到root文件系统,本文将使用busybox制作根文件系统并打包成ramdisk供u-boot启动内核使用. (1)制作根文件系统 使用busybox构建根文件系统的步骤能够參考本博客的另外一篇文章.该文章链接例如以下: S5PV210(TQ210)学习笔记--内核移植与文件系统构建 须要补充的是,文章"S5PV210(TQ210)学习笔记--内核移植与文件系统构建&qu

Git学习笔记整理

Git学习笔记 1.安装Git 注意git config命令的--global参数,用了这个参数,表示你这台机器上所有的Git仓库都会使用这个配置 $ git config --global user.name "Your Name" $ git config --global user.email "[email protected]" 2.创建版本库-repository $ mkdir learngit $ cd learngit $ pwd /Users/m

vector 学习笔记

vector 使用练习: /**************************************** * File Name: vector.cpp * Author: sky0917 * Created Time: 2014年04月27日 11:07:33 ****************************************/ #include <iostream> #include <vector> using namespace std; int main

Caliburn.Micro学习笔记(一)----引导类和命名匹配规则

Caliburn.Micro学习笔记(一)----引导类和命名匹配规则 用了几天时间看了一下开源框架Caliburn.Micro 这是他源码的地址http://caliburnmicro.codeplex.com/ 文档也写的很详细,自己在看它的文档和代码时写了一些demo和笔记,还有它实现的原理记录一下 学习Caliburn.Micro要有MEF和MVVM的基础 先说一下他的命名规则和引导类 以后我会把Caliburn.Micro的 Actions IResult,IHandle ICondu