The PE file IMAGE_IMPORT_DESCRIPTOR structure, which holds all the information about functions imported from a specific DLL, has pointers to two arrays in the executable. These arrays are called import address tables (IATs), or sometimes thunk data arrays. The first pointer references the real IAT, which the program loader fixes up when the executable is loaded. The second pointer references the original IAT, which is untouched by the loader and lists the imported functions.
实现原理
找到PE文件的Image_Import_Descriptor结构
找到Original LAT和Real LAT.
通过要hook的函数的名字在Original LAT找到要hook的imported function在数组中的index.
保存并修改Real LAT在相应index的function address
(refer to John Robbins, BugsLayerUtil.dll)
Hooking Imported Functions by ordinal
原理和Hook Imported functions by name一样,只是是通过要hook的函数的ordinal在original LAT中找到index.
Hooking a function in this dll
当一个DLL是通过LoadLibrary载入的时候,我们无法通过hook imported function的方法的hook它中的function。有两种可能的办法处理这种情况:
case DLL_THREAD_ATTACH:
break;
case DLL_THREAD_DETACH:
break;
case DLL_PROCESS_DETACH:
if (UninstallTextoutHook())
{
WriteLog("Uninstall hook success.\n");
}else
{
WriteLog("Unintall hook failed.\n");
}
break;
}
return TRUE;
}
#define DWORD_PTR DWORD*
#define __LOCAL_SIZE 40h
#define NAKED_PROLOG() \
DWORD_PTR dwRet ; \
DWORD_PTR dwESI ; \
{ \
__asm PUSH EBP /* Set up the standard frame.*/\
__asm MOV EBP , ESP \
__asm SUB ESP , __LOCAL_SIZE /* Save room for the local */\
/* variables. */\
__asm MOV EAX , EBP /* EBP has the stack coming */\
/* into the fn. in it. */\
__asm ADD EAX , 4 /* Account for PUSH EBP */\
__asm MOV EAX , [EAX] /* Get return address. */\
__asm MOV [dwRet] , EAX /* Save return address. */\
__asm MOV [dwESI] , ESI /* Save ESI so chkesp in dbg */\
/* builds works. */\
}
// The common epilog part that can be shared between the stdcall and
// cdecl hook functions.
#define EPILOG_COMMON() \
{ \
__asm MOV ESI , [dwESI] /* Restore ESI. */\
__asm ADD ESP , __LOCAL_SIZE /* Take away local var space */\
__asm MOV ESP, EBP /* Restore standard frame. */\
__asm POP EBP \
}
//Get the hook'a address.
HMODULE hModule = GetModuleHandle(_T("HookDLL.dll"));
if (NULL == hModule)
return FALSE;
DWORD dwHookAddr = NULL;
__asm
{
mov esi, offset HookLabel;
mov edi, 0x10000000;//0x10000000 is the dll's base address.
sub esi, edi;
add esi, hModule;
mov [dwHookAddr], esi;
}
//Get the NOP's address.
DWORD dwNOPAddr = NULL;
__asm
{
mov esi, offset NOPLabel;
mov edi, 0x10000000;//0x10000000 is the dll's base address.
sub esi, edi;
add esi, hModule;
mov [dwNOPAddr], esi;
}
//Save the first 5 byte of TextOutA to g_abOriCode
__asm
{
mov esi, g_oriTextout;
lea edi, g_abOriCode;
cld;
movsd;
movsb;
}
//Write g_abOriTextout to the end of Hook function(NOP addr), then write the jmp instruction.
VirtualProtectEx(hProcess, (LPVOID)dwNOPAddr, 10, PAGE_READWRITE, &dwOldFlag);
WriteProcessMemory(hProcess, (LPVOID)dwNOPAddr, g_abOriCode, sizeof(g_abOriCode), NULL);