20171012WindowsPrj08_04IAT Hook封装

IAT Hook:

IAT Hook注意点:

1:在之前说的, 在自己挂钩的函数(MyMessageBoxW)中,执行完自己的代码后,调用return MessageBoxW,这样会形成Hook的递归,导致程序一直在这里Hook。解决这个问题:在挂钩的时候, 先将USER32.dll映射内存位置的MessageBoxW的地址记录下来,在调用MyMessageBoxW后,return的地方再接着记录的地址执行,相当于是在执行被Hook的MessageBoxW,只不过在执行前先去自己写的MyMessageBoxW中走了一圈,这样,就可以将自己的代码插入到程序的执行流程,而不影响程序本身执行。
    特别注意: 平时,我们正常调用Windows的API的时候,程序都会在导入表里面找到这个函数的地址,然后调用,因此,我们更改这个地址后可以改变调用的函数, 但是,我们通过函数指针调用一个函数的话,相当于是已知了函数的位置,因此,就不会再在IAT表导入表里面去找这个函数的地址了,这样,就不会Hook到调用的这个函数了, 所以,我们在更改IAT表导入表里面函数地址的时候,应该记录原来的地址,在自己的函数里面在通过这个地址调用原来的函数,达到不影响程序执行的目的,由此也可以知道,一个好的Hook库,不仅要Hook需要Hook的这个函数,还要Hook的函数有: LoadLibraryA,LoadLibraryW,LoadLibraryExA,LoadLibraryExW,GetProcAddress五个函数, 前面四个是为了确保进程加载的每个DLL的时候,对这些DLL都Hook, 第五个函数,不管是否全部DLL和EXE都挂钩,他都可以取到原始函数的地址,因此,也需要对这个函数挂钩,保证其取到的是我们写的函数的地址,这是IAT Hook必须挂钩的五个函数。
2:按这样的挂钩,只能挂当前程序自己的钩,而且,当程序有多个DLL里面使用了MessageBoxW,我们还只能挂到当前这个模块(EXE)的钩,局限性非常大。
    例如,在main中挂钩后,再使用LoadLibrary,加载其他的DLL,那么他的钩就没挂上了,直接#pragma comment (lib, "MessageBoxWDllDemo.lib")这样加载的也是不行的,不管是在OnHook前还是后加载,都不行,除非,单独对其进行设置Hook,如下:
int _tmain(int argc, _TCHAR* argv[])
{
	//MessageBoxW(nullptr, L"123", nullptr, MB_OK);
	SetHook(nullptr, "MessageBoxW", "USER32.dll", "MyMessageBoxW");
	MessageBoxW(nullptr, L"123", nullptr, MB_OK);
	SetHook("MessageBoxWDllDemo.dll", "MessageBoxW", "USER32.dll", "MyMessageBoxW");
	Call();//就是MessageBoxWDllDemo.dll中一个调用MessageBoxW的函数
	SetHook("APIHook.dll", "MessageBoxW", "USER32.dll", "MyMessageBoxW");
	MessageBoxW(nullptr, L"123", nullptr, MB_OK);//直接return MessageBoxW的话,就会无限递归,需要调用原始函数的地址。

	return 0;
}

获取导入表:

1:在之前获取导入表的时候,我们是通过从开头往后找的方式,是为了熟悉PE结构,实际上,Windows提供了API可以直接取得里面的结构体:
    ImageDirectoryEntryToData:位于Desktop technologies -> Diagnostics -> Debugging and Error Handling里面,实际上,他的本质也是通过计算偏移来找到的。
2:ImageDirectoryEntryToData函数原型:
PVOID WINAPI ImageDirectoryEntryToData(
  _In_  PVOID   Base,
  _In_  BOOLEAN MappedAsImage,
  _In_  USHORT  DirectoryEntry,
  _Out_ PULONG  Size
);

    函数参数:
    1:Base:Image基地址,就是HModule模块的地址,可以使用GetModuleHandle来获取。
    2:如果此参数为TRUE,则系统将该文件映射为图像。如果标志为FALSE,则该文件将通过MapViewOfFile函数映射为数据文件 。
    3:需要获取的条目的索引,可以取一些值,详看 MSDN
    4:指向一个表示目录条目数据大小的变量的指针。
    头文件:该函数需要包含头文件#include "ImageHlp.h",#pragma comment(lib, "ImageHlp.lib");

封装IAT Hook:

1:IAT Hook封装类里面必要的方法和成员变量:
    1:需要Hook的模块名:对哪个模块进行Hook,一般对一个进程的所有模块都Hook
    2:需要Hook的方法名和方法所在模块:Hook哪个方法,以及这个方法所在的模块名,也可以直接找,不要模块名,实际上可以通过方法名得到模块名。
    3:新方法的地址:替换的方法地址。
    4:挂钩函数:设置Hook的方法。
    5:卸载挂钩函数:卸载Hook的方法。
2:方法名获取模块名:
    通过GetProcAddr可以获取到方法名的地址,这个地址是属于一个模块的,然后通过查询虚拟地址得到BaseAddr,就是ModuleHandle了。






猜你喜欢

转载自blog.csdn.net/qq_31622605/article/details/78219878