提问人:Pieter Jansen 提问时间:11/6/2023 最后编辑:Brian Tompsett - 汤莱恩Pieter Jansen 更新时间:11/6/2023 访问量:76
Win32 API 挂钩/导入地址表
Win32 API hooking/Import address table
问:
任何人都可以阅读这篇文章并纠正我的错误/回答我的问题吗?这是我到目前为止的理解:
当可执行文件加载到内存中时,编译时已知的导入将加载到内存中。指向这些函数的指针存储在导入地址表中,当进程想要调用函数时,它必须从导入地址表中检索指针(我了解 IAT、INT、H/N 表等之间的关系)。
当函数在运行时加载并且动态链接器检索指针时;因此,例如,当进程调用 MessageBoxA 时,操作系统加载程序会在内存中加载 DLL Kernel32 并返回指向此特定函数的指针。到目前为止,这部分是正确的吗?LoadLibrary
GetProcAddress()
据我所知,操作系统根据定义加载的第一个库是 ntdll.dll,第二个是更抽象的包装器 Kernel32.dll。我想知道什么..当进程在运行时调用 MessageBoxA 或 CreateFileA 时,DLL 不需要加载到内存中吧?因为这些函数是已经加载的库的一部分,即 Kernel32。
动态链接器是否将指向动态加载函数的指针存储在某种缓存中,或者..?据我所知,它没有更新导入地址表,那么当进程再次调用函数时会发生什么,是需要再次调用解析虚拟地址还是有更有效的方法?
GetProcAddress
当我想钩接动态加载的函数时,我是否需要在运行时钩接并使用跳转指令将返回指针更改为我的填充函数(并存储原始函数指针以调用原始函数/之后使用原始参数)。
GetProcAddress
答:
当进程想要调用函数时,它必须从导入地址表中检索指针
检索听起来有点麻烦,但是的:对导入函数的调用被编译为对 IAT 的调用,其中有一个 JMP [地址] 指令,在加载库时,该指令会使用实际的函数地址进行修补。
当在运行时使用 LoadLibrary 和 GetProcAddress() 加载函数时,动态链接器将检索指针;因此,例如,当进程调用 MessageBoxA 时,操作系统加载程序会在内存中加载 DLL Kernel32 并返回指向此特定函数的指针。
LoadLibrary
将 DLL 加载到内存中。 返回指向特定导出函数的指针。不是上面那样的存根,而是模块中实际函数的地址。GetProcAddress
当进程在运行时调用 MessageBoxA 或 CreateFileA 时,DLL 不需要加载到内存中吧?
MessageBoxA
实际上驻留在 user32.dll 中,但对于 CreateFileA,您是正确的,kernel32.dll 已经加载。
动态链接器是否将指向动态加载函数的指针存储在某种缓存中,或者..?
加载的模块的地址记录在内核对象中。据我所知,单个函数的地址没有被缓存。
据我所知,它不会更新import addres表,那么当进程再次调用函数时会发生什么,是否需要再次调用GetProcAddress来解析虚拟地址,或者有没有更有效的方法?
通常,如果您需要多次使用变量,您会将返回的内容存储在变量中。GetProcAddress
当我想钩接动态加载的函数时,我是否需要在运行时钩接GetProcAddress,并使用跳转指令更改返回指针到我的钩子函数(并存储原始函数指针以调用原始函数/之后使用原始参数)。
是的,没错。
评论
GetProcAddress
GetProcAddress
GetProcAddress
评论