挂钩Windows API(5) typedef strUCt _IMAGE_THUNK_DATA { union { PBYTE ForwarderString; PDWord Function; DWORD Ordinal; PIMAGE_IMPORT_BY_NAME AddressOfData; } ; } IMAGE_THUNK_DATA,*PIMAGE_THUNK_DATA; typedef struct _IMAGE_IMPORT_DESCRIPTOR { union { DWORD CharacteristiCS; PIMAGE_THUNK_DATA OriginalFirstThunk; } ; DWORD TimeDateStamp; DWORD ForwarderChain; DWORD Name; PIMAGE_THUNK_DATA FirstThunk; } IMAGE_IMPORT_DESCRIPTOR,*PIMAGE_IMPORT_DESCRIPTOR; IMAGE_IMPORT_DESCRIPTOR里的Name成员变量是模块名字的指针。如果我们想要挂钩某个函数比如是来自kernel32.dll我们就在导入表里找属于名字kernel32.dll的描述符号。我们先调用ImageDirectoryEntryToData然后找到名字是"kernel32.dll"的描述符号(可能不只一个描述符号是这个名字),最后我们在这个模块的记录里所有函数的列表里找到我们想要的函数(函数地址通过GetProcAddress函数获得)。如果我们找到了就必须用VirtualProtect函数来改变内存页面的保护属性,然后就可以在内存中的这些部分写入代码了。在改写了地址之后我们要把保护属性改回来。在调用VirtualProtect之前我们还要先知道有关页面的信息,这通过VirtualQuery来实现。我们可以加入一些测试以防某些函数会失败(比方说如果第一次调用VirtualProctect就失败了,我们就没办法继续)。