表,由输入地址表再跳转到DLL真正的函数
入口。例如:
图2 对MessageBox()的调用跳转到输入地址表,从输入地址表再跳转到Mess
ageBox函数
IMAGE—IMPORT—DESCRIPTOR和IMAGE—THUNK—DATA分别对应于DLL和函数。
它们是PE
文件的输入地址表的格式(数据结构参见winnt.h)。
BOOL ChangeFuncEntry(HMODULE hmodule)
{ PIMAGE—DOS—HEADER pDOSHeader;
PIMAGE—NT—HEADERS pNTHeader;
PIMAGE—IMPORT—DESCRIPTOR pImportDesc;
/get system functions and my functions′entry/
pSysFunc1=(DWORD)GetProcAddress(GetModuleHandle(″gdi32.dll″),″T
extOutA″);
pMyFunc1= (DWORD)GetProcAddress(GetModuleHandle(″hookdll.dll″),″
MyTextOutA″);
pDOSHeader=(PIMAGE—DOS—HEADER)hmodule;
if (IsBadReadPtr(hmodule, sizeof(PIMAGE—NT—HEADERS)))
return FALSE;
if (pDOSHeader-〉e—magic != IMAGE—DOS—SIGNATURE)
return FALSE;
pNTHeader=(PIMAGE—NT—HEADERS)((DWORD)pDOSHeader+(DWORD)pDOSHead
er-〉e—
lfanew);
if (pNTHeader-)Signature != IMAGE—NT—SIGNATURE)
return FALSE;
pImportDesc = (PIMAGE—IMPORT—DESCRIPTOR)((DWORD)hmodule+(DWORD)
pNTHeader
-)OptionalHeader.DataDirectory
[IMAGE—DIRECTORY—ENTRY—IMPORT].VirtualAddress);
if (pImportDesc == (PIMAGE—IMPORT—DESCRIPTOR)pNTHeader)
return FALSE;
while (pImportDesc-)Name)
{ PIMAGE—THUNK—DATA pThunk;
strcpy(buffer,(char)((DWORD)hmodule+(DWORD)pImportDesc-)Name))
;
CharLower(buffer);
if(strcmp(buffer,"gdi32.dll"))
{ pImportDesc++;
continue;
}else
{ pThunk=(PIMAGE—THUNK—DATA)((DWORD)hmodule+(DWORD)pImportDesc-)Fi
rstThunk);
while (pThunk-)u1.Function)
{ if ((pThunk-)u1.Function) == pSysFunc1)
{ VirtualProtect((LPVOID)(&pThunk-)u1.Function),
sizeof(DWORD),PAGE—EXECUTE—READWRITE, &dwProtect);
(pThunk-)u1.Function)=pMyFunc1;
VirtualProtect((LPVOID)(&pThunk-)u1.Function), sizeof(DWORD),dw
Protect,&temp); }
pThunk++; } return 1;}}}
替换了输入地址表中TextOutA的入口为MyTextOutA后,截获系统函数调用的
主要部分已经完成,当
一个被注入进程调用TextOutA时,其实调用的是MyTextOutA,只需在MyTextOutA
中显示传进来的字符
串,再交给TextOutA处理即可。