程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> C# >> C#入門知識 >> windows函數鉤子實現

windows函數鉤子實現

編輯:C#入門知識

  要求要了解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

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved