• 博客园logo
  • 会员
  • 周边
  • 众包
  • 新闻
  • 博问
  • 闪存
  • 赞助商
  • Chat2DB
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录
Fcoding_狂人
自由 编码 Fcoding
博客园    首页    新随笔    联系   管理     

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

  

posted @ 2012-10-10 15:18  Fcoding_狂人  阅读(2721)  评论(0)    收藏  举报
刷新页面返回顶部
博客园  ©  2004-2025
浙公网安备 33010602011771号 浙ICP备2021040463号-3