windows函数钩子实现

  要求要了解PE文件结构,熟悉基本的windowsAPI。下面程序把原来需要调用user32.dll中的MessageBoxA函数用自己实现的MyMessageBox代替,也就是一个重定向的功能。

 

[cpp]
// NormalProject.cpp : Defines the entry point for the application. 
// 
 
#include "stdafx.h" 
#include <windows.h> 
#include "NormalProject.h" 
#include "KPEFile.h" 
 
int WINAPI MyMessageA(HWND hWnd, LPCSTR pText, LPCSTR pCaption, 
                      UINT uType); 
 
int APIENTRY _tWinMain(HINSTANCE hInstance, 
                       HINSTANCE hPrevInstance, 
                       LPTSTR    lpCmdLine, 
                       int       nCmdShow) 

    KPEFile pe(hInstance); 
 
    pe.SetImportAddress("user32.dll","MessageBoxA", 
        (FARPROC)MyMessageA); 
 
    MessageBoxA(NULL,"Test","SetImportAddress",MB_OK); 

 
int WINAPI MyMessageA(HWND hWnd, LPCSTR pText, LPCSTR pCaption, 
                      UINT uType) 

    WCHAR wText[MAX_PATH]; 
    WCHAR wCaption[MAX_PATH]; 
 
    MultiByteToWideChar(CP_ACP,MB_PRECOMPOSED,pText,-1,wText,MAX_PATH); 
    wcscat(wText,L"-intercepted"); 
 
    MultiByteToWideChar(CP_ACP,MB_PRECOMPOSED,pCaption,-1,wCaption,MAX_PATH); 
    wcscat(wCaption,L"-intercepted"); 
 
    return MessageBoxW(hWnd,wText,wCaption,uType); 

      接下来是KPEFile.h

[cpp] view plaincopy
#pragma once 
 
class KPEFile 

    const char * m_pModule; 
    PIMAGE_DOS_HEADER m_pDOSHeader; 
    PIMAGE_NT_HEADERS m_pNTHeader; 
public: 
    KPEFile(HMODULE hModule); 
    ~KPEFile(void); 
 
    const char * RVA2Ptr(unsigned rva)  
    { 
        if ((m_pModule!=NULL)&&rva) 
        { 
            return m_pModule+rva; 
        } 
        else 
        { 
            return NULL; 
        } 
    } 
    const void * GetDirectory(int id); 
    PIMAGE_IMPORT_DESCRIPTOR GetImportDescriptor(LPCSTR pDllName); 
    const unsigned * GetFunctionPtr(PIMAGE_IMPORT_DESCRIPTOR pImport, 
        LPCSTR pProcName); 
 
    FARPROC SetImportAddress(LPCSTR pDllName, LPCSTR pProcName, FARPROC pNewProc); 
}; 
以及实现代码:

[cpp] 
#include "StdAfx.h" 
#include "KPEFile.h" 
 
 
KPEFile::KPEFile(HMODULE hModule) 

    m_pModule = (const char *)hModule; 
 
    if (IsBadReadPtr(m_pModule, sizeof(IMAGE_DOS_HEADER))) 
    { 
        m_pDOSHeader = NULL; 
        m_pNTHeader = NULL; 
    } 
    else 
    { 
        m_pDOSHeader = (PIMAGE_DOS_HEADER)m_pModule; 
 
        if (IsBadReadPtr(RVA2Ptr(m_pDOSHeader->e_lfanew),sizeof(IMAGE_NT_HEADERS))) 
        { 
            m_pNTHeader = NULL; 
        } 
        else 
        { 
            m_pNTHeader = (PIMAGE_NT_HEADERS)RVA2Ptr(m_pDOSHeader->e_lfanew); 
        } 
    } 

 
KPEFile::~KPEFile(void) 


 
const void * KPEFile::GetDirectory(int id) 

    return RVA2Ptr(m_pNTHeader->OptionalHeader.DataDirectory[id].VirtualAddress); 

 
PIMAGE_IMPORT_DESCRIPTOR KPEFile::GetImportDescriptor(LPCSTR pDllName) 

    PIMAGE_IMPORT_DESCRIPTOR pImport = (PIMAGE_IMPORT_DESCRIPTOR)GetDirectory(IMAGE_DIRECTORY_ENTRY_IMPORT); 
     
    if ( pImport == NULL) 
    { 
        return NULL; 
    } 
    while(pImport->FirstThunk) 
    { 
        if (stricmp(pDllName,RVA2Ptr(pImport->Name))==0) 
        { 
            return pImport; 
        } 
        pImport++; 
    } 
    return NULL; 

 
const unsigned * KPEFile::GetFunctionPtr(PIMAGE_IMPORT_DESCRIPTOR pImport, LPCSTR pProcName) 

    PIMAGE_THUNK_DATA pThunk; 
 
    pThunk = (PIMAGE_THUNK_DATA)RVA2Ptr(pImport->OriginalFirstThunk); 
 
    for (int i =0; pThunk->u1.Function; i++) 
    { 
        bool match; 
        if (pThunk->u1.Ordinal & 0x80000000) 
        { 
            match = (pThunk->u1.Ordinal&0xFFFF) == ((DWORD)pProcName); 
        } 
        else 
        { 
            match = stricmp(pProcName,RVA2Ptr((unsigned)pThunk->u1.AddressOfData)+2) == 0; 
        } 
        if (match) 
        { 
            return (unsigned*)RVA2Ptr(pImport->FirstThunk)+i; 
        } 
        pThunk++; 
    } 
    return NULL; 

 
FARPROC KPEFile::SetImportAddress(LPCSTR pDllName, LPCSTR pProcName, FARPROC pNewProc) 

    PIMAGE_IMPORT_DESCRIPTOR pImport = GetImportDescriptor(pDllName); 
    if (pImport) 
    { 
        const unsigned * pfn = GetFunctionPtr(pImport,pProcName); 
        if (IsBadReadPtr(pfn, sizeof(DWORD))) 
        { 
            return NULL; 
        } 
        FARPROC oldproc = (FARPROC) * pfn; 
        DWORD dwWritten; 
        WriteProcessMemory(GetCurrentProcess(),(void *)pfn, 
            &pNewProc, sizeof(DWORD), &dwWritten);  //改变符号指向的地址,实现钩子目的。 
        return oldproc; 
    } 
    else 
    { 
        return NULL; 
    } 

作者:eagleatustb
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Windows钩子函数是一种Windows API机制,它允许程序在操作系统中拦截和监视特定事件或消息。这些事件或消息可以是键盘、鼠标、消息队列等。钩子函数通常用于记录用户输入,或者在特定条件下触发自定义操作。 实现Windows钩子函数需要以下步骤: 1. 定义钩子函数 钩子函数是一个回调函数,当特定事件或消息发生时,操作系统将调用该函数钩子函数需要根据钩子类型和事件类型进行定义,例如键盘钩子函数可以监视按键事件,鼠标钩子函数可以监视鼠标事件等。 2. 安装钩子 安装钩子需要使用`SetWindowsHookEx`函数。该函数需要三个参数:钩子类型、钩子函数地址、以及钩子函数所属进程的句柄。钩子类型可以是全局钩子或局部钩子,具体取决于监视的事件或消息。 3. 卸载钩子 卸载钩子需要使用`UnhookWindowsHookEx`函数。该函数需要一个参数,即之前安装钩子时返回的句柄。 下面是一个示例键盘钩子函数实现: ```c++ LRESULT CALLBACK KeyboardHook(int nCode, WPARAM wParam, LPARAM lParam) { if (nCode >= 0) { // 拦截到键盘事件 PKBDLLHOOKSTRUCT p = (PKBDLLHOOKSTRUCT)lParam; if (wParam == WM_KEYDOWN) { // 按键按下事件 // 处理按键事件 } } return CallNextHookEx(NULL, nCode, wParam, lParam); // 调用下一个钩子 } int main() { HHOOK hook = SetWindowsHookEx(WH_KEYBOARD_LL, KeyboardHook, NULL, 0); // 安装键盘钩子 // ... UnhookWindowsHookEx(hook); // 卸载键盘钩子 return 0; } ``` 在上面的示例中,`KeyboardHook`函数是一个键盘钩子函数,它拦截键盘事件并进行处理。在`main`函数中,使用`SetWindowsHookEx`函数安装了一个全局键盘钩子,并使用`UnhookWindowsHookEx`函数卸载了该钩子
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值