1. 程式人生 > >windows鉤子 Hook示例

windows鉤子 Hook示例

結果 port func 鉤子 cat back 卸載 恢復 fun

1.首先編寫一個 win32 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; }

在def文件添加顯式導出: (沒找到def文件需要添加)

LIBRARY
DESCRIPTION "ADD LA
" EXPORTS add @1;

2.編寫調用此dll的主程序 新建基於對話框的MFC工程

在dlg頭文件裏添加聲明:

#include <windef.h>
public:
 HINSTANCE hAddDll;
 typedef int (WINAPI*AddProc)(int a,int b);
 AddProc add;

在程序入口 編寫加載函數:

if (hAddDll==NULL)
  hAddDll=::LoadLibrary("add.dll");

 add=(AddProc)::GetProcAddress(hAddDll,"add");

添加一個按鈕函數 調用:

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

到這裏運行主程序 就會看到。彈窗 1+2 = 3的結果。

3.編寫hook dll 新建一個MFC dll 工程。

 在InitInstance函數中添加:

 hinst=::AfxGetInstanceHandle();
 DWORD dwPid=::GetCurrentProcessId();
 hProcess=OpenProcess(PROCESS_ALL_ACCESS,0
,dwPid); //調用註入函數 Inject(); return CWinApp::InitInstance();

所有的聲明:

#pragma data_seg("SHARED")
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 變量定義

//函數定義
void HookOn();
void HookOff(); //關閉鉤子
LRESULT CALLBACK MouseProc(int nCode,WPARAM wParam,LPARAM lParam); //鼠標鉤子函數
void Inject(); //具體進行註射,替換入口的函數
int WINAPI Myadd(int a,int b); //我們定義的新的add()函數
BOOL InstallHook(); //安裝鉤子函數
void UninstallHook(); //卸載鉤子函數

聲明函數的實現:

LRESULT CALLBACK MouseProc(int nCode,WPARAM wParam,LPARAM lParam)
{
    LRESULT RetVal= CallNextHookEx(hhk,nCode,wParam,lParam);
    return RetVal;
}

BOOL InstallHook()
{

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

void UninstallHook()
{
    ::UnhookWindowsHookEx(hhk);
}



    void Inject()
{
    if (m_bInjected==false)
    { 

    m_bInjected=true;


    HMODULE hmod=::LoadLibrary("add.dll");
    add=(AddProc)::GetProcAddress(hmod,"add");
    pfadd=(FARPROC)add;

    if (pfadd==NULL)
    {
        AfxMessageBox("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(); //可以開啟鉤子了
 }
}


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


int WINAPI Myadd(int a,int b)
{
    //截獲了對add()的調用,我們給a,b都加1
    a=a+1;
    b=b+1;

    HookOff();//關掉Myadd()鉤子防止死循環

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

    HookOn();//開啟Myadd()鉤子

    return ret;
}

在def文件 添加顯式導出:

 InstallHook  
 MouseProc
 Myadd
 UninstallHook 

hook dll 就完成了。

4.回到主程序 添加2個按鈕 一個註入 一個卸載:

註入:

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

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

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

卸載:

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

運行主程序:

計算:顯示1+2 =3

註入:顯示 1+2=5

完。

有任何不明白的地方歡迎騷擾:0x7317AF28

windows鉤子 Hook示例