分类

链接

2011 年 6 月
 12345
6789101112
13141516171819
20212223242526
27282930  

近期文章

热门标签

新人福利,免费薅羊毛

现在位置:    首页 > C/C++, Others > 正文
共享办公室出租
api hook(二)
C/C++, Others 暂无评论 阅读(2,282)

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

}

============ 欢迎各位老板打赏~ ===========

本文版权归Bruce's Blog所有,转载引用请完整注明以下信息:
本文作者:Bruce
本文地址:api hook(二) | Bruce's Blog

发表评论

留言无头像?