#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项,用于保存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 on 2009-04-14 11:17  Yincheng  阅读(293)  评论(0编辑  收藏  举报