zoukankan      html  css  js  c++  java
  • vc++HOOK API编程必知必会

    #include
     
     // 定义API挂接项结构 
     typedef struct _HOOK_ITEM { 
     DWORD dwAddr ;   // IAT项所在地址 
     DWORD dwOldValue ;  // IAT项的原始函数地址 
     DWORD dwNewValue ;  // IAT项的新函数地址 
     } HOOK_ITEM, *PHOOK_ITEM ; 
     HOOK_ITEM HookItem = {0} ; // 定义IAT项,用于保存MessageBoxA的IAT项信息
     
     // 定义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 ; 
     }
     
    

      

  • 相关阅读:
    InfoPath 发布表单到SharePoint库报错
    在log4net中控制nhibernate输出
    微信扫一扫(wx.scanQRCode)功能新手可能遇到的问题
    3.Zookeeper的安装和配置(集群模式)
    1.配置HDFS HA (高可用)
    2.Zookeeper工作原理(详细)
    1.Zookeeper 定义与工作原理
    js 获取元素的几种方法
    弹出层居中
    XUACompatible
  • 原文地址:https://www.cnblogs.com/FCoding/p/2718347.html
Copyright © 2011-2022 走看看