zoukankan      html  css  js  c++  java
  • api hook(二)

    #include <windows.h>

     

    // 定义API挂接项结构

    typedef struct _HOOK_ITEM {

     DWORD dwAddr ;   // IAT项所在地址

     DWORD dwOldValue ;  // IAT项的原始函数地址

     DWORD dwNewValue ;  // IAT项的新函数地址

    } HOOK_ITEM, *PHOOK_ITEM ;

    HOOK_ITEM HookItem = {0} ; // 定义IAT项,用于保存MessageBoxAIAT项信息

     

    // 定义MessageBoxA函数原型

    typedef int (WINAPI* PFNMessageBoxA)( HWND hWnd, LPCSTR lpText, LPCSTR lpCaption, UINT uType ) ;

     

    // 定义重定向API的实现函数

    BOOL WINAPI RedirectApi ( PCHAR pDllName, PCHAR pFunName, DWORD dwNewProc, PHOOK_ITEM pItem ) ;

     

    // 自定义的MessageBoxA函数

    // 实现对原始MessageBoxA的输入、输出参数的监控,甚至是取消调用

    int WINAPI NEW_MessageBoxA( HWND hWnd, LPCSTR lpText, LPCSTR lpCaption, UINT uType )

    {

     // 此处可以观察/修改调用参数,甚至可以取消调用直接返回。

     // ……

     

     // 取得原函数地址

     PFNMessageBoxA pfnMessageBoxA = (PFNMessageBoxA)HookItem.dwOldValue ;

     

     // 输出测试信息,

     // 如果这里直接调用MessageBoxA,就进入无限循环

     pfnMessageBoxA ( hWnd, "这是API重定向过程的消息框", "测试", 0 ) ;

     

     // 调用原函数

     int ret = pfnMessageBoxA ( hWnd, lpText, lpCaption, uType ) ;

     

     // 此处可以查看/修改调用原函数的返回值

     // ……

     

     return ret ;

    }

     

    int WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow )

    {

     // 重定向API

     if ( !RedirectApi ( "USER32.dll", "MessageBoxA", (DWORD)NEW_MessageBoxA, &HookItem ) )

      OutputDebugStringA ( "RedirectApi failed!" ) ;

     else

      OutputDebugStringA ( "RedirectApi success!" ) ;

     

     MessageBoxA ( 0, "正常消息框", "测试", 0 ) ;

     return 0 ;

    }

     

    // 实现重定向API

    // 参数pDllName:目标API所在的DLL名称

    // 参数pFunName:目标API名称

    // 参数dwNewProc:自定义的函数地址

    // 参数pItem:用于保存IAT项信息

    BOOL WINAPI RedirectApi ( PCHAR pDllName, PCHAR pFunName, DWORD dwNewProc, PHOOK_ITEM pItem )

    {

     // 检查参数是否合法

     if ( pDllName == NULL || pFunName == NULL || !dwNewProc || !pItem )

      return FALSE ;

     

     // 检测目标模块是否存在

     char szTempDllName[256] = {0} ;

     DWORD dwBaseImage = (DWORD)GetModuleHandle(NULL) ;

     if ( dwBaseImage == 0 )

      return FALSE ;

     

     // 取得PE文件头信息指针

     PIMAGE_DOS_HEADER   pDosHeader = (PIMAGE_DOS_HEADER)dwBaseImage ;

     PIMAGE_NT_HEADERS   pNtHeader = (PIMAGE_NT_HEADERS)(dwBaseImage + (pDosHeader->e_lfanew)) ;

     PIMAGE_OPTIONAL_HEADER32 pOptionalHeader = &(pNtHeader->OptionalHeader) ;

     PIMAGE_SECTION_HEADER  pSectionHeader = (PIMAGE_SECTION_HEADER)((DWORD)pNtHeader + 0x18 + pNtHeader->FileHeader.SizeOfOptionalHeader ) ;

     

     // 遍历导入表

     PIMAGE_THUNK_DATA pThunk, pIAT ;

     PIMAGE_IMPORT_DESCRIPTOR pIID = (PIMAGE_IMPORT_DESCRIPTOR)(dwBaseImage+pOptionalHeader->DataDirectory[1].VirtualAddress ) ;

     while ( pIID->FirstThunk )

     {

      // 检测是否目标模块

      if ( strcmp ( (PCHAR)(dwBaseImage+pIID->Name), pDllName ) )

      {

       pIID++ ;

       continue ;

      }

     

      pIAT = (PIMAGE_THUNK_DATA)( dwBaseImage + pIID->FirstThunk ) ;

      if ( pIID->OriginalFirstThunk )

       pThunk = (PIMAGE_THUNK_DATA)( dwBaseImage + pIID->OriginalFirstThunk ) ;

      else

       pThunk = pIAT ;

     

      // 遍历IAT

      DWORD dwThunkValue = 0 ;

      while ( ( dwThunkValue = *((DWORD*)pThunk) ) != 0 )

      {

       if ( ( dwThunkValue & IMAGE_ORDINAL_FLAG32 ) == 0 )

       {

        // 检测是否目标函数

        if ( strcmp ( (PCHAR)(dwBaseImage+dwThunkValue+2), pFunName ) == 0 )

        {

         // 填充函数重定向信息

         pItem->dwAddr  = (DWORD)pIAT ;

         pItem->dwOldValue = *((DWORD*)pIAT) ;

         pItem->dwNewValue = dwNewProc;

     

         // 修改IAT

         DWORD dwOldProtect = 0 ;

         VirtualProtect ( pIAT, 4, PAGE_READWRITE, &dwOldProtect ) ;

         *((DWORD*)pIAT) = dwNewProc ;

         VirtualProtect ( pIAT, 4, PAGE_READWRITE, &dwOldProtect ) ;

         return TRUE ;

        }

       }

     

       pThunk ++ ;

       pIAT ++ ;

      }

     

      pIID ++ ;

     }

     

     return FALSE ;

    }


  • 相关阅读:
    Unity基础:AR(增强现实)的学习
    Fire Balls 04——平台组合,场景的美化
    Fire Balls 12——UI界面的制作
    Fire Balls 11——修正游戏的BUG
    Unity使用Rider作为IDE的体验
    Unity 5 使用Roslyn编译器支持C# 7
    MySQL 5.5主从复制(Replication)
    使用libcurl的正确姿势
    U盘安装Ubuntu Server 14.04
    arguments介绍(二)
  • 原文地址:https://www.cnblogs.com/longle/p/2072874.html
Copyright © 2011-2022 走看看