『楼 主』:
HOOK API ABOUT C++ PROGRAM
使用 LLM 解释/回答一下
#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 ;
}
```cpp
#include
// Define the API hooking item structure
typedef struct _HOOK_ITEM {
DWORD dwAddr; // Address where the IAT entry is located
DWORD dwOldValue; // Original function address of the IAT entry
DWORD dwNewValue; // New function address of the IAT entry
} HOOK_ITEM, *PHOOK_ITEM;
HOOK_ITEM HookItem = {0}; // Define the IAT entry to save the IAT information of MessageBoxA
// Define the function prototype of MessageBoxA
typedef int (WINAPI* PFNMessageBoxA)(HWND hWnd, LPCSTR lpText, LPCSTR lpCaption, UINT uType);
// Define the implementation function to redirect API
BOOL WINAPI RedirectApi(PCHAR pDllName, PCHAR pFunName, DWORD dwNewProc, PHOOK_ITEM pItem);
// Custom MessageBoxA function
// Realize monitoring of input and output parameters of the original MessageBoxA, and even cancel the call
int WINAPI NEW_MessageBoxA(HWND hWnd, LPCSTR lpText, LPCSTR lpCaption, UINT uType)
{
// Here you can observe/modify the call parameters, and even cancel the call and return directly.
// ……
// Get the original function address
PFNMessageBoxA pfnMessageBoxA = (PFNMessageBoxA)HookItem.dwOldValue;
// Output test information,
// If you call MessageBoxA directly here, it will enter an infinite loop
pfnMessageBoxA(hWnd, "This is the message box in the API redirection process", "Test", 0);
// Call the original function
int ret = pfnMessageBoxA(hWnd, lpText, lpCaption, uType);
// Here you can view/modify the return value of the original function call
// ……
return ret;
}
int WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
// Redirect API
if (!RedirectApi("USER32.dll", "MessageBoxA", (DWORD)NEW_MessageBoxA, &HookItem))
OutputDebugStringA("RedirectApi failed!");
else
OutputDebugStringA("RedirectApi success!");
MessageBoxA(0, "Normal message box", "Test", 0);
return 0;
}
// Implement API redirection
// Parameter pDllName: DLL name where the target API is located
// Parameter pFunName: Target API name
// Parameter dwNewProc: Address of the custom function
// Parameter pItem: Used to save IAT entry information
BOOL WINAPI RedirectApi(PCHAR pDllName, PCHAR pFunName, DWORD dwNewProc, PHOOK_ITEM pItem)
{
// Check if parameters are valid
if (pDllName == NULL || pFunName == NULL || !dwNewProc || !pItem)
return FALSE;
// Check if the target module exists
char szTempDllName = {0};
DWORD dwBaseImage = (DWORD)GetModuleHandle(NULL);
if (dwBaseImage == 0)
return FALSE;
// Get the pointer to the PE file header information
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);
// Traverse the import table
PIMAGE_THUNK_DATA pThunk, pIAT;
PIMAGE_IMPORT_DESCRIPTOR pIID = (PIMAGE_IMPORT_DESCRIPTOR)(dwBaseImage + pOptionalHeader->DataDirectory.VirtualAddress);
while (pIID->FirstThunk)
{
// Check if it is the target module
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;
// Traverse the IAT
DWORD dwThunkValue = 0;
while ((dwThunkValue = *((DWORD*)pThunk)) != 0)
{
if ((dwThunkValue & IMAGE_ORDINAL_FLAG32) == 0)
{
// Check if it is the target function
if (strcmp((PCHAR)(dwBaseImage + dwThunkValue + 2), pFunName) == 0)
{
// Fill in the function redirection information
pItem->dwAddr = (DWORD)pIAT;
pItem->dwOldValue = *((DWORD*)pIAT);
pItem->dwNewValue = dwNewProc;
// Modify the IAT entry
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;
}
```
|