Hook Function... 貌似Hacker/Cracker做的事情,不过我既不是Hacker,也不是Cracker,而是Game Programer...Game Programer,不仅要通晓图形图像,数学物理,貌似十八般武器,左道旁门都要耍一耍。今天,我也根据自己的实验过程,写一些Hook 方法,请各位大牛多批评指正。。。
本次Hook Function 的研究动因来自于对Memroy Alloction Function接管的需求;
[第一种方法]:(Override IAT),就是通常所说的Hook API,只得是对DLL中的导出函数进行Hook,Hook的方法就是重写IAT(Import Address Table)中的相应条目;
下面代码我忘记抄的哪一位的了,自己认领吧..详细解释网上很多,自己google吧,我对这个函数稍作了改进,可以挂接dll中引入的api,比如mscvr80.dll中引用的kernel32 中的API。
这种方法只适用于挂接dll中的可导出函数(如果你能找到dll对应的def文件,或者dumpbin 它就知道哪些函数是导出函数了 ),挂接msvcrt 中的函数,不能对msvcrt.dll操作(早期版本也许可以);而是对新版本crt dll,比如vc8 的 msvcr80.dll;如何有效的找到对应版本的crt dll?这个问题我还不清楚。跟踪crt source,发现_CRT_DLL_INIT是ntdll中的函数控制的...
另外,如果要注入其他进程,需要放到dll。。。
这种方法的缺点是无法挂接静态连接的函数。
void WINAPI HookOneAPI( HMODULE hInstance,LPCTSTR ModuleName,LPCTSTR ApiName,PROC NewFuction,PROC* OldFuction)
{
DWORD size;
HMODULE hModule = GetModuleHandle(ModuleName);
PROC HookAPIAddr = GetProcAddress( hModule,ApiName);
*OldFuction = HookAPIAddr;
PIMAGE_IMPORT_DESCRIPTOR pImportDesc = (PIMAGE_IMPORT_DESCRIPTOR) ImageDirectoryEntryToData (hInstance,TRUE,IMAGE_DIRECTORY_ENTRY_IMPORT,&size);
PIMAGE_IMPORT_DESCRIPTOR pImportDesc1 = pImportDesc;
if(pImportDesc == NULL)
return;
for (;pImportDesc1->Name;pImportDesc1++)
{
LPSTR pszDllName = (LPSTR)((PBYTE)hInstance + pImportDesc1->Name);
if(lstrcmpiA(pszDllName,ModuleName) == 0)
{
//break;
pImportDesc = pImportDesc1;
}
else
{
HMODULE hModule1 = GetModuleHandle(pszDllName);
HookOneAPI( hModule1,ModuleName,ApiName,NewFuction,OldFuction );
}
}
if(pImportDesc->Name == NULL)
return;
PIMAGE_THUNK_DATA pThunk = (PIMAGE_THUNK_DATA)((PBYTE)hInstance + pImportDesc->FirstThunk);//IAT
for(;pThunk->u1.Function;pThunk++)
{
PROC * ppfn= (PROC *)&pThunk->u1.Function;
if (*ppfn == HookAPIAddr)
{
MEMORY_BASIC_INFORMATION mbi;
ZeroMemory(&mbi, sizeof(MEMORY_BASIC_INFORMATION));
VirtualQuery(ppfn,&mbi,sizeof(MEMORY_BASIC_INFORMATION));
VirtualProtect(mbi.BaseAddress,mbi.RegionSize,PAGE_READWRITE,&mbi.Protect);
*ppfn = NewFuction;
DWORD dwOldProtect;
VirtualProtect(mbi.BaseAddress,mbi.RegionSize,mbi.Protect,&dwOldProtect);
return;
}
}
}
[第二种方法]:改写函数起始指令
这种方法可以有效地处理静态连接的函数,包括exe代码中的函数和exe所连接静态lib中的函数;但是对于dll所链接的静态lib函数的hook,如果没有source比较困难;除非把分析代码段多有的call指令,然后改写。
以下代码参考多任务下的数据结构与算法改编( 周伟明 著 华中科技大学出版社 ),vc8 编译测试通过。
对于静态链接的函数
HANDLE hProcess = ::GetCurrentProcess();
unsigned char buff[256];
buff[0] = 0xff;
buff[1] = 0x25;
*(DWORD*)(buff+2) = (DWORD)pfun_new_var;
DWORD write_bytes = 0;
::WriteProcessMemory( hProcess,(PROC*)lpSrcFunc,buff,6,&write_bytes );
}
//new handler for malloc
void* __cdecl malloc_new( __in size_t _Size )
{
...
}
//test code:
HMODULE handle = ::GetModuleHandle(NULL);
#ifdef _MT
# ifdef _DLL // for crt dll
HookOneAPI(handle,"msvcr80d.dll","malloc",(PROC)malloc_new,(PROC*)&malloc_old);
#else // for static crt lib
static DWORD dwNewFunc1 = (DWORD)malloc_new;
HookFunction( malloc,&dwNewFunc1 ); // don‘t use direct function addr malloc_new!
# endif
#endif
malloc(10);
如果还要恢复原函数的运行,就需要预先储存前面6个字节;在新的函数执行完以后,将修改的前6个字节恢复原样。