在 Windows® 中,DLL 所导出的函数可以替换为其他可提供相同签名的自定义函数。该技术称为“挂钩”。它通过更改 DLL 的导入地址表 (IAT) 内部的函数地址指针来工作。每个被导入的 API 都在 IAT 中具有它自己的保留位置。在 IAT 中,导入函数的地址由 Windows 加载程序写入。在模块加载以后,IAT 就包含在调用导入的 API 时调用的地址。
我的挂钩函数包含在 HookSupport 类中,该类作为与本文关联的代码下载的一部分,可在 MSDN_Magazine Web 站点上得到。该类上最重要的方法是 HookImportFunctionsByName,它采用将在其中挂钩导入函数的模块句柄、要挂钩的模块的名称、包含要挂钩的函数名称的结构数组,以及新的自定义函数过程地址。John Robbins(MSDN Magazine 的 Bugslayer 专栏作家)在使用 Win32_ 的时期经常说明如何挂钩函数。我将使用 John 在他的调试著作 Debugging Applications for Microsoft .NET and Microsoft Windows (Microsoft Press, 2003) 中介绍的技术。
正如前面提到的那样,ASP 客户端无法使用 .NET 异常的原因是,该异常最初被使用 SetErrorInfo 设置为线程的错误对象;随后,当脚本运行库调用 GetErrorInfo 以生成 IDispatch Invoke 方法所必需的 EXCEPINFO 结构时,该异常被清除。在理论上,如果可以在另一个自定义函数中挂钩和替换 SetErrorInfo 函数,则在脚本运行库调用 GetErrorInfo 以清除 .NET 异常接口指针之前,可以使用 EMAB 提取和发布它。
SetErrorInfo 函数定义在 OLEAUT32 模块中。遗憾的是,尽管该模块是从 mscorwks/mscorsvr 中加载的,但无法容易地挂钩它,因为 OLEAUT32 模块在 mscorwks/mscorsvr 的导入地址表中不存在(该模块只存在于单独的延迟加载 IAT 中)。这是因为该模块被延迟加载:在运行时,LoadLibrary 和 GetProcAddress 被调用以解析 SetErrorInfo 的函数地址。得到的地址随后被存储在延迟加载 IAT 中,以便将来的调用能够直接转向 API。
尽管挂钩依赖于对模块的导入表进行修改,但对于延迟加载的 DLL 而言,在模块内部对该函数进行首次调用之前,必须完成这一工作。由于您不显式加载 mscorwks.dll,因此当您开始挂钩时,您无法确保尚未对 SetErrorInfo 进行首次调用。
延伸阅读
文章来源于领测软件测试网 https://www.ltesting.net/