一个模块是否有可能调用不同模块中的函数?
我了解导入表和延迟导入表。但是还有其他选择吗?它在二进制文件中看起来如何?(在这种情况下,操作码可能是间接的,但是要跳转到的地址将驻留在何处?)
跳跃也一样吗?
我知道这有点笼统,所以一些相关阅读材料的链接也很好。
谢谢。
一个模块是否有可能调用不同模块中的函数?
我了解导入表和延迟导入表。但是还有其他选择吗?它在二进制文件中看起来如何?(在这种情况下,操作码可能是间接的,但是要跳转到的地址将驻留在何处?)
跳跃也一样吗?
我知道这有点笼统,所以一些相关阅读材料的链接也很好。
谢谢。
好消息:是的,当然有可能,而且经常这样做。我将把我的回答限制在 Windows 上。在 Linux 或其他系统中存在类似的场景,但在细节上有所不同。
首先让我们澄清一下什么是“模块”。我从你的问题中假设你的意思是“模块”是一个 DLL,例如由某些 exe 二进制文件加载和调用。这是一个“紧耦合”的场景:被调用的模块与调用模块驻留在相同的 2GB 内存虚拟地址空间中。在两个模块驻留在不同进程中的“松散耦合”场景的情况下,您需要“远程过程调用”的一种可能性,如 XML-RPC、SOAP 或 - 在 .NET 环境中 - 远程处理。还有很多其他的。以下内容适用于紧密耦合的 Windows DLL。
Case1:函数由模块导出。这很简单:
这是“正常”程序的场景。它的优点是不需要静态库来链接 DLL 的地址,并且 DLL 不需要在 exe 启动时出现。它的缺点是生成正确的函数指针有点繁琐。
Case2:函数没有被模块导出,被调用模块的基地址未知。
这是更有趣的情况,例如,您想要修补 exe 文件并调用模块 DLL 中感兴趣的函数,或者只想跳转到与模块起始地址相关的某个已知地址。
它的工作原理 - 在汇编程序和机器代码级别 - 与上述完全相同的方式,有一点困难:如何在补丁中调用“LoadLibrary”函数?这并不像乍一看那样微不足道。
“LoadLibrary”函数驻留在模块“Kernel32.dll”中,这是每个Windows程序所必需的。你可能会调用“LoadLibraryA(“Kernel32.dll”),你会看到“猫咬尾巴”的递归问题。这行不通。不要依赖kernel32.dll固定不变地址。这在 ASLR 的世界中是行不通的。
这是所有shellcode编程的普遍问题。幸运的是,有一种方法可以可靠地获取 Kernel32.dll(以及 ntdll.dll)的地址。您可能想从http://www.hick.org/code/skape/papers/win32-shellcode.pdf下载 Skape 的优秀且相当古老的论文,描述了这一点和许多其他有趣的事情。该方法在 Windows XP、Windows7 和 Windows10 中对我同样有效。Skapes 方法适用于 32 位世界。对于 64 位 Windows 中的相应解决方案,您可能需要查阅https://www.tophertimzen.com/blog/windowsx64Shellcode/(但要注意解决方案中可能存在的错误)。
玩得开心!