标题: HOOK API ABOUT C++ PROGRAM 
[打印本页]
作者: LinHQ2010     
时间: 2010-6-3 17:23    
标题: HOOK API ABOUT C++ PROGRAM
#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 ; 
}